分享
 
 
 

Windows图标-Icon文件格式分析。

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

[原创]Windows图标-Icon文件格式分析。

最近想做个随时间变化显示为时间的秒数的动态变化图标,查找了很多资料,基本都是使用BitBlt+BuildIcon或CreateIcon等API函数来生成图标,感觉操作过程比较复杂,而且在Picture使用这些函数制造图标的话,运行效果不太理想,因此想到用现有的BMP位图数据换算为ICON文件保存后再用LoadPicture载入后使用还比较合用。找了很多关于图标的资料后,中文的VB构造ICON文件说明都没找到,最后只能自己利用图标制作工具生成些图标分析结合英文的关于C语言的图标构造说明来自己摸索出合适VB使用的ICON文件格式资料,因为在CSDN也没找到VB的图标文件说明,因此将自己的一些分析心得post上来以供大家交流。

ICON文件结构有点类似BMP文件,不过因为ICON文件支持多资源,所以比BMP文件多了一个索引目录的结构,以供检索文件内的各个图标资源。图像数据部分除了多一段1bpp的掩码部分以外,剩余的部分和BMP文件的位图信息段及图像信息段是相同的。

1.文件头

C原型定义:

typedef struct

{

word idreserved; // reserved (must be 0)

word idtype; // resource type (1 for icons)

word idcount; // how many images?

icondirentry identries[1]; // an entry for each image (idcount of 'em)

} icondir, *lpicondir;

VB定义:

Public Type icondir

idreserved As Integer '; word // reserved (must be 0):保留字必须是0

idtype As Integer '; word // resource type (1 for icons):资源类型,1是图标,2就是光标了?

idcount As Integer '; word // how many images?:有几个图像资源

identries() As icondirentry '[1]'icondirentry; // an entry for each image (idcount of 'em):每个图像的入口定义

End Type

文件内的资源个数由idcount来定义,读取文件的时候,先读入

idreserved As Integer

idtype As Integer

idcount As Integer

3个变量后,再用idcount来定义identries(idcount)类型的数量。

1.1 icondirentry结构,图标资源索引目录结构。

C原型定义:

typedef struct

{

byte bwidth; // width, in pixels, of the image

byte bheight; // height, in pixels, of the image

byte bcolorcount; // number of colors in image (0 if >=8bpp)

byte breserved; // reserved ( must be 0)

word wplanes; // color planes

word wbitcount; // bits per pixel

dword dwbytesinres; // how many bytes in this resource?

dword dwimageoffset; // where in the file is this image?

} icondirentry, *lpicondirentry;

VB定义:

Public Type icondirentry

bwidth As Byte ';byte // width, in pixels, of the image:图像宽度,以象素为单位。一个字节

bheight As Byte ';byte // height, in pixels, of the image:图像高度,以象素为单位。一个字节

bcolorcount As Byte ';byte // number of colors in image (0 if >=8bpp):图像中的颜色数(如果是>=8bpp的位图则为0)

breserved As Byte ';byte // reserved ( must be 0):保留字必须是0

wplanes As Integer ';word // color planes:为目标设备说明位面数,其值将总是被设为1

wbitcount As Integer ';word // bits per pixel:每象素所占位数。

dwbytesinres As Long ';dword // how many bytes in this resource?:这份资源所占字节数

dwimageoffset As Long ';dword // where in the file is this image?:图像数据(iconimage)起点偏移位置。

End Type ' icondirentry

其中dwbytesinres记录了该目录指向的图像数据区的尺寸,dwimageoffset指的是该段目录指向的图像数据段的起点在整个文件中的偏移量。

2.图像数据段

C原型定义:

typdef struct

{

bitmapinfoheader icheader; // dib header

rgbquad iccolors[1]; // color table

byte icxor[1]; // dib bits for xor mask

byte icand[1]; // dib bits for and mask

} iconimage, *lpiconimage;

VB定义:

Public Type iconimage '{

icheader As bmih ';DIB位图信息头:bitmapinfoheader // dib header,注:bmih 是我简化了bitmapinfoheader的名称。

' used: bisize, biwidth, biheight(xorH+andH)即2倍高度, biplanes, bibitcount, bisizeimage.

'all other members must be 0.

iccolors() As rgbq '[1]';色彩表:rgbquad // color table

icxor() As Byte '[1];byte // dib bits for xor mask:DIB结构的图像数据。XOR掩码?

'本文讨论的格式以16色的ICON文件为主,每字节表示两个象素4bpp。

'对于256色的文件,icxor数组每字节表示一个象素即:8bpp。

icand() As Byte '[1];byte // dib bits for and mask:DIB结构的图像数据。AND掩码?1bpp

End Type '} iconimage

其中的icheader采用的是DIB结构的BMP文件(常用)的位图信息头的定义类型(参见BMP文件结构分析),但是其中使用的关键变量只用到:bisize, biwidth, biheight, biplanes, bibitcount, bisizeimage.几个,其他变量必须为0。其中的biheight变量和BMP文件里稍有不同,在BMP文件里,该变量指的是文件的高度象素量,而在ICON文件里,可能由于采用了两段掩码图像数据的缘故,该变量的值一般设定为高度象素量的2倍。

色彩表iccolors的尺寸由文件使用的色彩数量决定,对于16色的图像数据为:iccolors(0 to 15),对于256色的图像数据为:iccolors(0 to 255)。但这个数量不是绝对的,

最后定义的时候还是应该由icheader中的bisize, biwidth, biheight, bibitcount变量和索引目录中的dwbytesinres计算得出=(dwbytesinres - biSize - AndMaskall - (biHeight / 2) * Lb)/4 '其中AndMaskall为1bpp那段掩码的尺寸,Lb为每行象素所占的字节数。

icxor数据尺寸为Lb乘以图标高度(biHeight / 2)。icand尺寸为1bpp的掩码数据段每行所占字节数乘以图标高度(biHeight / 2)。

每行象素所占字节数=((icheader.biWidth * icheader.biBitCount + 31) And &HFFFFFFE0) \ 8,是4的倍数,象素位数不够4倍数的用&H00补齐。

掩码的用途:

' AND位掩码 XOR位掩码 显示'

' -------------------------------------------'

' 0 0 黑色'

' 0 0-F 调色板指定色'

' 1 0 屏幕,透明'

' 1 1 屏幕的反色,一般不用。

2.1 DIB位图信息头:bitmapinfoheader:icheader As bmih

C原型定义:

typedef struct tagBITMAPINFOHEADER { /* bmih */

DWORD biSize;

LONG biWidth;

LONG biHeight;

WORD biPlanes;

WORD biBitCount;

DWORD biCompression;

DWORD biSizeImage;

LONG biXPelsPerMeter;

LONG biYPelsPerMeter;

DWORD biClrUsed;

DWORD biClrImportant;

} BITMAPINFOHEADER;

VB定义:

'--------------------位图信息头,BITMAPINFOHEADER

'说明BITMAPINFOHEADER结构,其中包含了有关位图的尺寸及位格式等信息

Public Type bmih 'BITMAPINFOHEADER ,bmiHeader;

biSize As Long 'DWORD ;Bitmap Header Size,BITMAPINFOHEADER段尺寸。*

biWidth As Long 'LONG ;Width 1 dword 位图的宽度,以象素为单位*

biHeight As Long 'LONG ;Height 1 dword 位图的高度,以象素为单位*

biPlanes As Integer 'WORD ;Planes 1 word 位图的位面数(注:该值将总是1)*

biBitCount As Integer ';WORD;Bits Per Pixel,每个象素的位数*

biCompression As Long ';DWORD,Compression,压缩说明:

biSizeImage As Long ';DWORD;Bitmap Data Size 1 dword 用字节数表示的位图数据的大小。该数必须是4的倍数*

biXPelsPerMeter As Long ';LONG;HResolution 1 dword 用象素/米表示的水平分辨率

biYPelsPerMeter As Long ';LONG;VResolution 1 dword 用象素/米表示的垂直分辨率

biClrUsed As Long ';DWORD;Colors 1 dword 位图使用的颜色数。如8-比特/象素表示为100h或者 256.

biClrImportant As Long ';DWORD;Important Colors 1 dword 指定重要的颜色数。当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要

End Type

在ICON文件中使用的关键变量只用到:bisize, biwidth, biheight, biplanes, bibitcount, bisizeimage.几个,其他变量必须为0。biheight变量的值为高度象素量的2倍。

关于BITMAPINFOHEADER的更多介绍参见BMP文件格式分析的文章,在此不作冗述。

2.2色彩表:rgbquad:iccolors() As rgbq

[摘自:BMP文件格式分析:彩色表包含的元素与位图所具有的颜色数相同,象素的颜色用RGBQUAD结构来定义。对于24-位真彩色图象就不使用彩色表(同样也包括16位、和32位位图),因为位图中的RGB值就代表了每个象素的颜色。彩色表中的颜色按颜色的重要性排序,这可以辅助显示驱动程序为不能显示足够多颜色数的显示设备显示彩色图象。RGBQUAD结构描述由R、G、B相对强度组成的颜色,定义如下]

C原型定义:

typedef struct tagRGBQUAD { /* rgbq */

BYTE rgbBlue;

BYTE rgbGreen;

BYTE rgbRed;

BYTE rgbReserved;

} RGBQUAD;

VB定义:

'-----------------色彩表

'说明彩色表RGBQUAD结构的阵列,其中包含索引图像的真实RGB值。

Public Type rgbq 'RGBQUAD, bmiColors[];

rgbBlue As Byte ' 指定蓝色强度

rgbGreen As Byte ' 指定绿色强度

rgbRed As Byte ' 指定红色强度

rgbReserved As Byte ' 保留,设置为0

End Type

色彩表的定义也是来自BMP文件结构的定义,定义的类型格式和BMP文件的相同。

3.ICON文件的完整结构

Public Type icondirentry

bwidth As Byte ';byte // width, in pixels, of the image:图像宽度,以象素为单位。一个字节

bheight As Byte ';byte // height, in pixels, of the image:图像高度,以象素为单位。一个字节

bcolorcount As Byte ';byte // number of colors in image (0 if >=8bpp):图像中的颜色数(如果是>=8bpp的位图则为0)

breserved As Byte ';byte // reserved ( must be 0):保留字必须是0

wplanes As Integer ';word // color planes:为目标设备说明位面数,其值将总是被设为1

wbitcount As Integer ';word // bits per pixel:每象素所占位数。

dwbytesinres As Long ';dword // how many bytes in this resource?:这份资源所占字节数

dwimageoffset As Long ';dword // where in the file is this image?:图像数据(iconimage)起点偏移位置。

End Type ' icondirentry

Public Type icondir

idreserved As Integer '; word // reserved (must be 0):保留字必须是0

idtype As Integer '; word // resource type (1 for icons):资源类型,1是图标,2就是光标了?

idcount As Integer '; word // how many images?:有几个图像

identries() As icondirentry '[1]'icondirentry; // an entry for each image (idcount of 'em):每个图像的入口定义

End Type

Public Type bmih 'BITMAPINFOHEADER ,bmiHeader;

biSize As Long 'DWORD ;Bitmap Header Size,BITMAPINFOHEADER段尺寸。*

biWidth As Long 'LONG ;Width 1 dword 位图的宽度,以象素为单位*

biHeight As Long 'LONG ;Height 1 dword 位图的高度,以象素为单位*

biPlanes As Integer 'WORD ;Planes 1 word 位图的位面数(注:该值将总是1)*

biBitCount As Integer ';WORD;Bits Per Pixel,每个象素的位数*

biCompression As Long ';DWORD,Compression,压缩说明:

biSizeImage As Long ';DWORD;Bitmap Data Size 1 dword 用字节数表示的位图数据的大小。该数必须是4的倍数*

biXPelsPerMeter As Long ';LONG;HResolution 1 dword 用象素/米表示的水平分辨率

biYPelsPerMeter As Long ';LONG;VResolution 1 dword 用象素/米表示的垂直分辨率

biClrUsed As Long ';DWORD;Colors 1 dword 位图使用的颜色数。如8-比特/象素表示为100h或者 256.

biClrImportant As Long ';DWORD;Important Colors 1 dword 指定重要的颜色数。当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要

End Type

Public Type rgbq 'RGBQUAD;

rgbBlue As Byte ' 指定蓝色强度

rgbGreen As Byte ' 指定绿色强度

rgbRed As Byte ' 指定红色强度

rgbReserved As Byte ' 保留,设置为0

End Type

Public Type iconimage '{

icheader As bmih ';DIB位图信息头:bitmapinfoheader // dib header,注:bmih 是我简化了bitmapinfoheader的名称。

' used: bisize, biwidth, biheight(xorH+andH)即2倍高度, biplanes, bibitcount, bisizeimage.

'all other members must be 0.

iccolors() As rgbq '[1]';色彩表:rgbquad // color table

icxor() As Byte '[1];byte // dib bits for xor mask:DIB结构的图像数据。XOR掩码?4bpp

icand() As Byte '[1];byte // dib bits for and mask:DIB结构的图像数据。AND掩码?1bpp

End Type '} iconimage

Public Type Iconfile

iDir As icondir '目录

imgDate() As iconimage '图像数据段

End Type

由结构定义得知,ICON文件由目录段和图像数据段组成。完整的结构示意图如下:

'-------------完整的文件构成

+---目录段

+------目录头

idreserved As Integer '; word // reserved (must be 0):保留字必须是0

idtype As Integer '; word // resource type (1 for icons):资源类型,1是图标,2就是光标了?

idcount As Integer '; word // how many images?:有几个图像

+-------------目录索引1

identries(0) As icondirentry

+-------------目录索引2

identries(1) As icondirentry

+-------------目录索引x最大为32767

identries(X) As icondirentry

+---图像数据段

+--------------图像1

icheader As bmih

iccolors(0 to 15) As rgbq '16色

icxor(0 to 511) As Byte '32*32

icand(0 to 127) As Byte '32*32

+--------------图像2

.

+--------------图像x最大为32768

.

'--------------END file.

通过以上结构,你就可以方便的读写ICON文件并制作属于你自己的ICON文件编辑器了。

4.显示ICON图像的方法之一

我们大家都知道用LoadPicture可以直接加载ICON文件,在此向大家介绍另外一种显示方法,相信会使你得到一些启发。

在此用到几个API函数:

'ICON图像描述

Public Type ICONINFO

fIcon As Long

xHotspot As Long

yHotspot As Long

hbmMask As Long

hbmColor As Long

End Type

'CreateIconFromResource 函数通过ICON图像资源位描述信息创建一个图标或光标,presbits:图像资源起始点指针,dwResSize:图像数据尺寸,fIcon:TRUE为图标、FALSE将创建一个光标,dwVer:指定创建的图标的版本号(Windows 2.x =&H20000、Windows 3.x =&H30000 ,在WIN32程序中使用的都是Windows 3.x格式)。失败返回NULL,成功则返回创建的图标的句柄(handle )。

Declare Function CreateIconFromResource Lib "user32" (presbits As Byte, ByVal dwResSize As Long, ByVal fIcon As Long, ByVal dwVer As Long) As Long

'GetIconInfo 函数取得与图标有关的信息。返回非零表示成功,零表示失败。函数返回时,由ICONINFO结构载入的位图必须由应用程序删去。hIcon 为由CreateIconFromResource 函数创建的图标的句柄即:CreateIconFromResource 函数的返回值。

Declare Function GetIconInfo Lib "user32" (ByVal hIcon As Long, piconinfo As ICONINFO) As Long

' CreateIconIndirect 函数通过GetIconInfo函数取得的ICONINFO(图标信息)创建一个图标,执行成功返回图标的句柄,零表示失败。

Declare Function CreateIconIndirect Lib "user32" (piconinfo As ICONINFO) As Long

'DrawIcon 函数在指定设备的指定位置画一个图标。返回非零表示成功,零表示失败。hdc:设备关联句柄,x/y:绘制图像的起点位置,hIcon:图标的句柄。

Declare Function DrawIcon Lib "user32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal hIcon As Long) As Long

'DestroyIcon 函数清除创建的图标以释放其占用的内存。返回非零表示成功,零表示失败。hIcon:图标的句柄。

Declare Function DestroyIcon Lib "user32" (ByVal hIcon As Long) As Long

通过上面的函数说明可见,我们可以单单使用图像信息来创建一个图标,即上面的iconimage结构。下面是以32×32象素,16色单资源图标文件为例的例子:

Dim tmphIcon As Long

Dim IconShow() As Byte

Private Sub Command4_Click()

Dim lTemp As Long

Dim lSize As Long

Dim freefn As Integer

ReDim IconShow(743) '等同于前面第3节中定义的iconimage结构。

freefn = FreeFile

Open App.Path + "\11.ico" For Binary As #freefn

Seek #freefn, 23

Get #freefn, , IconShow

Close #freefn

'---------------------------直接加载图标。

lTemp = DestroyIcon(tmphIcon)

Picture3.Cls

lSize = 744

lTemp = CreateIconFromResource(IconShow(0), lSize, 1, &H30000)

DrawIcon Picture3.hdc, 0, 0, lTemp

Picture3.Refresh

tmphIcon = lTemp

End Sub

以上代码只是取到抛砖引玉的作用,并不表明任何其他意图。同样,使用CreateIconIndirect 函数创建的图标也可以直接用DrawIcon 函数函数显示。

5.参考资料

【BMP文件格式分析(zz)- -】:http://lhbyron.blogchina.com/652956.html

【icons in win32】:http://www.moon-soft.com/program/FORMAT/windows/icons.htm

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有