Magic_Game/core/Common/Image.cpp

398 lines
7.3 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)
2018-05-22 23:36:46 +08:00
, _cropRect()
{
}
e2d::Image::Image(const String& filePath)
: _bitmap(nullptr)
2018-05-22 23:36:46 +08:00
, _cropRect()
{
this->open(filePath);
}
e2d::Image::Image(int resNameId, const String& resType)
: _bitmap(nullptr)
2018-05-22 23:36:46 +08:00
, _cropRect()
{
this->open(resNameId, resType);
}
2018-05-22 23:36:46 +08:00
e2d::Image::Image(const String& filePath, const Rect& cropRect)
: _bitmap(nullptr)
2018-05-22 23:36:46 +08:00
, _cropRect()
{
this->open(filePath);
2018-05-22 23:36:46 +08:00
this->crop(cropRect);
}
2018-05-22 23:36:46 +08:00
e2d::Image::Image(int resNameId, const String& resType, const Rect& cropRect)
: _bitmap(nullptr)
2018-05-22 23:36:46 +08:00
, _cropRect()
{
this->open(resNameId, resType);
2018-05-22 23:36:46 +08:00
this->crop(cropRect);
}
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-05-22 23:36:46 +08:00
void e2d::Image::crop(const Rect& cropRect)
2018-02-03 22:04:43 +08:00
{
if (_bitmap)
{
2018-05-22 23:36:46 +08:00
_cropRect.origin.x = min(max(cropRect.origin.x, 0), this->getSourceWidth());
_cropRect.origin.y = min(max(cropRect.origin.y, 0), this->getSourceHeight());
_cropRect.size.width = min(max(cropRect.size.width, 0), this->getSourceWidth() - cropRect.origin.x);
_cropRect.size.height = min(max(cropRect.size.height, 0), this->getSourceHeight() - cropRect.origin.y);
}
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
{
2018-05-22 23:36:46 +08:00
return _cropRect.size.width;
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
{
2018-05-22 23:36:46 +08:00
return _cropRect.size.height;
2018-02-03 22:04:43 +08:00
}
e2d::Size e2d::Image::getSize() const
2018-02-03 22:04:43 +08:00
{
2018-05-22 23:36:46 +08:00
return _cropRect.size;
}
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
{
2018-05-22 23:36:46 +08:00
return _cropRect.origin.x;
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
{
2018-05-22 23:36:46 +08:00
return _cropRect.origin.y;
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
{
2018-05-22 23:36:46 +08:00
return _cropRect.origin;
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,
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>
// (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,
nullptr,
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,
nullptr,
&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-22 12:24:43 +08:00
SafeRelease(pDecoder);
SafeRelease(pSource);
SafeRelease(pStream);
SafeRelease(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,
nullptr,
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,
nullptr,
0.f,
WICBitmapPaletteTypeMedianCut
);
}
if (SUCCEEDED(hr))
{
// <20><> WIC λͼ<CEBB><CDBC><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Direct2D λͼ
hr = Renderer::getRenderTarget()->CreateBitmapFromWicBitmap(
pConverter,
nullptr,
&pBitmap
);
}
if (SUCCEEDED(hr))
{
s_mBitmapsFromResource.insert(std::pair<int, ID2D1Bitmap*>(resNameId, pBitmap));
}
// <20>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
2018-05-22 12:24:43 +08:00
SafeRelease(pDecoder);
SafeRelease(pSource);
SafeRelease(pStream);
SafeRelease(pConverter);
SafeRelease(pScaler);
return SUCCEEDED(hr);
}
void e2d::Image::clearCache()
{
for (auto bitmap : s_mBitmapsFromFile)
{
2018-05-22 12:24:43 +08:00
SafeRelease(bitmap.second);
}
s_mBitmapsFromFile.clear();
for (auto bitmap : s_mBitmapsFromResource)
{
2018-05-22 12:24:43 +08:00
SafeRelease(bitmap.second);
}
s_mBitmapsFromResource.clear();
2018-05-14 00:36:01 +08:00
for (auto bitmap : s_vBitmaps)
{
2018-05-22 12:24:43 +08:00
SafeRelease(bitmap);
2018-05-14 00:36:01 +08:00
}
s_vBitmaps.clear();
}
void e2d::Image::_setBitmap(ID2D1Bitmap * bitmap)
{
if (bitmap)
{
_bitmap = bitmap;
2018-05-22 23:36:46 +08:00
_cropRect.origin.x = _cropRect.origin.y = 0;
_cropRect.size.width = _bitmap->GetSize().width;
_cropRect.size.height = _bitmap->GetSize().height;
2018-05-14 00:36:01 +08:00
}
}
ID2D1Bitmap * e2d::Image::getBitmap()
{
return _bitmap;
}