📄 imagedecoder.cpp
字号:
/*
ImageDecoder.cpp
Class ImageDecoder Implementation, base upon imaging com interface.
*/
#include "ImageDecoder.h"
#include "debug.h"
ImageDecoder::ImageDecoder(TCHAR* ImageFileName)
{
HRESULT hr;
ImageInfo ii;
lstrcpy(this->filename, ImageFileName);
if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
{
DBGMSG(TEXT("CoInitializeEx failed, hr: 0x%08x\n"), hr);
goto finish;
}
hr = CoCreateInstance(CLSID_ImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IImagingFactory,
(void**) &pImagingFactory);
if(FAILED(hr))
{
DBGMSG(TEXT("CoCreateInstance failed, hr:0x08x\n"), hr);
goto finish;
}
DBGMSG(TEXT("Opening %s"), filename);
if(FAILED(hr = CreateStreamOnFile(filename, &pStream)))
{
DBGMSG(TEXT("CreateStreamOnFile failed, hr: 0x%08x\n"), hr);
goto finish;
}
GetCodecCLSID(pImagingFactory, NULL, NULL, eDecoder);
if(FAILED(hr = pImagingFactory->CreateImageDecoder(pStream, DecoderInitFlagBuiltIn1st, &pImageDecoder)))
{
DBGMSG(TEXT("CreateImageDecoder failed, hr: 0x%08x\n"), hr);
goto finish;
}
if (FAILED(hr = pImageDecoder->GetFrameCount(&FrameDimensionTime, &nFrameCount)))
{
//DBGMSG(TEXT("GetFrameCount failed, hr: 0x%08x\n"), hr);
nFrameCount = 0;
//JPG file will fail this call, just pass it
//goto finish;
}
pImageDecoder->GetImageInfo(&ii);
this->ii = ii;
if(FAILED(hr = pImagingFactory->CreateNewBitmap(ii.Width, ii.Height, ii.PixelFormat, &pBitmapImage)))
{
DBGMSG(TEXT("CreateNewBitmap failed, hr = 0x%08x\n"), hr);
goto finish;
}
if(FAILED(hr = pBitmapImage->QueryInterface(IID_IImageSink, (void**)&pImageSink)))
{
DBGMSG(TEXT("QueryInterface for ImageSink from BitmapImage failed, hr: 0x%08x\n"), hr);
goto finish;
}
if(FAILED(hr = pBitmapImage->QueryInterface(IID_IImage, (void**)&pImage)))
{
DBGMSG(TEXT("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\n"), hr);
goto finish;
}
if (FAILED(hr = pBitmapImage->QueryInterface(IID_IBasicBitmapOps, (void**)&pBasicBitmapOps)))
{
DBGMSG(TEXT("QueryInterface for BasicBitmapOps from BitmapImage failed, hr: 0x%08x\n"), hr);
goto finish;
}
state = Init;
goto finish_ok;
finish:
state = UnInit;
finish_ok:
Angle = 0;
pBitmapImageRotate = NULL;
pImageRotate = NULL;
nSelectedFrame = 0;
return;
}
ImageDecoder::ImageDecoder(HRSRC hRes)
{
HRESULT hr;
ImageInfo ii;
//lstrcpy(this->filename, ImageFileName);
if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
{
DBGMSG(TEXT("CoInitializeEx failed, hr: 0x%08x\n"), hr);
goto finish;
}
hr = CoCreateInstance(CLSID_ImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IImagingFactory,
(void**) &pImagingFactory);
if(FAILED(hr))
{
DBGMSG(TEXT("CoCreateInstance failed, hr:0x08x\n"), hr);
goto finish;
}
//DBGMSG(TEXT("Opening %s"), filename);
//if(FAILED(hr = CreateStreamOnFile(filename, &pStream)))
if(FAILED(hr = CreateStreamOnResource(hRes, &pStream)))
{
DBGMSG(TEXT("CreateStreamOnFile failed, hr: 0x%08x\n"), hr);
goto finish;
}
GetCodecCLSID(pImagingFactory, NULL, NULL, eDecoder);
if(FAILED(hr = pImagingFactory->CreateImageDecoder(pStream, DecoderInitFlagBuiltIn1st, &pImageDecoder)))
{
DBGMSG(TEXT("CreateImageDecoder failed, hr: 0x%08x\n"), hr);
goto finish;
}
if (FAILED(hr = pImageDecoder->GetFrameCount(&FrameDimensionTime, &nFrameCount)))
{
//DBGMSG(TEXT("GetFrameCount failed, hr: 0x%08x\n"), hr);
nFrameCount = 0;
//JPG file will fail this call, just pass it
//goto finish;
}
pImageDecoder->GetImageInfo(&ii);
this->ii = ii;
if(FAILED(hr = pImagingFactory->CreateNewBitmap(ii.Width, ii.Height, ii.PixelFormat, &pBitmapImage)))
{
DBGMSG(TEXT("CreateNewBitmap failed, hr = 0x%08x\n"), hr);
goto finish;
}
if(FAILED(hr = pBitmapImage->QueryInterface(IID_IImageSink, (void**)&pImageSink)))
{
DBGMSG(TEXT("QueryInterface for ImageSink from BitmapImage failed, hr: 0x%08x\n"), hr);
goto finish;
}
if(FAILED(hr = pBitmapImage->QueryInterface(IID_IImage, (void**)&pImage)))
{
DBGMSG(TEXT("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\n"), hr);
goto finish;
}
if (FAILED(hr = pBitmapImage->QueryInterface(IID_IBasicBitmapOps, (void**)&pBasicBitmapOps)))
{
DBGMSG(TEXT("QueryInterface for BasicBitmapOps from BitmapImage failed, hr: 0x%08x\n"), hr);
goto finish;
}
state = Init;
goto finish_ok;
finish:
state = UnInit;
finish_ok:
Angle = 0;
pBitmapImageRotate = NULL;
pImageRotate = NULL;
nSelectedFrame = 0;
return;
}
ImageDecoder::~ImageDecoder()
{
if(pImageRotate)
{
pImageRotate->Release();
pImageRotate = NULL;
}
if(pBitmapImageRotate)
{
pBitmapImageRotate->Release();
pBitmapImageRotate = NULL;
}
if(pBasicBitmapOps)
{
pBasicBitmapOps->Release();
pBasicBitmapOps = NULL;
}
if(pImage)
{
pImage->Release();
pImage = NULL;
}
if(pImageSink)
{
pImageSink->Release();
pImageSink = NULL;
}
if(pBitmapImage)
{
pBitmapImage->Release();
pBitmapImage = NULL;
}
if(pImageDecoder)
{
pImageDecoder->Release();
pImageDecoder = NULL;
}
if(pStream)
{
pStream->Release();
pStream = NULL;
}
if(pImagingFactory)
{
pImagingFactory->Release();
pImagingFactory = NULL;
}
CoUninitialize();
return;
}
void ImageDecoder::Decode() //decode the image
{
HRESULT hr;
if (FAILED(hr = pImageDecoder->BeginDecode(pImageSink, NULL)))
{
DBGMSG(TEXT("BeginDecode into Bitmap Image failed, hr = 0x%08d\n"), hr);
goto finish;
}
while (E_PENDING == (hr = pImageDecoder->Decode()))
{
Sleep(0);
}
hr = pImageDecoder->EndDecode(hr);
if (FAILED(hr))
{
DBGMSG(TEXT("Decoding failed, hr = 0x%08x\n"), hr);
goto finish;
}
state = Decoded;
finish:
return;
}
void ImageDecoder::Rotate(int Angle)
{
this->Angle = Angle;
}
StateType ImageDecoder::State()
{
return state;
}
#if 0
TCHAR* ImageDecoder::FileName()
{
//return filename;
}
#endif
int ImageDecoder::Width()
{
return ii.Width;
}
int ImageDecoder::Height()
{
return ii.Height;
}
UINT ImageDecoder::FrameCount()
{
return nFrameCount;
}
void ImageDecoder::SelectNextFrame()
{
HRESULT hr;
nSelectedFrame++;
if(nSelectedFrame > (nFrameCount - 1))
{
nSelectedFrame = 0;
}
ASSERT(pBitmapImage);
pBitmapImage->Release();
ASSERT(pImageSink);
pImageSink->Release();
ASSERT(pImage);
pImage->Release();
if (FAILED(hr = pImageDecoder->SelectActiveFrame(&FrameDimensionTime, nSelectedFrame)))
{
ASSERT(0);
}
if (FAILED(hr = pImagingFactory->CreateNewBitmap(ii.Width, ii.Height, ii.PixelFormat, &pBitmapImage)))
{
DBGMSG(TEXT("CreateNewBitmap failed, hr = 0x%08x\n"), hr);
ASSERT(0);
}
if (FAILED(hr = pBitmapImage->QueryInterface(IID_IImageSink, (void**)&pImageSink)))
{
DBGMSG(TEXT("QueryInterface for ImageSink from BitmapImage failed, hr: 0x%08x\n"), hr);
ASSERT(0);
}
if (FAILED(hr = pBitmapImage->QueryInterface(IID_IImage, (void**)&pImage)))
{
DBGMSG(TEXT("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\n"), hr);
ASSERT(0);
}
}
void ImageDecoder::Draw(HDC hdc, RECT &dstRect)
{
RECT rc;
HRESULT hr;
float fAngle = (float)Angle;
GetDestRect(ii.Width, ii.Height, dstRect.right, dstRect.bottom, rc);
if(Angle != 0)
{
if(pImageRotate)
{
pImageRotate->Release();
pImageRotate = NULL;
}
if(pBitmapImageRotate)
{
pBitmapImageRotate->Release();
pBitmapImageRotate = NULL;
}
if(FAILED(hr = pBasicBitmapOps->Rotate(fAngle, InterpolationHintDefault, &pBitmapImageRotate)))
{
DBGMSG(TEXT("Rotate Image failed, hr: 0x%08x\n"), hr);
}
if(FAILED(hr = pBitmapImageRotate->QueryInterface(IID_IImage, (void**)&pImageRotate)))
{
DBGMSG(TEXT("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\n"), hr);
}
pImageRotate->Draw(hdc, &rc, NULL);
}
else
{
pImage->Draw(hdc, &rc, NULL);
}
}
void ImageDecoder::Flip()
{
}
void ImageDecoder::Resize()
{
}
void ImageDecoder::AdjustBrightness()
{
}
void ImageDecoder::AdjustContrast()
{
}
void ImageDecoder::AdjustGamma()
{
}
BOOL ImageDecoder::GetCodecCLSID(IImagingFactory* pImagingFactory, CLSID * pclsid, WCHAR * wszMimeType, CodecType ctCodec)
{
UINT uiCount;
ImageCodecInfo * codecs;
HRESULT hr;
BOOL fRet = FALSE;
TCHAR * tszCodec;
if(eEncoder == ctCodec)
{
hr = pImagingFactory->GetInstalledEncoders(&uiCount, &codecs);
tszCodec = TEXT("Encoder");
}
else
{
hr = pImagingFactory->GetInstalledDecoders(&uiCount, &codecs);
tszCodec = TEXT("Decoder");
}
if(FAILED(hr))
{
DBGMSG(TEXT("GetInstalled%ss returned 0x%08x\n"), tszCodec, hr);
return FALSE;
}
for(UINT i = 0; i < uiCount; i++)
{
//DBGMSG(TEXT("%s %d of %d: MimeType = %s\n"), tszCodec, i + 1, uiCount, codecs[i].MimeType);
if (wszMimeType && !wcscmp(wszMimeType, codecs[i].MimeType))
{
*pclsid = codecs[i].Clsid;
fRet = TRUE;
break;
}
}
CoTaskMemFree(codecs);
return fRet;
}
HRESULT ImageDecoder::CreateStreamOnFile(const TCHAR * tszFilename, IStream ** ppStream)
{
HRESULT hrRet = S_OK;
HGLOBAL hg = NULL;
HANDLE hFile = NULL;
DWORD dwSize, dwRead;
BYTE* pbLocked = NULL;
// Open the file
hFile = CreateFile(tszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
DBGMSG(TEXT("CreateFile failed with GLE = %d\n"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
dwSize = GetFileSize(hFile, NULL);
if(0xffffffff == dwSize)
{
DBGMSG(TEXT("GetFileSize failed with GLE = %d\n"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
// Open a memory object
hg = GlobalAlloc(GMEM_MOVEABLE, dwSize);
if(NULL == hg)
{
DBGMSG(TEXT("GlobalAlloc failed with GLE = %d\n"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
// Ge a pointer to the memory we just allocated
pbLocked = (BYTE*) GlobalLock(hg);
if(NULL == pbLocked)
{
DBGMSG(TEXT("GlobalLock failed with GLE = %d\n"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
// copy the file
if(!ReadFile(hFile, pbLocked, dwSize, &dwRead, NULL))
{
DBGMSG(TEXT("ReadFile failed with GLE = %d\n"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
GlobalUnlock(hg);
// Create the stream
hrRet = CreateStreamOnHGlobal(hg, TRUE, ppStream);
CloseHandle(hFile);
return hrRet;
error:
if(pbLocked)
GlobalUnlock(hg);
if(hg)
GlobalFree(hg);
if(hFile)
CloseHandle(hFile);
return hrRet;
}
HRESULT ImageDecoder::CreateStreamOnResource(HRSRC hRes, IStream ** ppStream)
{
HRESULT hrRet = S_OK;
HGLOBAL hg = NULL;
//HANDLE hFile = NULL;
DWORD dwSize; //dwRead;
BYTE* pbLocked = NULL;
// Open the file
#if 0
hFile = CreateFile(tszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
DBGMSG(TEXT("CreateFile failed with GLE = %d"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
dwSize = GetFileSize(hFile, NULL);
if(0xffffffff == dwSize)
{
DBGMSG(TEXT("GetFileSize failed with GLE = %d"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
#endif
HGLOBAL hGbl = LoadResource(GetModuleHandle(NULL), hRes);
BYTE* pbData = (BYTE*)LockResource(hGbl);
dwSize = SizeofResource(GetModuleHandle(NULL), hRes);
// Open a memory object
hg = GlobalAlloc(GMEM_MOVEABLE, dwSize);
if(NULL == hg)
{
DBGMSG(TEXT("GlobalAlloc failed with GLE = %d\n"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
// Ge a pointer to the memory we just allocated
pbLocked = (BYTE*) GlobalLock(hg);
if(NULL == pbLocked)
{
DBGMSG(TEXT("GlobalLock failed with GLE = %d\n"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
// copy the file
memcpy(pbLocked, pbData, dwSize);
#if 0
if(!ReadFile(hFile, pbLocked, dwSize, &dwRead, NULL))
{
DBGMSG(TEXT("ReadFile failed with GLE = %d"), GetLastError());
hrRet = 0x80000000 + GetLastError();
goto error;
}
#endif
GlobalUnlock(hg);
// Create the stream
hrRet = CreateStreamOnHGlobal(hg, TRUE, ppStream);
//CloseHandle(hFile);
return hrRet;
error:
if(pbLocked)
GlobalUnlock(hg);
if(hg)
GlobalFree(hg);
// if(hFile)
// CloseHandle(hFile);
return hrRet;
}
void ImageDecoder::
GetDestRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight, RECT &out)
{
int x, y, width, height;
float XRatio, YRatio;
x = 0;
y = 0;
if(Angle == 0 || Angle == 360 || Angle == 180)
{
width = srcWidth;
height = srcHeight;
}
else
{
width = srcHeight;
height = srcWidth;
}
XRatio = (float)dstWidth/(float)width;
YRatio = (float)dstHeight/(float)height;
if(XRatio < YRatio)
{
height = (int)((float)height * XRatio);
width = dstWidth;
y = (dstHeight - height)/2;
}
else
{
height = dstHeight;
width = (int)((float)width * YRatio);
x = (dstWidth - width)/2;
}
out.left = x;
out.right = x + width;
out.top = y;
out.bottom = y + height;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -