yongshi123

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Mobil手机加载GIF动态图像的方法有两种,一个就是使用GIF89a标准算法,另一个就是使用SDK自带的Imaging组件,这两种方法是很典型的手机图像处理技术的实践。使用Imaging组件加载GIF比使用标准算法处理高效的多,特别是在处理真彩GIF动画表现更加突出。

Imaging组件中封装了对大部分图片格式的编解码算法,并以接口的形式提供给开发人员使用。Imaging组件是GDI+的微缩版。但是在实际使用上又有很大的不同。使用Imaging组件来加载GIF动态图片调用了几乎所有的Imaging接口

看看我们将要用到的接口:

IImagingFactory:图像操作最初要用到的接口,它的接口方法全是带CreateXXX的函数,可见他的制造工厂的特性。使用前需要调用CoCreateInstance初始化。

IImageDecoder:主要的图像操作接口,用来处理从大部分图像格式中获取数据。

IbitmapImage:主要的图位操作接口,这里能够对具体的图像像素进行运算。

IImage:主要的图形控制接口,也许是Imaging组件唯一的绘制接口

IImageSink:这个东东似乎是一个过渡性质的接口,它的亮点在它的sink的动词解释上:沉!

操作:

首先我们要使用IImagingFactoryCreateImageDecoderppy初始化IimageDecoder。使用这个接口的方法取得GIF图像数据信息,再用IimagingFactoryCreateNewBitmap初始化IbitmapImage。通过这个接口执行QueryInterface取得IImageIimageSink,然后调用IimageDecoderSelectActiveFrame设定当前的图像块数据。此时对获得的IimageSink进行decode,decode完毕后调用Iimage接口的draw方法,此时画出的就是指定的那个图像块图像。

部分代码:

文件到流的转化

HRESULT CGIFImage::CreateStreamOnFile(const TCHAR * tszFilenameIStream ** ppStream)

{

     HRESULT hrRet = S_OK;

     HGLOBAL hg = NULL;

     HANDLE hGIFFile = NULL;

     DWORD dwSizedwRead;

     BYTEpbLocked = NULL;

 

     // 建立一个文件池,我管CreateFile返回的handle这个叫文件池

     hGIFFile = CreateFile(tszFilenameGENERIC_READ, 0, NULLOPEN_EXISTING, 0, NULL);

     //handle地址为-1时表示没有创建成功

     if (INVALID_HANDLE_VALUE == hGIFFile)

     {

         hrRet = E_PENDING + GetLastError();

         goto error;

     }

     dwSize = GetFileSize(hGIFFileNULL);

     //当尺寸溢出时放弃

     if (INVALID_FILE_SIZE == dwSize)

     {

         hrRet = E_PENDING + GetLastError();

         goto error;

     }

 

     // 分配一个文件尺寸相同的活动内存池

     hg = GlobalAlloc(GMEM_MOVEABLEdwSize);

     //分配失败即放弃

     if (NULL == hg)

     {

         hrRet = E_PENDING + GetLastError();

         goto error;

     }

 

     //使用GlobalLock得到内存指针

     pbLocked = (BYTE*) GlobalLock(hg);

     //lock失败放弃

     if (NULL == pbLocked)

     {

         hrRet = E_PENDING + GetLastError();

         goto error;

     }

 

     // copy the file

     if (!ReadFile(hGIFFilepbLockeddwSize, &dwReadNULL))

     {

         hrRet = E_PENDING + GetLastError();

         goto error;

     }

 

     GlobalUnlock(hg);

 

     // 创建文件流

     hrRet = CreateStreamOnHGlobal(hgTRUEppStream);

 

     CloseHandle(hGIFFile);

     return hrRet;

error:

     if (pbLocked)

         GlobalUnlock(hg);

     if (hg)

         GlobalFree(hg);

     if (hGIFFile)

         CloseHandle(hGIFFile);

     return hrRet;

 

}

 

 文件加载

 

Loadfn方法

IStreamgifStream;//GIF文件数据流

 

     CreateStreamOnFile(fn,&gifStream);//加载文件到流中

 

//GIF流解码,取decoad对象

     if(SUCCEEDED(m_GIFImageFactory->CreateImageDecoder(gifStream,DecoderInitFlagBuiltIn1st,&m_GIFImageDecoder)))

     {

         UINT num;

         UINT delaySize;

         IBitmapImageibGif;

         //GUID pdi;

         //获取图像的dimension

         m_GIFImageDecoder->GetFrameDimensionsCount(&num);

         //获取图像的dimension列表

         m_GIFImageDecoder->GetFrameDimensionsList(&m_pdi,num);

         m_GIFImageDecoder->GetFrameCount(&m_pdi,&m_nPageQuantity);

 

         //获取图像间的延迟时间

         m_GIFImageDecoder->GetPropertyItemSize(PropertyTagFrameDelay,&delaySize);

         PropertyItempItem = NULL;

         pItem = (PropertyItem*)malloc(delaySize);

         m_GIFImageDecoder->GetPropertyItem(PropertyTagFrameDelay,delaySize,pItem);

         m_nRate=((UINT*)pItem->value)[0];

 

         m_GIFImageDecoder->GetImageInfo(&m_iif);

         m_GIFImageFactory->CreateNewBitmap(m_iif.Width,m_iif.Height,m_iif.PixelFormat,&ibGif);

         ibGif->QueryInterface(IID_IImageSink,(void**)&m_GIFImageSink);

         ibGif->QueryInterface(IID_IImage,(void**)&m_GIFImage);

 

     }

 

在定时器中执行下面代码,不仅实现了GIF动画的播放,还支持透明GIF动画的播放

Draw(HDC hDC,HWND hWnd,int XDest,int YDest)方法

 

if(m_GIFImageDecoder==0)

     {

         return 0;

     }

    

     //选择某个维面上的某一贞做为当前的活动贞

     m_GIFImageDecoder->SelectActiveFrame(&m_pdi,m_nCurPage);

     m_GIFImageDecoder->BeginDecode(m_GIFImageSink,NULL);

     /*while (E_PENDING == (m_GIFImageDecoder->Decode()))

     {

         Sleep(10);

     }*/

     m_GIFImageDecoder->Decode();

     m_GIFImageDecoder->EndDecode(E_FAIL);

 

     RECT rt;

    

     rt.left=XDest;

     rt.top=YDest;

     rt.right=XDest+m_iif.Width;

     rt.bottom=YDest+m_iif.Height;

 

     HDC hdcMemory=CreateCompatibleDC(hDC);

     HBITMAP hBitmapMemory=CreateCompatibleBitmap(hDC,m_iif.Width,m_iif.Height);

     HBITMAP hOldBitmapMemory=(HBITMAP)SelectObject(hdcMemory,hBitmapMemory);

 

     HDC hdcbkMemory=CreateCompatibleDC(hDC);

     HBITMAP hBitmapbkMemory=CreateCompatibleBitmap(hDC,m_iif.Width,m_iif.Height);

     HBITMAP hOldbkBitmap=(HBITMAP)SelectObject(hdcbkMemory,hBitmapbkMemory);

     if(NULL==m_hBKBitmap)

     {

         BitBlt(hdcbkMemory,0,0,m_iif.Width,m_iif.Height,hDC,rt.left,rt.top,SRCCOPY);

         m_hBKBitmap=(HBITMAP)SelectObject(hdcbkMemory,hOldbkBitmap);         

     }

     SelectObject(hdcbkMemory,m_hBKBitmap);

     BitBlt(hdcMemory,0,0,m_iif.Width,m_iif.Height,hdcbkMemory,0,0,SRCCOPY);

     //SelectObject(hdcbkMemory,hOldbkBitmap);

     DeleteObject(hOldbkBitmap);

     DeleteObject(hBitmapbkMemory);

     DeleteDC(hdcbkMemory);

     hdcbkMemory=NULL;

     hOldbkBitmap=NULL;

     hBitmapbkMemory=NULL;

 

 

     m_GIFImage->Draw(hdcMemory,CRect(0,0,m_iif.Width,m_iif.Height),NULL);

     BitBlt(hDC,rt.left,rt.top,m_iif.Width,m_iif.Height,hdcMemory,0,0,SRCCOPY);

     SelectObject(hdcMemory,hOldBitmapMemory);

     DeleteObject(hBitmapMemory);

     DeleteObject(hOldBitmapMemory);

     //DeleteObject(hBitmapbkMemory);

     hBitmapMemory=NULL;

     hOldBitmapMemory=NULL;

     //hBitmapbkMemory=NULL;

     DeleteDC(hdcMemory);

     ReleaseDC(hWnd,hDC);

     //m_GIFImage->Draw(hDC,&rt,NULL);

     return TRUE;

posted on 2009-07-15 00:12  yongshi123  阅读(1570)  评论(0编辑  收藏  举报