324 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			324 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| #include "..\e2dcommon.h"
 | ||
| #include "..\e2dbase.h"
 | ||
| #include "..\e2dtool.h"
 | ||
| 
 | ||
| std::map<e2d::Resource, ID2D1Bitmap*> e2d::Image::_bitmapCache;
 | ||
| 
 | ||
| e2d::Image::Image()
 | ||
| 	: _bitmap(nullptr)
 | ||
| 	, _cropRect()
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| e2d::Image::Image(const Resource& res)
 | ||
| 	: _bitmap(nullptr)
 | ||
| 	, _cropRect()
 | ||
| {
 | ||
| 	this->open(res);
 | ||
| }
 | ||
| 
 | ||
| e2d::Image::Image(const Resource& res, const Rect& cropRect)
 | ||
| 	: _bitmap(nullptr)
 | ||
| 	, _cropRect()
 | ||
| {
 | ||
| 	this->open(res);
 | ||
| 	this->crop(cropRect);
 | ||
| }
 | ||
| 
 | ||
| e2d::Image::Image(const String & fileName)
 | ||
| 	: _bitmap(nullptr)
 | ||
| 	, _cropRect()
 | ||
| {
 | ||
| 	this->open(Resource(fileName));
 | ||
| }
 | ||
| 
 | ||
| e2d::Image::Image(const String & fileName, const Rect & cropRect)
 | ||
| 	: _bitmap(nullptr)
 | ||
| 	, _cropRect()
 | ||
| {
 | ||
| 	this->open(Resource(fileName));
 | ||
| 	this->crop(cropRect);
 | ||
| }
 | ||
| 
 | ||
| e2d::Image::~Image()
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| bool e2d::Image::open(const Resource& res)
 | ||
| {
 | ||
| 	if (res.isFile())
 | ||
| 	{
 | ||
| 		WARN_IF(res.getFileName().isEmpty(), "Image open failed! Invalid file name.");
 | ||
| 
 | ||
| 		if (res.getFileName().isEmpty())
 | ||
| 			return false;
 | ||
| 	}
 | ||
| 
 | ||
| 	if (!Image::preload(res))
 | ||
| 	{
 | ||
| 		WARN("Load Image from file failed!");
 | ||
| 		return false;
 | ||
| 	}
 | ||
| 
 | ||
| 	this->_setBitmap(_bitmapCache.at(res));
 | ||
| 	return true;
 | ||
| }
 | ||
| 
 | ||
| bool e2d::Image::open(const String & fileName)
 | ||
| {
 | ||
| 	return open(Resource(fileName));
 | ||
| }
 | ||
| 
 | ||
| void e2d::Image::crop(const Rect& cropRect)
 | ||
| {
 | ||
| 	if (_bitmap)
 | ||
| 	{
 | ||
| 		_cropRect.origin.x = std::min(std::max(cropRect.origin.x, 0.0), this->getSourceWidth());
 | ||
| 		_cropRect.origin.y = std::min(std::max(cropRect.origin.y, 0.0), this->getSourceHeight());
 | ||
| 		_cropRect.size.width = std::min(std::max(cropRect.size.width, 0.0), this->getSourceWidth() - cropRect.origin.x);
 | ||
| 		_cropRect.size.height = std::min(std::max(cropRect.size.height, 0.0), this->getSourceHeight() - cropRect.origin.y);
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| double e2d::Image::getWidth() const
 | ||
| {
 | ||
| 	return _cropRect.size.width;
 | ||
| }
 | ||
| 
 | ||
| double e2d::Image::getHeight() const
 | ||
| {
 | ||
| 	return _cropRect.size.height;
 | ||
| }
 | ||
| 
 | ||
| e2d::Size e2d::Image::getSize() const
 | ||
| {
 | ||
| 	return _cropRect.size;
 | ||
| }
 | ||
| 
 | ||
| double e2d::Image::getSourceWidth() const
 | ||
| {
 | ||
| 	if (_bitmap)
 | ||
| 	{
 | ||
| 		return _bitmap->GetSize().width;
 | ||
| 	}
 | ||
| 	else
 | ||
| 	{
 | ||
| 		return 0;
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| double e2d::Image::getSourceHeight() const
 | ||
| {
 | ||
| 	if (_bitmap)
 | ||
| 	{
 | ||
| 		return _bitmap->GetSize().height;
 | ||
| 	}
 | ||
| 	else
 | ||
| 	{
 | ||
| 		return 0;
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| e2d::Size e2d::Image::getSourceSize() const
 | ||
| {
 | ||
| 	if (_bitmap)
 | ||
| 	{
 | ||
| 		return Size(getSourceWidth(), getSourceHeight());
 | ||
| 	}
 | ||
| 	else
 | ||
| 	{
 | ||
| 		return Size();
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| double e2d::Image::getCropX() const
 | ||
| {
 | ||
| 	return _cropRect.origin.x;
 | ||
| }
 | ||
| 
 | ||
| double e2d::Image::getCropY() const
 | ||
| {
 | ||
| 	return _cropRect.origin.y;
 | ||
| }
 | ||
| 
 | ||
| e2d::Point e2d::Image::getCropPos() const
 | ||
| {
 | ||
| 	return _cropRect.origin;
 | ||
| }
 | ||
| 
 | ||
| bool e2d::Image::preload(const Resource& res)
 | ||
| {
 | ||
| 	if (_bitmapCache.find(res) != _bitmapCache.end())
 | ||
| 	{
 | ||
| 		return true;
 | ||
| 	}
 | ||
| 
 | ||
| 	HRESULT hr = S_OK;
 | ||
| 
 | ||
| 	IWICBitmapDecoder *pDecoder = nullptr;
 | ||
| 	IWICBitmapFrameDecode *pSource = nullptr;
 | ||
| 	IWICStream *pStream = nullptr;
 | ||
| 	IWICFormatConverter *pConverter = nullptr;
 | ||
| 	ID2D1Bitmap *pBitmap = nullptr;
 | ||
| 	IWICImagingFactory *pImagingFactory = Renderer::getImagingFactory();
 | ||
| 
 | ||
| 	if (!res.isFile())
 | ||
| 	{
 | ||
| 		HRSRC imageResHandle = nullptr;
 | ||
| 		HGLOBAL imageResDataHandle = nullptr;
 | ||
| 		void *pImageFile = nullptr;
 | ||
| 		DWORD imageFileSize = 0;
 | ||
| 
 | ||
| 		// <20><>λ<EFBFBD><CEBB>Դ
 | ||
| 		imageResHandle = ::FindResourceW(
 | ||
| 			HINST_THISCOMPONENT, 
 | ||
| 			MAKEINTRESOURCE(res.getResNameId()), 
 | ||
| 			(LPCWSTR)res.getResType()
 | ||
| 		);
 | ||
| 
 | ||
| 		hr = imageResHandle ? S_OK : E_FAIL;
 | ||
| 		if (SUCCEEDED(hr))
 | ||
| 		{
 | ||
| 			// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
 | ||
| 			imageResDataHandle = ::LoadResource(HINST_THISCOMPONENT, imageResHandle);
 | ||
| 
 | ||
| 			hr = imageResDataHandle ? S_OK : E_FAIL;
 | ||
| 		}
 | ||
| 
 | ||
| 		if (SUCCEEDED(hr))
 | ||
| 		{
 | ||
| 			// <20><>ȡ<EFBFBD>ļ<EFBFBD>ָ<EFBFBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
 | ||
| 			pImageFile = ::LockResource(imageResDataHandle);
 | ||
| 
 | ||
| 			hr = pImageFile ? S_OK : E_FAIL;
 | ||
| 		}
 | ||
| 
 | ||
| 		if (SUCCEEDED(hr))
 | ||
| 		{
 | ||
| 			// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
 | ||
| 			imageFileSize = ::SizeofResource(HINST_THISCOMPONENT, imageResHandle);
 | ||
| 
 | ||
| 			hr = imageFileSize ? S_OK : E_FAIL;
 | ||
| 		}
 | ||
| 
 | ||
| 		if (SUCCEEDED(hr))
 | ||
| 		{
 | ||
| 			// <20><><EFBFBD><EFBFBD> WIC <20><>
 | ||
| 			hr = pImagingFactory->CreateStream(&pStream);
 | ||
| 		}
 | ||
| 
 | ||
| 		if (SUCCEEDED(hr))
 | ||
| 		{
 | ||
| 			// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
 | ||
| 			hr = pStream->InitializeFromMemory(
 | ||
| 				reinterpret_cast<BYTE*>(pImageFile),
 | ||
| 				imageFileSize
 | ||
| 			);
 | ||
| 		}
 | ||
| 
 | ||
| 		if (SUCCEEDED(hr))
 | ||
| 		{
 | ||
| 			// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD>
 | ||
| 			hr = pImagingFactory->CreateDecoderFromStream(
 | ||
| 				pStream,
 | ||
| 				nullptr,
 | ||
| 				WICDecodeMetadataCacheOnLoad,
 | ||
| 				&pDecoder
 | ||
| 			);
 | ||
| 		}
 | ||
| 	}
 | ||
| 	else
 | ||
| 	{
 | ||
| 		String actualFilePath = File(res.getFileName()).getFilePath();
 | ||
| 		if (actualFilePath.isEmpty())
 | ||
| 		{
 | ||
| 			return false;
 | ||
| 		}
 | ||
| 
 | ||
| 		// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 | ||
| 		hr = pImagingFactory->CreateDecoderFromFilename(
 | ||
| 			(LPCWSTR)actualFilePath,
 | ||
| 			nullptr,
 | ||
| 			GENERIC_READ,
 | ||
| 			WICDecodeMetadataCacheOnLoad,
 | ||
| 			&pDecoder
 | ||
| 		);
 | ||
| 	}
 | ||
| 
 | ||
| 	if (SUCCEEDED(hr))
 | ||
| 	{
 | ||
| 		// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 | ||
| 		hr = pDecoder->GetFrame(0, &pSource);
 | ||
| 	}
 | ||
| 
 | ||
| 	if (SUCCEEDED(hr))
 | ||
| 	{
 | ||
| 		// <20><><EFBFBD><EFBFBD>ͼƬ<CDBC><C6AC>ʽת<CABD><D7AA><EFBFBD><EFBFBD>
 | ||
| 		hr = pImagingFactory->CreateFormatConverter(&pConverter);
 | ||
| 	}
 | ||
| 
 | ||
| 	if (SUCCEEDED(hr))
 | ||
| 	{
 | ||
| 		// ͼƬ<CDBC><C6AC>ʽת<CABD><D7AA><EFBFBD><EFBFBD> 32bppPBGRA
 | ||
| 		hr = pConverter->Initialize(
 | ||
| 			pSource,
 | ||
| 			GUID_WICPixelFormat32bppPBGRA,
 | ||
| 			WICBitmapDitherTypeNone,
 | ||
| 			nullptr,
 | ||
| 			0.f,
 | ||
| 			WICBitmapPaletteTypeMedianCut
 | ||
| 		);
 | ||
| 	}
 | ||
| 
 | ||
| 	if (SUCCEEDED(hr))
 | ||
| 	{
 | ||
| 		// <20><> WIC λͼ<CEBB><CDBC><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Direct2D λͼ
 | ||
| 		hr = Renderer::getInstance()->getRenderTarget()->CreateBitmapFromWicBitmap(
 | ||
| 			pConverter,
 | ||
| 			nullptr,
 | ||
| 			&pBitmap
 | ||
| 		);
 | ||
| 	}
 | ||
| 
 | ||
| 	if (SUCCEEDED(hr))
 | ||
| 	{
 | ||
| 		_bitmapCache.insert(std::make_pair(res, pBitmap));
 | ||
| 	}
 | ||
| 
 | ||
| 	// <20>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
 | ||
| 	SafeRelease(pDecoder);
 | ||
| 	SafeRelease(pSource);
 | ||
| 	SafeRelease(pStream);
 | ||
| 	SafeRelease(pConverter);
 | ||
| 
 | ||
| 	return SUCCEEDED(hr);
 | ||
| }
 | ||
| 
 | ||
| void e2d::Image::clearCache()
 | ||
| {
 | ||
| 	if (_bitmapCache.empty())
 | ||
| 		return;
 | ||
| 
 | ||
| 	for (auto bitmap : _bitmapCache)
 | ||
| 	{
 | ||
| 		bitmap.second->Release();
 | ||
| 	}
 | ||
| 	_bitmapCache.clear();
 | ||
| }
 | ||
| 
 | ||
| void e2d::Image::_setBitmap(ID2D1Bitmap * bitmap)
 | ||
| {
 | ||
| 	if (bitmap)
 | ||
| 	{
 | ||
| 		_bitmap = bitmap;
 | ||
| 		_cropRect.origin.x = _cropRect.origin.y = 0;
 | ||
| 		_cropRect.size.width = _bitmap->GetSize().width;
 | ||
| 		_cropRect.size.height = _bitmap->GetSize().height;
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| ID2D1Bitmap * e2d::Image::getBitmap()
 | ||
| {
 | ||
| 	return _bitmap;
 | ||
| }
 |