通过CImageDecoder解码显示GIF动画

CGif_Reader是一个简单的GIF动画解析类,可以用来显示一个GIF动画在CCoeControl上。要构造CGif_Reader的话,需要增加下列代码在您containerConstructL()函数中。

iGif_Reader = new(ELeave)CGif_Reader(*this);

iGif_Reader->ConstructL(KTxtFileName);

KTxtFileName是一个GIF文件名称(有完整的路径包括盘符,路径,扩展名)。要绘制GIF动画你需要在containerDraw()中完成如下代码

void CMycontainer::Draw(const TRect& aRect) const

{

    CWindowGc& gc = SystemGc();       

    if(iGifReader)
 {
  if(iGifReader->Bitmap())
  {
   if(iGifReader->Bitmap()->Handle())
   {
   gc.DrawBitmap(aRect, iGifReader->Bitmap());                
   }
  }       
 }

}

 

Gif_Reader.cpp

#include "Gif_Reader.h"

 

#include <cntfield.h>

#include <cntdef.h>

#include <cntitem.h>

#include <cntfldst.h>

#include <cntdb.h>

#include <COEMAIN.H>

#include <akniconutils.h>

 

_LIT8(KtxTypeImageGif_8                     ,"image/gif");

 

const TInt KFrameTimeOut = 200000;// 0.2 sec frame timeout

 

 

CGif_Reader::CGif_Reader(CCoeControl& aParent)

:

CActive(0), iParent(aParent), iCurrImg(-1)

    {

    }

 

CGif_Reader::~CGif_Reader()

{

         Cancel();

         delete iExampleTimer;

         delete iImageDecoder;

         delete iFrame;

         delete iFrameImg;

         delete iFrameMsk;

 

         delete iBitmapDevice;

         delete iGraphicsContext;

}

 

 

void CGif_Reader::ConstructL(const TDesC& aFileName)

{

         CActiveScheduler::Add(this);

         iImageDecoder = CImageDecoder::FileNewL(CCoeEnv::Static()->FsSession(),

aFileName, KtxTypeImageGif_8);

         iCurrCount = iImageDecoder->FrameCount();

 

         if(iCurrCount > 0)

         {

                 iFrame = new(ELeave)CFbsBitmap();

                 iFrame->Create(iImageDecoder->FrameInfo(0).iOverallSizeInPixels,

iImageDecoder->FrameInfo(0).iFrameDisplayMode);

 

                 iBitmapDevice = CFbsBitmapDevice::NewL(iFrame);

                 User::LeaveIfError(iBitmapDevice->CreateContext(iGraphicsContext));

         }

}

 

void CGif_Reader::TimerExpired(TAny* /*aTimer*/, TInt /*aError*/)

{

         Cancel();

         NextImageL();

}

 

 

void CGif_Reader::NextImageL(void)

{

         iCurrImg++;

         if(iCurrImg >= iCurrCount || iCurrImg < 0)

         {

                 iCurrImg = 0;

         }

 

         delete iFrameImg;

         iFrameImg = NULL;

         iFrameImg = new(ELeave)CFbsBitmap();

         iFrameImg->Create(iImageDecoder->FrameInfo(iCurrImg).iOverallSizeInPixels,

iImageDecoder->FrameInfo(iCurrImg).iFrameDisplayMode);

 

         delete iFrameMsk;

         iFrameMsk = NULL;

         iFrameMsk = new(ELeave)CFbsBitmap();

         iFrameMsk->Create(iImageDecoder->FrameInfo(iCurrImg).iOverallSizeInPixels,

EGray2);

 

         iImageDecoder->Convert(&iStatus, *iFrameImg, *iFrameMsk, iCurrImg);

         SetActive();    

}

 

 

void CGif_Reader::DoCancel()

{

         iImageDecoder->Cancel();

}

 

CFbsBitmap* CGif_Reader::Bitmap()

{

         return iFrame;

}

 

 

void CGif_Reader::RunL()

{

         if(iFrameMsk && iFrameImg && iFrame && iGraphicsContext)

         {

                 if(iFrameMsk->Handle() && iFrameImg->Handle() && iFrame->Handle())

                 {

                          if(TFrameInfo::ERestoreToBackground & iImageDecoder->FrameInfo(iCurrImg).iFlags)

                          {

                                   iGraphicsContext->DrawBitmap(

TRect(0, 0, iFrame->SizeInPixels().iWidth, iFrame->SizeInPixels().iHeight),

iFrameImg);

                          }

                          else

                          {

                                   iGraphicsContext->DrawBitmapMasked(iImageDecoder->FrameInfo

 

(iCurrImg).iFrameCoordsInPixels,

iFrameImg, TRect(0, 0, iFrameImg->SizeInPixels().iWidth, iFrameImg->SizeInPixels().iHeight),

iFrameMsk, EFalse);

                          }

                 }

         }

 

         iParent.DrawNow();       

 

         if(iStatus.Int() != KErrCancel)

         {

                 if(!iExampleTimer)

                 {

                          iExampleTimer = CExampleTimer::NewL(CActive::EPriorityStandard, *this);

                 }       

 

                 iExampleTimer->After(KFrameTimeOut);

         }

}

 

Gif_Reader.h

#include <e32base.h>

#include <coecntrl.h>

#include <w32std.h>

#include <e32std.h>

#include <cntdef.h>

#include <cntdb.h>

#include <ImageConversion.h>

 

#include "CExampleTimer.h"

 

 

 

         class CGif_Reader : public CActive,MExampleTimerNotify

         {

         public:

             CGif_Reader(CCoeControl& aParent);

             void ConstructL(const TDesC& aFileName);

             ~CGif_Reader();

             CFbsBitmap* Bitmap();

         protected:

                 void TimerExpired(TAny* aTimer,TInt aError);

                 void DoCancel();

                 void RunL();

         private:

                 void NextImageL(void);

                 void FinnishReadL(void);

         private:

                 CCoeControl&              iParent;

                 TInt                               iCurrImg,iCurrCount;

                 CImageDecoder*            iImageDecoder;

                 CFbsBitmap*                        iFrame;

                 CFbsBitmap*                        iFrameMsk;

                 CFbsBitmap*                        iFrameImg;

                 CExampleTimer*            iExampleTimer;

                 CFbsBitGc*                         iGraphicsContext;

                 CFbsBitmapDevice*         iBitmapDevice;

         };

 

 

使用GDI+库显示gif动态图片,该类接口如下: 可以看出,该ImageEx完全继承了基类的接口函数。 说明: 如果打开非多帧图片,该类几乎完全等价于基类,比如你可以把该类的对象代入Graphics类系列的成员函数中; 如果打开的是多帧的图片,你只要打开图片后不调用InitAnimation函数(它会创建线程),则上述做法依然可以; 但如果调用InitAnimation函数后(单帧图像没关系,因为不会创建线程),则不可以了, 所有的基类继承过来的接口成员函数和配合gdi+库其他类的函数调用都是不可以的,因为没有作线程同步, 你只能调用下面位数不多的几个public成员函数,调用Destroy成员函数后,则就可以了,因为它会关闭线程。 其实你会发现下面的public成员函数操作的成员变量都是新增的成员变量,没涉及到线程同步问题。 class ImageEx : public Image { public: //以长度为nSize的内存pBuff中的内容构造图像 ImageEx(const void* pBuff, size_t nSize, BOOL useEmbeddedColorManagement = FALSE); //以类型为sResourceType,名称为sResource的资源构造图像 ImageEx(LPCTSTR sResourceType, LPCTSTR sResource, BOOL useEmbeddedColorManagement = FALSE); //以文件构造图像 ImageEx(LPCTSTR filename, BOOL useEmbeddedColorManagement = FALSE); //调用Destroy成员函数 ~ImageEx(); public: //如果已经构造的对象是动画,则创建动画线程,并返回true, //如果为静态图像或已经创建过动画线程,则也返回false // 图像将绘制在m_hWnd客户区的rect区域,会拉伸,支持镜像 bool InitAnimation(HWND hWnd, RECT rect); //判断是否为动画 bool IsAnimatedGIF() { return m_nFrameCount > 1; } //设置动画暂停与否 void SetPause(bool bPause); //判断动画是否处于暂停状态 bool IsPaused() { return m_bPause; } //关闭动画,事实上基类Image中还有的两个成员变量没有关闭,因为析构函数会调用基类析构函数进行关闭的 void Destroy(); //另外的非public的东西省略.. }; 用法: MFC对话框程序在下面添加: BOOL CTestDlgDlg::OnInitDialog() { CDialog::OnInitDialog(); //其它的初始化代码 // GDI+ //m_image为ImageEx指针类型成员变量,"GIF"为资源类型,"HEARTS"为资源名称 m_image = new ImageEx( _T("GIF"), _T("HEARTS") ); RECT rc; GetClientRect(&rc); m_image->InitAnimation(this->m_hWnd, rc);//创建gif播放线程 return TRUE; // return TRUE unless you set the focus to a control } CTestDlgDlg::~CTestDlgDlg() { // GDI+ delete m_image; } 其中的m_image = new ImageEx( _T("GIF"), _T("HEARTS") );你可以换成ImageEx类的另外两个构造函数
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值