- UID
- 1
- 精华
- 积分
- 76361
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
所谓ICO、CUR指的是Windows的图标和光标文件。这种文件结构十分简单,描述一下就是这样:
ICO、CUR文件结构:
1个文件信息头
N个图像信息头
然后是N个BMP(BITMAPINFOHEADER、调色板、位图)
BITMAPINFOHEADER的高的值是宽的两倍。
如果不是32位的位图,则尾部附带单色位图透明数据
文件信息头的结构:- struct ICONFILEHEADER //文件信息头,一个ICO只有一个
- {
- WORD wReserved; //保留,值为0
- WORD wType; //类型,1为ICO,2为CUR
- WORD wCount; //整个ICO文件的图像数
- };
复制代码 图像信息头的结构:- struct ICONINFOHEADER //图像信息头,有多少图像就有多少个图像信息头
- {
- BYTE bWidth; //图像宽度
- BYTE bHeight; //图像高度
- BYTE bColorCount; //图像颜色数低8位
- BYTE bReserved; //保留
- union
- {
- struct
- {
- INT16 wCursorX; //光标中心X
- INT16 wCursorY; //光标中心Y
- }AsCursor;
- struct
- {
- WORD wPlanes; //位面数
- WORD wBitCount; //颜色位数
- }AsIcon;
- };
- DWORD dwBytesInRes; //图像大小
- DWORD dwImageOffset; //图像位置
- };
复制代码 之后的数据就是ICO、CUR文件包含的位图图像了。这些图像都是以BMP位图的形式存在的——就像去掉了BMP文件头的BMP文件一样,结构如下说明:
- 一个BITMAPINFOHEADER结构体。
- 如果是索引颜色,这里有调色板,否则没有。
- 位图数据。
- 位图透明通道数据,如果位图不是32位的
其中BITMAPINFOHEADER结构体中的“高度”(即biHeight)的数值是“宽度”(即biWidth)的数值的两倍。如果位图不是32位位图(比如24位、16位、8位、4位、2位、1位等)则在位图数据后面有透明通道数据,这个透明通道数据的内容,相当于一个单色BMP文件的位图部分。
根据如上的资料,我们就能制作出一个ICO、CUR文件的编辑器了。不过我可不想造轮子,造一个功能像画图一样不支持透明通道的不爽,而造一个像PhotoShop一样的则感觉没啥意义。因此我干脆借助NASM汇编的平坦模型原理,编写了一个“脚本”,用NASM编译一下它,就能得到一个ICO、CUR文件,原理是将BMP位图合并到位图里。
想必大家可能失望了……我可不想用汇编语言造一个这样的画图器轮子啊!只是利用了NASM的特性了而已,把它当作组装文件的“脚本解释器”了而已。
我这套工具主要就三个文件:
makeicon.asm
makeicon.inc
makeicon.bat
用法:将位图文件准备好,放到指定位置(比如这个工具的文件夹)
其中文件名以“mask”结尾的BMP文件是黑白位图(所谓“单色位图”),作用是定义位图的透明通道,黑色表示对应像素不透明,白色表示透明。
然后我们来编写makeicon.asm吧。需要的宏已经在makeicon.inc提供了。大家可以看看makeicon.inc的内容:- ;==============================================================================
- ;作者:0xAA55
- ;网站:http://www.0xaa55.com/
- ;请注明原作者信息,否则视为侵权。
- ;------------------------------------------------------------------------------
- %ifndef _ICON_CURSOR_FILE_GEN_
- %define _ICON_CURSOR_FILE_GEN_
- ;==============================================================================
- ;ICO、CUR文件结构:
- ;1个文件信息头
- ;N个图像信息头
- ;然后是N个BMP(BITMAPINFOHEADER、调色板、位图)
- ;BITMAPINFOHEADER的高的值是宽的两倍。
- ;如果不是32位的位图,则尾部附带单色位图透明数据
- ;------------------------------------------------------------------------------
- ;==============================================================================
- ;BMP文件头
- ;------------------------------------------------------------------------------
- struc BMFH;BITMAPFILEHEADER
- .bfType resw 1
- .bfSize resd 1
- .bfReserved1 resw 1
- .bfReserved2 resw 1
- .bfOffBits resd 1
- .Size:
- endstruc
- ;==============================================================================
- ;BMP信息头
- ;------------------------------------------------------------------------------
- struc BMIF;BITMAPINFOHEADER
- .biSize resd 1
- .biWidth resd 1
- .biHeight resd 1
- .biPlanes resw 1
- .biBitCount resw 1
- .biCompression resd 1
- .biSizeImage resd 1
- .biXPelsPerMeter resd 1
- .biYPelsPerMeter resd 1
- .biClrUsed resd 1
- .biClrImportant resd 1
- .Size:
- endstruc
- ;==============================================================================
- ;调色板项
- ;------------------------------------------------------------------------------
- struc RGBQ
- .R resb 1
- .G resb 1
- .B resb 1
- .X resb 1
- .Size:
- endstruc
- ;==============================================================================
- ;宏:FileHeader
- ;用法:用在汇编文件最开始的地方,定义ICO或CUR文件的文件头。
- ;参数:FT_Ico或FT_Cur,指明文件格式。
- ;------------------------------------------------------------------------------
- %define FT_Ico 1
- %define FT_Cur 2
- %macro FileHeader 1
- segment .data align=1
- segment .text align=1
- %define FT_FileType %1
- %assign NumImages 0
- dw 0
- dw %1
- dw NbImages
- %endmacro
- ;宏:_bitmap_pitch
- ;用于计算位图每行字节数
- %define _bitmap_pitch(w,b) ((((w) * (b) - 1) / 32 + 1) * 4)
- ;==============================================================================
- ;宏:IncludeBMP
- ;参数:
- ;如果是图标:
- ; 尺寸,颜色数,位面数,颜色位数,BMP文件路径
- ;
- ;如果是光标:
- ; 尺寸,颜色数,位面数,颜色位数,焦点X,焦点Y,BMP文件路径
- ;
- ;如果BMP文件是索引颜色,则有第六个参数:作为透明通道的BMP文件路径,必须为单色位
- ;图。
- ;------------------------------------------------------------------------------
- %macro IncludeBMP 5-6
- segment .text
- db (%1)&0xFF;宽度
- db (%1)&0xFF;高度
- db (1 << (%4))&0xFF;颜色数
- db 0 ;保留
-
- ;如果是图标,下面两个参数分别是位面数和颜色位数,如果是光标,则是焦点坐标
- %if FT_FileType == FT_Ico
- dw %3, %4
- %define Color_File %5
- %define Alpha_File %6
- %else
- dw %5, %6
- %define Color_File %7
- %define Alpha_File %8
- %endif
-
-
- dd %%ImageDataLen
- dd %%ImageData
-
- segment .data
- %%ImageData:
- dd BMIF.Size
- dd (%1)
- dd (%1) * 2 ;高的值是宽的两倍
- dw %3, %4
- dd 0 ;不能是压缩格式,也不能有位域
- dd (%1) * _bitmap_pitch(%1, %4) ; 实际大小
- ;从文件取打印尺寸
- incbin Color_File, BMFH.Size + BMIF.biXPelsPerMeter, 4 * 2
- %if (%4)<=8 ;调色板颜色
- dd 1 << (%4) ;使用的颜色数
- dd 1 << (%4) ;重要的颜色数
- incbin Color_File, BMFH.Size + BMIF.Size, 4 * (%2) ;插入调色板
- times (1 << (%4)) - (%2) dd 0 ;补全调色板颜色
- incbin Color_File, BMFH.Size + BMIF.Size + 4 * (%2), (%1) * _bitmap_pitch(%1, %4) ;按照实际大小插入位图
- incbin Alpha_File,BMFH.Size + BMIF.Size + 4 * 2 ;然后插入透明通道
- %else
- dd 0 ;无调色板数据
- dd 0
- incbin Color_File, BMFH.Size + BMIF.Size ;插入整张位图
- %endif
- %%ImageDataLen equ $-%%ImageData
-
- %assign NumImages NumImages+1
- %endmacro
- ;==============================================================================
- ;宏:IncludePNG
- ;参数:
- ;如果是图标:
- ; 尺寸,PNG文件路径
- ;
- ;如果是光标:
- ; 尺寸,焦点X,焦点Y,PNG文件路径
- ;
- ;------------------------------------------------------------------------------
- %macro IncludePNG 2-4
- segment .text
- db (%1)&0xFF;宽度
- db (%1)&0xFF;高度
- db 0 ;颜色数
- db 0 ;保留
-
- ;如果是图标,下面两个参数分别是位面数和颜色位数,如果是光标,则是焦点坐标
- %if FT_FileType == FT_Ico
- dw 1, 32
- %define Color_File %2
- %else
- dw %2, %3
- %define Color_File %4
- %endif
-
- dd %%ImageDataLen
- dd %%ImageData
-
- segment .data
- %%ImageData:
- incbin Color_File
- %%ImageDataLen equ $-%%ImageData
-
- %assign NumImages NumImages+1
- %endmacro
- ;==============================================================================
- ;宏:FileEnd
- ;用法:用在文件结尾。
- ;------------------------------------------------------------------------------
- %macro FileEnd 0
- NbImages equ NumImages
- %endmacro
- %endif
复制代码 可以从源码上看出这些宏的用法:
FileHeader:定义文件头的内容。
IncludeBMP:将BMP位图文件加入到ICO或CUR中,参数已经在源码中说明了。
IncludePNG:将PNG文件加入到ICO或CUR中。
FileEnd:做一些结尾工作。
为了缩小文件尺寸,我已经把icon16.bmp、icon32.bmp、icon48.bmp处理为256色(8位色)位图了。
因此当我们需要把刚才那些位图组合成一个ICO文件,我们只需要这样编写makeicon.asm就行了:- %include"makeicon.inc"
- FileHeader FT_Ico
- ;IncludeBMP 尺寸,颜色数,位面数,颜色位数,位图文件名[,透明通道文件名]
- ;如果不是图标,是光标,那么参数则应该是:
- ;IncludeBMP 尺寸,颜色数,位面数,颜色位数,焦点X,焦点Y,位图文件名[,透明通道文件名]
- ;如果不是32位色(或者0x100000000色)那么就必须要有透明通道文件,这里叫“掩码”。
- ;前两张位图实际颜色数是22,这是用PS看到的
- IncludeBMP 16,22,1,8,"icon16x16.bmp","mask16x16.bmp"
- IncludeBMP 32,22,1,8,"icon32x32.bmp","mask32x32.bmp"
- ;后面这张48x48的实际颜色数是256
- IncludeBMP 48,256,1,8,"icon48x48.bmp","mask48x48.bmp"
- ;PNG格式的图标用不着啰嗦
- IncludePNG 128,"icon128x128.png"
- FileEnd
复制代码 边写好了以后,保存,然后双击makeicon.bat。哦?对了,我们必须要有nasm.exe这个编译器在系统里,它是一个著名的汇编器,非常屌。
NASM汇编器点此下载
之后把它放到这个源码文件夹,或者干脆放到%PATH%下使其随时都能使用(我就是这么做的)。
双击了makeicon.bat之后,它只显示了“请按任意键继续。。。”
那么让我们切克闹。
可以看到我们得到了makeicon.ico这个文件。是它是它就是它,我们的朋友小哪吒。
事实证明这个图标文件没有问题,一切正常,它的三个图像都能正常显示。
从某种程度上来说,我这个东西基本只依赖NASM这个汇编器(makeicon.bat这个文件也只是调用了nasm,给了一个很简单的命令行参数而已。)而nasm是开源的跨平台汇编器。因此我的这个BMP转图标的“脚本”也是跨平台的哦。要在安卓手机上可以通过安装DOSBox运行DOS版的NASM编译makeicon.asm文件得到图标。
BIN:没有
SRC:
makeicon.zip
(52.55 KB, 下载次数: 6)
|
|