以前搞了GIF、JPEG的解码器,前些时候发现系统的解码组件貌似也有类似的功能,google了一下,发现的确有人用系统codec做过gif动画,所以看了一下,发现的确是ok的,关键代码:
IStream* CTestGif::CreateStreamFromFile(LPCTSTR strFileName)
{
hFile = CreateFile(strFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
dwFileSize = GetFileSize(hFile, NULL);
hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
LPVOID pvData = GlobalLock(hGlobal);
DWORD dwBytesRead = 0;
BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);
GlobalUnlock(hGlobal);
hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
...
}
初始化解码过程:
m_pStream = CreateStreamByFileName(pszFileName);
hr = CoCreateInstance (CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **)&m_pImgFactory);
if(SUCCEEDED(hr))
{
hr = m_pImgFactory->CreateImageDecoder(m_pStream, DecoderInitFlagNone, &m_pDecoder);
}
if(SUCCEEDED(hr))
{
LARGE_INTEGER dlibMove = { 0, 0 };
UINT uSize = 0;
UINT uDismensions = 0;
hr = m_pDecoder->TerminateDecoder();
hr = m_pStream->Seek(dlibMove, STREAM_SEEK_SET, NULL );
hr = m_pDecoder->InitDecoder(m_pStream, DecoderInitFlagBuiltIn1st);
hr = m_pDecoder->GetPropertyItemSize(PropertyTagFrameDelay, &uSize);
m_pPropItem = (PropertyItem*)malloc(uSize);
hr = m_pDecoder->GetPropertyItem(PropertyTagFrameDelay, uSize, m_pPropItem);
hr = m_pDecoder->GetImageInfo(&m_ImgInfo);
hr = m_pDecoder->GetFrameDimensionsCount(&uDismensions);
m_pGuid = (GUID*) new GUID[uDismensions];
hr = m_pDecoder->GetFrameDimensionsList(m_pGuid, uDismensions);
hr = m_pDecoder->GetFrameCount(&m_pGuid[0], &m_uFrameCount);
}
解码单帧 并获取延时:
HRESULT CTestGif::DecodeFrame(int& nFrameDelay)
{
...
IBitmapImage *pBmp = NULL;
IImageSink *pSink = NULL;
HRESULT hr = m_pDecoder->SelectActiveFrame(m_pGuid, m_uCurFrame);
hr = m_pImgFactory->CreateNewBitmap(m_ImgInfo.Width, m_ImgInfo.Height, PixelFormatDontCare, &pBmp);
hr = pBmp->QueryInterface(IID_IImageSink, (void**)&pSink);
hr = m_pDecoder->BeginDecode(pSink, NULL);
hr = m_pDecoder->Decode();
IBasicBitmapOps *pOps = NULL;
hr = pBmp->QueryInterface(IID_IBasicBitmapOps, (void **) &pOps);
if(m_pImage)
m_pImage->Release();
m_pImage = NULL;
hr = pBmp->QueryInterface(IID_IImage, (void**)&m_pImage);
hr = m_pDecoder->EndDecode(hr);
pBmp->Release();
pSink->Release();
pOps->Release();
nFrameDelay = GetDelay();
++m_uCurFrame;
return hr;
}
int CTestGif::GetDelay()
{
if(!m_pPropItem)
return -1;
ASSERT(m_uCurFrame>=0);
int lPause = ((long*)m_pPropItem->value)[m_uCurFrame]*10; //毫秒
return lPause;
}
发现的问题:
1. 解码能力比较差,只能整个图解码,无法在解码前后缩放,也不支持设置图片位深
2. 只能通过m_pImage->Draw(hdc, &rcClient, NULL); 输出图片,输出时候无法bitblt,感觉很不顺手。
奇怪的是m_pImage->Draw输出好像有点问题,画指定的区域到设备上时候明显输出比例有问题,还有待研究。