本文分享&备忘最近了解到的icon资源在windows平台下相关的一部分知识。所有测试代码都尽可能的依赖win32 API实现。通过源码可以了解其结构,同时它们也是可复用的代码积累。
内容摘要:如何保存exe的图标为*.ico文件、如何遍历PE文件的icon资源并保存为*.ico文件、如何合并多个*.ico文件、如何分割含有多张图片的*.ico文件
一、 保存exe的图标为*.ico文件
exe在windows shell下的可显示图标有3或者4种,使用win32 API获取它们的ICON handle的代码也很简单,前一篇文章已经说过。这里主要难点是如何根据ico文件的存储格式,把HICON保存为*.ico文件。
文件格式:icon文件头 + directory entrys + bmp header info and color table + image data + mask data。
思路:从HICON拿到两个BITMAP HANDLE,从Color HANDLE拿到ICON image data,从MaskHandle拿到mask data,从两HANDLE拿到bmp header 的数据。所有数据拿到后写入文件,循环处理多个HICON。
256*256 icon的说明:这是windows vista+版本才有的。虽然可以加载保存为png格式的*.ico文件,但是GDI并没有提供直接操作png图片的API,我写的工具保存256 * 256 icon图片为BMP格式,会比较大。注意到在directory entry中各只有一个字节保存icon的的长、宽,所以256*256的图片该位置的值是0。
HICON保存为*.ico文件的详细代码见:https://github.com/cswuyg/icon_tool/blob/master/save_exe_iconfile/model/save_icon_file_by_handle.cc
二、抽取PE文件的icon资源
使用EnumResourceNames枚举到资源,通过CreateIconFromResourceEx从资源获取到HICON,之后就是HICON到*.ico的过程。也可以尝试加个icon文件头后直接把资源写入到文件(我未做测试验证)。
枚举PE文件所有*.ico资源的HICON的详细代码:https://github.com/cswuyg/icon_tool/blob/master/enum_pe_all_icons/model/enum_all_icons.cc
三、合并*.ico文件
这里不需要涉及资源API,纯粹是文件数据操作。
思路:把所有*.ico文件的数据读取出来,再把数据按照一个*.ico文件的格式找位置写到一个文件里。我的做法是先读取每个源文件的前6个字节,拿到了所有图片的数量,算出directory entry的占用的size,这样就可以定位到目标文件图片实际数据的初始位置,后面再循环处理一个个ico文件,写入图片数据和entry。小工具不暂考虑一个源文件被读两次的性能问题~
合并*.ico文件的详细代码:https://github.com/cswuyg/icon_tool/blob/master/combine_iconfiles/model/combine_iconfile_impl.cc
四、分割含有多张图片的*.ico文件
这里也不需要涉及资源API,纯粹是文件数据操作。
思路:读取*.ico文件头的前6个字节,拿到图片个数,循环读取对应的directory entry和图片数据,把新的*ico文件头、新的directory entry、图片数据写入到新的独立目标文件。
五、工具release
1、找出EXE的所有windows shell可显示icon,并保存到一个*.ico文件中;
2、找出PE文件的所有icon,并按组保存;
3、合并*.icon文件;
4、将*icon中的图片一个个分割保存;
工具所在:https://github.com/cswuyg/icon_tool/tree/master/tool%20release
代码project:https://github.com/cswuyg/icon_tool
本文所在:http://www.cnblogs.com/cswuyg/p/3619687.html
六、参考资料
1、Icon资源详解[1]:http://www.cnblogs.com/cswuyg/p/3603707.html
2、不错的代码资源:http://chironexsoftware.com/blog/?p=26 ; http://chironexsoftware.com/blog/?p=30