GDI+ gif文件的显示和格式转换

 

                                                GDI+ gif文件的显示和格式转换

           怎么获取gif文件的每一帧,并且显示出来呢?

 

            1.怎么用gid+显示gif文件

                总体思路:用Image装载图像,用Graphic显示图像。

               相关函数:

               (1)Image::FromFile可以从文件中加载一个图像。         

                       可以加载的文件类型有: BMP, GIF, JPEG, PNG, TIFF, and EMF

                       Image* image = Image::FromFile(_T("res//test.gif"));

 

               (2)Image::GetFrameDimensionsCount 返回一个所谓的“维度”的个数,

                     每个维 度可能包含多个帧,gif文件就是包含1个维度,然后维度中可能包含

                     不定数目的帧。

                      UINT count  = image->GetFrameDimensionsCount();

 

               (3)Image::GetFrameDimensionsList 就是获得这些维度的GUID列表。

                       先分配count个GUID的数组。

                       GUID *pDimensionIDs=(GUID*)new GUID[count];
                       image->GetFrameDimensionsList(pDimensionIDs, count);

               (4)Image::GetFrameCount获得指定的“维数”有多少帧。

                     UINT   FrameNums=image->GetFrameCount(&pDimensionIDs[0]);

 

                 (5) 获得每帧之间的时间间隔。

                       PropertyTagFrameDelay是GDI+中预定义的一个GIG属性ID值,表示标

                       签帧数据的延迟时间。

                       

                       先调用 Image::GetPropertyItemSize获得有多少个时间间隔属性item.

                       然后调用Image::GetPropertyItem填充获得的items.

 

                       UINT   FrameDelayNums=image->GetPropertyItemSize  

                       (PropertyTagFrameDelay);

 


                       PropertyItem *  lpPropertyItem=new  PropertyItem

                       [FrameDelayNums];


                      image->GetPropertyItem

                      (PropertyTagFrameDelay,FrameDelayNums,lpPropertyItem);

 

                      时间间隔就保存在PropertyItem的value成员中。

 

                (6)最后,用一个while循环来循环显示每一帧。

                        Image::SetActiveFrame来设置显示那一帧。

 

                  总体的代码如下:

 

                     

                      

                       

                       

 

                 

  1. //装载gif文件  
  2. Image* image = Image::FromFile(_T("res//test.gif"));  
  3.   
  4. //获得有多少个维度,对于gif就一个维度  
  5. UINT count  = image->GetFrameDimensionsCount();  
  6. GUID *pDimensionIDs=(GUID*)new GUID[count];  
  7. image->GetFrameDimensionsList(pDimensionIDs, count);  
  8. TCHAR strGuid[39];  
  9. StringFromGUID2(pDimensionIDs[0], strGuid, 39);  
  10. UINT frameCount=image->GetFrameCount(&pDimensionIDs[0]);  
  11.   
  12. delete []pDimensionIDs;     
  13.   
  14.    //获得这个维度有多少个帧  
  15. UINT   FrameNums=image->GetFrameCount(&pDimensionIDs[0]);  
  16.   
  17.   
  18. //获得各帧之间的时间间隔  
  19. //先获得有多少个时间间隔,PropertyTagFrameDelay是GDI+中预定义的一个GIG属性ID值,表示标签帧数据的延迟时间  
  20.    UINT   FrameDelayNums=image->GetPropertyItemSize(PropertyTagFrameDelay);  
  21.   
  22.   
  23. PropertyItem *  lpPropertyItem=new  PropertyItem[FrameDelayNums];  
  24. image->GetPropertyItem(PropertyTagFrameDelay,FrameDelayNums,lpPropertyItem);  
  25.   
  26.   
  27.   
  28. //Guid的值在显示GIF为FrameDimensionTime,显示TIF时为FrameDimensionPage  
  29. int    FrameCount=0;  
  30. GUID    Guid = FrameDimensionTime;  
  31.    image->SelectActiveFrame(&Guid,FrameCount);  
  32. while(true)  
  33. {  
  34.     Graphics   gh(pDC->GetSafeHdc());  
  35.   
  36.     //显示当前帧  
  37.        gh.DrawImage(image,0,0,image->GetWidth(),image->GetHeight());  
  38.   
  39.     //时间间隔  
  40.     long lPause = ((long*)lpPropertyItem->value)[FrameCount]*10;  
  41.     Sleep(lPause);   
  42.   
  43.   
  44.     //设置当前需要显示的帧数  
  45.     if ((FrameCount+1)==FrameNums)  
  46.     {   //如果已经显示到最后一帧,那么重新开始显示  
  47.         FrameCount=0;  
  48.         image->SelectActiveFrame(&Guid,0);  
  49.     }  
  50.     else  
  51.     {  
  52.         image->SelectActiveFrame(&Guid,++FrameCount);  
  53.     }  
  54.       
  55. }  

 

 

 

         2.怎么将gif中的某一帧提取出来,保存为其他的文件格式。

            (1) Image::Save函数

                               Status Save(      

     const WCHAR *filename,      const CLSID *clsidEncoder,      const EncoderParameters *encoderParams );
                 其中第一个参数是表示要保存的文件名称,第二个参数是想采用的编码器,不同
                  的图片格式对应的编码器也不一样。第三个参数设为NULL即可。
             (2)要得到参数2,必须调用函数:
                     Image::GetImageEncodersSize来获得编码器列表
                     Image::GetImageEncoders来获得对应的编码器相关信息(包括CLSID)

              下面是相关的代码:
  1. //获得指定格式的编码器的CLSID  
  2. int CTestGifImageDlg::GetEncoderClsid(const WCHAR* format, CLSID* pClsid)  
  3. {  
  4.     UINT  num = 0;          // number of image encoders  
  5.     UINT  size = 0;         // size of the image encoder array in bytes  
  6.     ImageCodecInfo* pImageCodecInfo = NULL;  
  7.     GetImageEncodersSize(&num, &size);  
  8.     if(size == 0)  
  9.         return -1;  // Failure  
  10.     pImageCodecInfo = (ImageCodecInfo*)(malloc(size));  
  11.     if(pImageCodecInfo == NULL)  
  12.         return -1;  // Failure  
  13.     GetImageEncoders(num, size, pImageCodecInfo);  
  14.     for(UINT j = 0; j < num; ++j)  
  15.     {  
  16.         if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )  
  17.         {  
  18.             *pClsid = pImageCodecInfo[j].Clsid;  
  19.             free(pImageCodecInfo);  
  20.             return j;  // Success  
  21.         }      
  22.     }  
  23.     free(pImageCodecInfo);  
  24.     return -1;  // Failure  
  25. }  
  26.   
  27.   
  28. bool CTestGifImageDlg::DrawGifFrame(CDC *  pDC)  
  29. {  
  30.     //装载gif文件  
  31.     Image* image = Image::FromFile(_T("res//test.gif"));  
  32.   
  33.             //获得有多少个维度,对于gif就一个维度  
  34.     UINT count  = image->GetFrameDimensionsCount();  
  35.     GUID *pDimensionIDs=(GUID*)new GUID[count];  
  36.     image->GetFrameDimensionsList(pDimensionIDs, count);  
  37.     TCHAR strGuid[39];  
  38.     StringFromGUID2(pDimensionIDs[0], strGuid, 39);  
  39.     UINT frameCount=image->GetFrameCount(&pDimensionIDs[0]);  
  40.   
  41.     delete []pDimensionIDs;     
  42.   
  43.     //获得这个维度有多少个帧  
  44.     UINT   FrameNums=image->GetFrameCount(&pDimensionIDs[0]);  
  45.   
  46.        //将第一帧转换为png图片保存  
  47.        GUID    Guid = FrameDimensionTime;  
  48.     image->SelectActiveFrame(&Guid,0);  
  49.   
  50.         //保存  
  51.     CLSID  encoderClsid;  
  52.     if(GetEncoderClsid(_T("image/png"), &encoderClsid) >= 0)  
  53.     {  
  54.       image->Save(_T("pngfiles//test.png"),&encoderClsid,NULL);  
  55.     }  
  56.   
  57.   
  58.   
  59. }  
posted on 2013-09-05 13:57  言止予思  阅读(602)  评论(0编辑  收藏  举报