Mobil手机加载GIF动态图像的方法有两种,一个就是使用GIF89a标准算法,另一个就是使用SDK自带的Imaging组件,这两种方法是很典型的手机图像处理技术的实践。使用Imaging组件加载GIF比使用标准算法处理高效的多,特别是在处理真彩GIF动画表现更加突出。
Imaging组件中封装了对大部分图片格式的编解码算法,并以接口的形式提供给开发人员使用。Imaging组件是GDI+的微缩版。但是在实际使用上又有很大的不同。使用Imaging组件来加载GIF动态图片调用了几乎所有的Imaging接口,看看我们将要用到的接口:
IImagingFactory:图像操作最初要用到的接口,它的接口方法全是带CreateXXX的函数,可见他的制造工厂的特性。使用前需要调用CoCreateInstance初始化。
IImageDecoder:主要的图像操作接口,用来处理从大部分图像格式中获取数据。
IbitmapImage:主要的图位操作接口,这里能够对具体的图像像素进行运算。
IImage:主要的图形控制接口,也许是Imaging组件唯一的绘制接口
IImageSink:这个东东似乎是一个过渡性质的接口,它的亮点在它的sink的动词解释上:沉!
操作:
首先我们要使用IImagingFactory的CreateImageDecoderppy初始化IimageDecoder。使用这个方法取得GIF图像数据,用IimagingFactory的CreateNewBitmap初始化IbitmapImage。通过这个接口执行QueryInterface取得IImage和IimageSink,然后调用IimageDecoder的SelectActiveFrame设定当前的图像块数据。此时对获得的IimageSink进行decode,decode完毕后调用Iimage接口的draw方法,此时画出的就是指定的那个图像块图像。
部分代码:
文件到流的转化
1 HRESULT CGIFImage::CreateStreamOnFile(const TCHAR * tszFilename, IStream ** ppStream)
2
3 {
4
5 HRESULT hrRet = S_OK;
6
7 HGLOBAL hg = NULL;
8
9 HANDLE hGIFFile = NULL;
10
11 DWORD dwSize, dwRead;
12
13 BYTE* pbLocked = NULL;
14
15
16
17 // 建立一个文件池,我管CreateFile返回的handle这个叫文件池
18
19 hGIFFile = CreateFile(tszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
20
21 //当handle地址为-1时表示没有创建成功
22
23 if (INVALID_HANDLE_VALUE == hGIFFile)
24
25 {
26
27 hrRet = E_PENDING + GetLastError();
28
29 goto error;
30
31 }
32
33 dwSize = GetFileSize(hGIFFile, NULL);
34
35 //当尺寸溢出时放弃
36
37 if (INVALID_FILE_SIZE == dwSize)
38
39 {
40
41 hrRet = E_PENDING + GetLastError();
42
43 goto error;
44
45 }
46
47
48
49 // 分配一个文件尺寸相同的活动内存池
50
51 hg = GlobalAlloc(GMEM_MOVEABLE, dwSize);
52
53 //分配失败即放弃
54
55 if (NULL == hg)
56
57 {
58
59 hrRet = E_PENDING + GetLastError();
60
61 goto error;
62
63 }
64
65
66
67 //使用GlobalLock得到内存指针
68
69 pbLocked = (BYTE*) GlobalLock(hg);
70
71 //lock失败放弃
72
73 if (NULL == pbLocked)
74
75 {
76
77 hrRet = E_PENDING + GetLastError();
78
79 goto error;
80
81 }
82
83
84
85 // copy the file
86
87 if (!ReadFile(hGIFFile, pbLocked, dwSize, &dwRead, NULL))
88
89 {
90
91 hrRet = E_PENDING + GetLastError();
92
93 goto error;
94
95 }
96
97
98
99 GlobalUnlock(hg);
100
101
102
103 // 创建文件流
104
105 hrRet = CreateStreamOnHGlobal(hg, TRUE, ppStream);
106
107
108
109 CloseHandle(hGIFFile);
110
111 return hrRet;
112
113 error:
114
115 if (pbLocked)
116
117 GlobalUnlock(hg);
118
119 if (hg)
120
121 GlobalFree(hg);
122
123 if (hGIFFile)
124
125 CloseHandle(hGIFFile);
126
127 return hrRet;
128
129
130
131
文件加载
Code
在定时器中执行下面代码,不仅实现了GIF动画的播放,还支持透明GIF动画的播放
Draw(HDC hDC,HWND hWnd,int XDest,int YDest)方法
1 if(m_GIFImageDecoder==0)
2
3 {
4
5 return 0;
6
7 }
8
9 //选择某个维面上的某一贞做为当前的活动贞
10
11 m_GIFImageDecoder->SelectActiveFrame(&m_pdi,m_nCurPage);
12
13 m_GIFImageDecoder->BeginDecode(m_GIFImageSink,NULL);
14
15 /*while (E_PENDING == (m_GIFImageDecoder->Decode()))
16
17 {
18
19 Sleep(10);
20
21 }*/
22
23 m_GIFImageDecoder->Decode();
24
25 m_GIFImageDecoder->EndDecode(E_FAIL);
26
27
28 RECT rt;
29
30 rt.left=XDest;
31
32 rt.top=YDest;
33
34 rt.right=XDest+m_iif.Width;
35
36 rt.bottom=YDest+m_iif.Height;
37
38
39 HDC hdcMemory=CreateCompatibleDC(hDC);
40
41 HBITMAP hBitmapMemory=CreateCompatibleBitmap(hDC,m_iif.Width,m_iif.Height);
42
43 HBITMAP hOldBitmapMemory=(HBITMAP)SelectObject(hdcMemory,hBitmapMemory);
44
45
46
47 HDC hdcbkMemory=CreateCompatibleDC(hDC);
48
49 HBITMAP hBitmapbkMemory=CreateCompatibleBitmap(hDC,m_iif.Width,m_iif.Height);
50
51 HBITMAP hOldbkBitmap=(HBITMAP)SelectObject(hdcbkMemory,hBitmapbkMemory);
52
53 if(NULL==m_hBKBitmap)
54
55 {
56
57 BitBlt(hdcbkMemory,0,0,m_iif.Width,m_iif.Height,hDC,rt.left,rt.top,SRCCOPY);
58
59 m_hBKBitmap=(HBITMAP)SelectObject(hdcbkMemory,hOldbkBitmap);
60
61 }
62
63 SelectObject(hdcbkMemory,m_hBKBitmap);
64
65 BitBlt(hdcMemory,0,0,m_iif.Width,m_iif.Height,hdcbkMemory,0,0,SRCCOPY);
66
67 //SelectObject(hdcbkMemory,hOldbkBitmap);
68
69 DeleteObject(hOldbkBitmap);
70
71 DeleteObject(hBitmapbkMemory);
72
73 DeleteDC(hdcbkMemory);
74
75 hdcbkMemory=NULL;
76
77 hOldbkBitmap=NULL;
78
79 hBitmapbkMemory=NULL;
80
81
82 m_GIFImage->Draw(hdcMemory,CRect(0,0,m_iif.Width,m_iif.Height),NULL);
83
84 BitBlt(hDC,rt.left,rt.top,m_iif.Width,m_iif.Height,hdcMemory,0,0,SRCCOPY);
85
86 SelectObject(hdcMemory,hOldBitmapMemory);
87
88 DeleteObject(hBitmapMemory);
89
90 DeleteObject(hOldBitmapMemory);
91
92 //DeleteObject(hBitmapbkMemory);
93
94 hBitmapMemory=NULL;
95
96 hOldBitmapMemory=NULL;
97
98 //hBitmapbkMemory=NULL;
99
100 DeleteDC(hdcMemory);
101
102 ReleaseDC(hWnd,hDC);
103
104 //m_GIFImage->Draw(hDC,&rt,NULL);
105
106 return