Magic_Game/core/Common/Image.cpp

422 lines
8.0 KiB
C++
Raw Normal View History

2018-05-14 00:36:01 +08:00
#include "..\e2dcommon.h"
#include "..\e2dbase.h"
#include <map>
static std::map<size_t, ID2D1Bitmap*> s_mBitmapsFromFile;
static std::map<int, ID2D1Bitmap*> s_mBitmapsFromResource;
2018-05-14 00:36:01 +08:00
static std::set<ID2D1Bitmap*> s_vBitmaps;
e2d::Image::Image()
: _bitmap(nullptr)
, _cropX(0)
, _cropY(0)
, _cropWidth(0)
, _cropHeight(0)
{
}
e2d::Image::Image(const String& filePath)
: _bitmap(nullptr)
{
this->open(filePath);
}
e2d::Image::Image(int resNameId, const String& resType)
: _bitmap(nullptr)
{
this->open(resNameId, resType);
}
e2d::Image::Image(const String& filePath, double cropX, double cropY, double cropWidth, double cropHeight)
: _bitmap(nullptr)
{
this->open(filePath);
this->crop(cropX, cropY, cropWidth, cropHeight);
}
e2d::Image::Image(int resNameId, const String& resType, double cropX, double cropY, double cropWidth, double cropHeight)
: _bitmap(nullptr)
{
this->open(resNameId, resType);
this->crop(cropX, cropY, cropWidth, cropHeight);
}
2018-05-17 12:22:52 +08:00
e2d::Image * e2d::Image::create()
{
return Create<Image>();
}
e2d::Image * e2d::Image::create(const String & filePath)
{
return Create<Image>(filePath);
}
e2d::Image * e2d::Image::create(int resNameId, const String & resType)
{
return Create<Image>(resNameId, resType);
}
e2d::Image * e2d::Image::create(const String & filePath, double cropX, double cropY, double cropWidth, double cropHeight)
{
return Create<Image>(filePath, cropX, cropY, cropWidth, cropHeight);
}
e2d::Image * e2d::Image::create(int resNameId, const String & resType, double cropX, double cropY, double cropWidth, double cropHeight)
{
return Create<Image>(resNameId, resType, cropX, cropY, cropWidth, cropHeight);
}
e2d::Image::~Image()
{
}
bool e2d::Image::open(const String& filePath)
{
2018-05-14 00:36:01 +08:00
WARN_IF(filePath.isEmpty(), "Image open failed! Invalid file name.");
if (filePath.isEmpty())
return false;
if (!Image::preload(filePath))
{
WARN_IF(true, "Load Image from file failed!");
return false;
}
2018-05-14 00:36:01 +08:00
this->_setBitmap(s_mBitmapsFromFile.at(filePath.getHashCode()));
return true;
}
bool e2d::Image::open(int resNameId, const String& resType)
{
if (!Image::preload(resNameId, resType))
{
WARN_IF(true, "Load Image from file failed!");
return false;
}
2018-05-14 00:36:01 +08:00
this->_setBitmap(s_mBitmapsFromResource.at(resNameId));
return true;
}
2018-04-06 11:31:24 +08:00
void e2d::Image::crop(double x, double y, double width, double height)
2018-02-03 22:04:43 +08:00
{
if (_bitmap)
{
_cropX = min(max(x, 0), this->getSourceWidth());
_cropY = min(max(y, 0), this->getSourceHeight());
_cropWidth = min(max(width, 0), this->getSourceWidth() - _cropX);
_cropHeight = min(max(height, 0), this->getSourceHeight() - _cropY);
}
2018-02-03 22:04:43 +08:00
}
2018-02-27 21:07:43 +08:00
double e2d::Image::getWidth() const
2018-02-03 22:04:43 +08:00
{
return _cropWidth;
2018-02-03 22:04:43 +08:00
}
2018-02-27 21:07:43 +08:00
double e2d::Image::getHeight() const
2018-02-03 22:04:43 +08:00
{
return _cropHeight;
2018-02-03 22:04:43 +08:00
}
e2d::Size e2d::Image::getSize() const
2018-02-03 22:04:43 +08:00
{
return Size(_cropWidth, _cropHeight);
}
2018-02-27 21:07:43 +08:00
double e2d::Image::getSourceWidth() const
{
if (_bitmap)
{
return _bitmap->GetSize().width;
}
else
{
return 0;
}
}
2018-02-27 21:07:43 +08:00
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();
}
}
2018-04-06 11:31:24 +08:00
double e2d::Image::getCropX() const
2018-02-03 22:04:43 +08:00
{
return _cropX;
2018-02-03 22:04:43 +08:00
}
2018-04-06 11:31:24 +08:00
double e2d::Image::getCropY() const
2018-02-03 22:04:43 +08:00
{
return _cropY;
2018-02-03 22:04:43 +08:00
}
2018-04-06 11:31:24 +08:00
e2d::Point e2d::Image::getCropPos() const
2018-02-03 22:04:43 +08:00
{
return Point(_cropX, _cropY);
2018-02-03 22:04:43 +08:00
}
2018-05-14 00:36:01 +08:00
bool e2d::Image::preload(const String& filePath)
{
2018-05-14 00:36:01 +08:00
if (s_mBitmapsFromFile.find(filePath.getHashCode()) != s_mBitmapsFromFile.end())
{
return true;
}
HRESULT hr = S_OK;
IWICBitmapDecoder *pDecoder = nullptr;
IWICBitmapFrameDecode *pSource = nullptr;
IWICStream *pStream = nullptr;
IWICFormatConverter *pConverter = nullptr;
ID2D1Bitmap *pBitmap = nullptr;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
hr = Renderer::getIWICImagingFactory()->CreateDecoderFromFilename(
2018-05-14 00:36:01 +08:00
filePath,
NULL,
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>
// (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
hr = Renderer::getIWICImagingFactory()->CreateFormatConverter(&pConverter);
}
2018-05-10 00:58:43 +08:00
if (SUCCEEDED(hr))
{
// ͼƬ<CDBC><C6AC>ʽת<CABD><D7AA><EFBFBD><EFBFBD> 32bbpPBGRA
hr = pConverter->Initialize(
pSource,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.f,
WICBitmapPaletteTypeMedianCut
);
}
2018-05-10 00:58:43 +08:00
if (SUCCEEDED(hr))
{
// <20><> WIC λͼ<CEBB><CDBC><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Direct2D λͼ
hr = Renderer::getRenderTarget()->CreateBitmapFromWicBitmap(
pConverter,
NULL,
&pBitmap
);
}
2018-05-10 00:58:43 +08:00
if (SUCCEEDED(hr))
{
// <20><><EFBFBD><EFBFBD>ͼƬָ<C6AC><D6B8><EFBFBD><EFBFBD>ͼƬ<CDBC><C6AC> Hash <20><>
s_mBitmapsFromFile.insert(
std::map<size_t, ID2D1Bitmap*>::value_type(
2018-05-14 00:36:01 +08:00
filePath.getHashCode(),
pBitmap)
);
}
// <20>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
2018-05-10 20:23:32 +08:00
SafeReleaseInterface(pDecoder);
SafeReleaseInterface(pSource);
SafeReleaseInterface(pStream);
SafeReleaseInterface(pConverter);
return SUCCEEDED(hr);
}
bool e2d::Image::preload(int resNameId, const String& resType)
{
if (s_mBitmapsFromResource.find(resNameId) != s_mBitmapsFromResource.end())
{
return true;
}
HRESULT hr = S_OK;
IWICBitmapDecoder *pDecoder = nullptr;
IWICBitmapFrameDecode *pSource = nullptr;
IWICStream *pStream = nullptr;
IWICFormatConverter *pConverter = nullptr;
IWICBitmapScaler *pScaler = nullptr;
ID2D1Bitmap *pBitmap = nullptr;
HRSRC imageResHandle = nullptr;
HGLOBAL imageResDataHandle = nullptr;
void *pImageFile = nullptr;
DWORD imageFileSize = 0;
// <20><>λ<EFBFBD><CEBB>Դ
imageResHandle = ::FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(resNameId), resType);
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 = Renderer::getIWICImagingFactory()->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 = Renderer::getIWICImagingFactory()->CreateDecoderFromStream(
pStream,
NULL,
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>
// (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
hr = Renderer::getIWICImagingFactory()->CreateFormatConverter(&pConverter);
}
if (SUCCEEDED(hr))
{
// ͼƬ<CDBC><C6AC>ʽת<CABD><D7AA><EFBFBD><EFBFBD> 32bppPBGRA
hr = pConverter->Initialize(
pSource,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.f,
WICBitmapPaletteTypeMedianCut
);
}
if (SUCCEEDED(hr))
{
// <20><> WIC λͼ<CEBB><CDBC><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Direct2D λͼ
hr = Renderer::getRenderTarget()->CreateBitmapFromWicBitmap(
pConverter,
NULL,
&pBitmap
);
}
if (SUCCEEDED(hr))
{
s_mBitmapsFromResource.insert(std::pair<int, ID2D1Bitmap*>(resNameId, pBitmap));
}
// <20>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
2018-05-10 20:23:32 +08:00
SafeReleaseInterface(pDecoder);
SafeReleaseInterface(pSource);
SafeReleaseInterface(pStream);
SafeReleaseInterface(pConverter);
SafeReleaseInterface(pScaler);
return SUCCEEDED(hr);
}
void e2d::Image::clearCache()
{
for (auto bitmap : s_mBitmapsFromFile)
{
2018-05-10 20:23:32 +08:00
SafeReleaseInterface(bitmap.second);
}
s_mBitmapsFromFile.clear();
for (auto bitmap : s_mBitmapsFromResource)
{
2018-05-10 20:23:32 +08:00
SafeReleaseInterface(bitmap.second);
}
s_mBitmapsFromResource.clear();
2018-05-14 00:36:01 +08:00
for (auto bitmap : s_vBitmaps)
{
SafeReleaseInterface(bitmap);
}
s_vBitmaps.clear();
}
void e2d::Image::_setBitmap(ID2D1Bitmap * bitmap)
{
if (bitmap)
{
_bitmap = bitmap;
_cropX = _cropY = 0;
_cropWidth = _bitmap->GetSize().width;
_cropHeight = _bitmap->GetSize().height;
}
}
ID2D1Bitmap * e2d::Image::getBitmap()
{
return _bitmap;
}