本文分享&備忘最近了解到的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