分享
 
 
 

基于IImgCtx的图像解码器

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

作者:马健

邮箱:stronghorse@tom.com主页:http://stronghorse.yeah.net

一、为什么要使用IImgCtx进行图像解码?

在Windows下开发图像显示、图像处理软件的时候,第一步要面对的就是图像解码。目前免费的图像解码代码不少,单独的包括:

Independent JPEG Group(独立JPEG小组)发布的专门解JPEG格式的源代码

libpng组织提供的专门解png格式的源代码

libtiff组织提供的专门解TIFF格式的源代码

giflib组织提供的专门解gif格式的源代码

如果觉得一个、一个去找这些源代码太麻烦,也可以使用Davide Pizzolato开发的CxImage,其中集成了对大多数常见图像格式的解码源代码。

但是在我用过这些源代码后,也发现一些问题:

用起来太麻烦了,不仅在编译的时候需要对编译参数进行设置,而且解码后的图像用起来也麻烦。

可靠性令人怀疑,而且在出错后,跟踪、调试太难了,那一大堆C代码不是好玩的。

所有的解码代码都需要嵌入编译后生成的EXE文件,或DLL中,增加了最终发行包的尺寸。当然如果最终用户希望到手的是一个“大型软件”,则另当别论。

所以我和其它一些“懒”程序员一样,也希望能够找到一个像Windows

API那样,用起来方便,生成的代码又小的通用图像解码器。

根据我在网上看到的资料,我最先考虑使用Windows本身提供的IPicture接口。这个接口在MSDN中有非常详细的说明,在codegurucodeproject上也有详细的例子可供参考,用起来很方便。可惜的是,这个接口只能解码BMP、WMF、ICO、GIF、JPG格式(公开文档只承认可以解BMP、WMF、ICO)的图像,对PNG、TIFF格式无效。

后来在安装Windows系统的时候,我发现缺省情况下,Windows下GIF、PNG、JPG文件都被关联到了IE浏览器,再仔细想想,这些图像都经常在网页中出现,所以IE支持他们也没有什么好奇怪的。那么IE内核有没有提供什么接口,就好像可以用IHTMLDocument解析HTML源代码一样,可以供我们进行图像解码呢?

答案是:有的,就是IImgCtx接口。这个接口可以解码所有能够在IE中显示的图像格式,包括JPG、PNG、GIF、BMP、WMF、ICO,有时也能解TIFF(后面我会解释为什么说“有时”)。

二、如何使用IImgCtx进行图像解码?

在我手头的IE 5.5 SDK包中,有对IImgCtx接口的完整定义(在IImgCtx.h文件中),在VC++

6的安装目录中,也有对这个接口的定义,文件名一样,文件内容也只差了一行:IE

5.5 SDK包中多定义了一个常量DWN_MIRRORIMAGE,估计是IE 5.5比IE 4多出来的东西,可以对解码出来的图像进行镜像翻转。

但是不要说在MSDN中找,就算是用google搜,也找不到对这个接口的任何说明。好在这个接口比较简单,从接口定义还能大致猜测到它的用法:

DECLARE_INTERFACE_(IImgCtx, IUnknown)

{

#ifndef NO_BASEINTERFACE_FUNCS

/* IUnknown methods */

STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;

STDMETHOD_(ULONG, AddRef)(THIS) PURE;

STDMETHOD_(ULONG, Release)(THIS) PURE;

#endif

/* IImgCtx methods */

/* Initialization/Download methods */

STDMETHOD(Load)(THIS_ LPCWSTR pszUrl, DWORD dwFlags) PURE;

STDMETHOD(SelectChanges)(THIS_ ULONG ulChgOn, ULONG ulChgOff, BOOL fSignal) PURE;

STDMETHOD(SetCallback)(THIS_ PFNIMGCTXCALLBACK pfn, void * pvPrivateData) PURE;

STDMETHOD(Disconnect)(THIS) PURE;

/* Query methods */

STDMETHOD(GetUpdateRects)(THIS_ struct tagRECT FAR* prc, struct tagRECT FAR* prcImg, long FAR* pcrc) PURE;

STDMETHOD(GetStateInfo)(THIS_ ULONG FAR* pulState, struct tagSIZE FAR* psize, BOOL fClearChanges) PURE;

STDMETHOD(GetPalette)(THIS_ HPALETTE FAR* phpal) PURE;

/* Rendering methods */

STDMETHOD(Draw)(THIS_ HDC hdc, struct tagRECT FAR* prcBounds) PURE;

STDMETHOD(Tile)(THIS_ HDC hdc, struct tagPOINT FAR* pptBackOrg, struct tagRECT FAR* prcClip, struct tagSIZE FAR* psize) PURE;

STDMETHOD(StretchBlt)(THIS_ HDC hdc, int dstX, int dstY, int dstXE, int dstYE, int srcX, int srcY, int srcXE, int srcYE, DWORD dwROP) PURE;

};

从接口上看,在创建IImgCtx接口对象后,可以用Load方法调入图像文件,解码完成后即可用Draw方法显示了,不过:

Load方法中的参数指明是一个URL(估计是IE内核的要求),因此需要将本地文件名转换成file://开头的URL,并且必须使用Unicode编码。

与IE中的其它接口一样,IImgCtx工作过程也是异步的,所以才需要SetCallback方法设置回调函数,SelectChanges方法对状态进行监视,不过由于实在找不到什么资料,所以我也不知道这两个接口怎么用。我只知道对于这种异步处理过程,必须创建消息泵,对解码过程中产生的消息进行分发,否则解码过程会被吊住。

Draw方法允许传入一个HDC作为目标DC,如果这个HDC是一个内存DC,即可不显示,直接在内存中对图像进行解码。解码出来的图像是DDB,再转换成DIB后,即可进行常规图像处理。

用IImgCtx进行解码的详细过程见实例文件中的WndImgCtx.cpp。

三、如何将实例源代码集成到VC++工程中?

本文提供的实例包含在ImgViewer.zip中,解开后是一个完整的VC++

6工程。其中除了包含用IImgCtx对图像进行解码的代码外,还包含一个对目录中的文件进行搜索、排序,实现顺序浏览目录中所有图像的实例代码。

如果只需要使用图像解码部分,将WndImgCtx.h、WndImgCtx.cpp包含到你的工程中,在需要用到解码功能的CPP文件开头加入:

#include "WndImgCtx.h"

然后就可以调用

HBITMAP GetBitmapFromFile(LPCTSTR pszFilename);

函数进行解码。从函数原型上即可看出,这个函数传入一个文件路径,返回一个DDB句柄。

如果需要包含顺序显示目录下所有图像的功能,将SrchDir.h、SrchDir.cpp、DirMng.h、DirMng.cpp包含到你的工程中,具体使用方法见MainFrm.cpp中的相关代码。

从使用的效果来看,在Windows 98/Me下,IImgCtx解码TIFF文件的时候有问题,在MSDN上也有几篇文章讨论在98/Me下IE显示不了TIFF的文章,不过照文章上说的进行设置,好像还是不行。在Windows

2000/XP下则没有什么问题。

四、为什么TIFF文件是一个例外?

IE几乎支持所有常见图像格式,包括JPEG、PNG、GIF等,但是在IE的“打开文件”对话框中,唯独不见TIFF。我用libtiff组织提供的TIFF图像例子,测试本文提供的图像浏览器实例,结果发现在98/Me/XP下,一个TIFF文件也打不开;在Windows

2000下,能够打开差不多一半,另一半打不开。

在Windows 2000下,在VC 6中按Debug模式编译、运行ImageViewer,打开TIFF文件,退出,在Output窗口中可以看到下列行:

Loaded 'C:\WINNT\system32\imgutil.dll', no matching symbolic information found.

Loaded 'C:\WINNT\system32\tifflt.dll', no matching symbolic information found.

Loaded 'C:\WINNT\system32\oieng400.dll', no matching symbolic information found.

Loaded 'C:\WINNT\system32\mscms.dll', no matching symbolic information found.

Loaded 'C:\WINNT\system32\winspool.drv', no matching symbolic information found.

而在Windows XP下,只能看到第一行,没有后续的行。

在Windows 2000中,运行regedit,然后搜索tifflt.dll,可以看到它提供“TIFFilter Class”,CLSID为

{EBD0F6B6-4AED-11D1-9CDB-00805F0C62F5} 。再继续在regedit32中搜索这个CLSID,可以在

HKEY_CLASSES_ROOT\MIME\Database\Content Type\image/tiff 项中,看到 Image

Filter CLSID 为这个值。在这个项的前面,还有 image/png、image/jpeg

等项,它们都有 Image Filter CLSID

这个键。从MSDN提供的文档可以知道,HKEY_CLASSES_ROOT\MIME\Database\Content

Type 项下列出的是IE能够识别的所有MIME type,MIME

type一般从web server返回的HTML包头提取。

从 Image Filter CLSID 这个键的名称来看,这个CLSID记录的应该就是图像解码器的CLSID。在Windows

98/Me/XP下运行regedit32,查找到HKEY_CLASSES_ROOT\MIME\Database\Content Type\image/tiff项,在它下面并没有

Image Filter CLSID 这个键。而在 image/png、image/jpeg

等项下面,都有这个键。这个大概就是为什么在Windows 98/Me/XP下,IE

无法解码TIFF文件的原因:没有对应的解码器。

我曾经尝试过将tifflt.dll移至到Windows XP下,但是因为DLL冲突,没有成功。看来要想在2000以外的Windows平台下显示TIFF文件,只有等待微软推出对应的TIFF解码器了。

五、进一步的练习

实例代码虽然演示了一个图像浏览器的最原始功能,但是要想成为一个真正的图像浏览器,还有很多需要改进的地方,有兴趣的可以试一下,就当做是练习好了:

支持在线浏览。其实IImgCtx本身就支持对网络图片进行解码,而且可以边解码边显示,就象在IE中一样。

支持从内存中显示图片,而不是读文件。这个需要一定的技巧,可以有两种简单点的办法:一种是架势web服务器,解码器按照http协议获取图片。在codeguru和codeproject上,有很多现成的web server代码,直接拿来用就好,自己只要考虑怎么填写返回内容即可。VC 6自带的MSDN光盘上,也带了一个名为HTTPSVR的例子,说明如何用MFC和WinSock创建web server。另一种是使用Asynchronous Pluggable Protocols(协议插件),到MSDN、codeguru和codeproject上搜索这几个关键字,从理论到源代码都能找出一堆,在这里我就不罗嗦了。

图像居中显示。这个相对容易一些。

对于大图像,支持用鼠标拖拽。这个应该是有现成例子可供参考,找一下吧。

支持图像处理。这个可以参考CxImage,它支持将DDB转换成DIB,然后对DIB进行各种处理。不过如果不使用其它图像编码代码的话,编辑完的图像大概只能存储成BMP文件。

支持浏览子目录下的图片。SrchDir.h、SrchDir.cpp、DirMng.h、DirMng.cpp都是我从ComicsViewer源代码中拷贝过来的,不过做了很多简化,有兴趣的可以再把我简化掉的东西试着补回去。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有