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


     

    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. }  
  • 相关阅读:
    WPF中textbox控件的一些样式的后台写法
    SQL中left join、right join、inner join的区别
    WPF引用多个样式
    【转载】C#使用Split函数根据特定分隔符分割字符串
    单例模式
    简单工厂模式
    设计模式简介
    JavaScript--String
    JavaScript--Array
    JavaScript--Object
  • 原文地址:https://www.cnblogs.com/lisuyun/p/3303177.html
Copyright © 2020-2023  润新知