word 分析可知,ico图标与bmp位图有三个一样的局部〔注:真彩图标与真彩位图的数据结构均没有调色板局部,所以是两个一样的局部〕,而且这三个局部是最重要的局部因此,我们只要去掉 bmp位图的 BMP文件头,再加上ICON文件头、ICON图象信息块和AND位图,就可以轻松制作出255×255象素以的任何规格的图标了然而……且慢,有一点却是很不轻松的:如果你想制作背景透明〔屏蔽背景色〕的图标,那么你还需要对 XOR位图的数据动大手术,更不轻松的是,AND 位图的数据也必须符合相应的要求,这是相当困难的;而制作有背景色的图标的话,XOR 位图局部我们可以原封不动,AND 位图全是 0,只要计算出它的长度来即可添加到 XOR位图数据的后面,这是很容易实现的所以,下面我所讲的,都是制作有背景色的图标 ICON文件头结构很简单,一共只有3个数据共6个字节,我们要给其中的“资源类型〞和“图象个数〞 2个数据均赋值为 1 ICON 图象信息块有 7个数据共16字节,有5个数据要赋值:图标宽度、图标高度、颜色计数、图像数据块的长度、图象数据块相对于文件头部的偏移量要赋值的 5个数据中,图象数据块相对于文件头部的偏移量是固定的,图像数据块的长度需要计算,其余 3个数据可从 BMP 信息头中获得资料。
AND 位图的长度必须根据从 BMP 信息头中获得的有关数据计算 此外,还要更改 BMP 信息头中的 2个数据:一个是图象长度数据〔要加上 AND 位图的长度〕,另一个是图像高度数据〔这只要简单地将原数据×2即可〕 OK,一切都准备好了,万事俱备,只欠东风,下面就让东风劲吹吧2.编程 新建一个窗体,添加一个公用对话框,两个图片框,三个按纽 窗体与图片框的ScaleMode属性均设为3,其中 Picture1 的 Autosize 属性设为 Ture 按纽的属性设置:mand1:Caption=打开图片mand2:Caption=数据处理,Enabled=Falsemand3:Caption=保存图标,Enabled=False 代码如下:Option ExplicitDim pDAT() As Byte '源图数据Dim aDAT() As Byte 'AND位图数据Dim iDAT() As Byte 'icon文件头和图象信息块数据Private Sub mand2_Click()On Error GoTo 100Dim d As Long, c As LongDim aLength As Long 'AND位图长度aLength = 4 * (pDAT(4) \ 32 + Abs((pDAT(4) Mod 32) > 0)) * pDAT(8) '计算AND位图的长度ReDim aDAT(aLength - 1) As ByteReDim iDAT(21) As Byte'给 icon文件头和 icon图象信息块的元素赋值iDAT(2) = 1 '资源类型iDAT(4) = 1 '图像个数iDAT(6) = pDAT(4) '图像宽iDAT(7) = pDAT(8) '图像高iDAT(8) = 16 * Abs(pDAT(14) = 4)iDAT(18) = 22 '图象数据块相对于文件头部的偏移量'更改BMP信息头中的图像高度数据d = 2 * pDAT(8)Select Case Len(Hex(d))Case 1, 2: pDAT(8) = dCase 3, 4: pDAT(9) = d \ 256: pDAT(8) = d And 255End Select'更改BMP信息头中的图象长度数据c = pDAT(21): d = pDAT(20) + c * 256 + pDAT(22) * 65536 + aLengthSelect Case Len(Hex(d)) Case 1, 2: pDAT(20) = dCase 3, 4: pDAT(21) = d \ 256: pDAT(20) = d And 255Case 5, 6: c = d And 65535: pDAT(22) = d \ 65536: pDAT(21) = c \ 256: pDAT(20) = c And 255End Select'计算icon图像信息块中的图象长度数据Select Case pDAT(14) 'pDAT(14)=4为16色,=8为256色,=24为真彩Case 4: d = d + 40 + 64 '64是16色调色板长度,40是BMP信息头的长度Case 8: d = d + 40 + 1024 '1024是256色调色板长度Case 24: d = d + 40End SelectSelect Case Len(Hex(d))Case 1, 2: iDAT(14) = dCase 3, 4: iDAT(15) = d \ 256: iDAT(14) = d And 255Case 5, 6: c = d And 65535: iDAT(16) = d \ 65536: iDAT(15) = c \ 256: iDAT(14) = c And 255End Selectmand3.Enabled = True: mand2.Enabled = False100End SubPrivate Sub mand1_Click()On Error GoTo ReadErrDim ImageName As String, fLength As Long, BJ As BooleanWith monDialog1.DialogTitle = "打开".Filter = "图片文件(*.bmp,*.jpg,*.gif)|*.bmp;*.jpg;*.gif".ShowOpenIf Len(.FileName) < 5 Then Exit SubImageName = .FileNameEnd WithPicture1.Picture = LoadPicture(ImageName)Picture2.Width = Picture1.Width: Picture2.Height = Picture1.HeightPicture2.Picture = LoadPicture()If Right(LCase(ImageName), 3) <> "bmp" Then '如果不是位图,先存为位图,再读取BJ = TrueImageName = App.Path & "\TempFile.bmp"SavePicture Picture1.Image, ImageNameEnd IffLength = FileLen(ImageName) '获取文件长度ReDim pDAT(fLength - 15) As ByteOpen ImageName For Binary As #1Get #1, 15, pDATCloseIf BJ Then Kill ImageName '删除临时位图文件If (pDAT(5) + pDAT(6) + pDAT(7) + pDAT(9) + pDAT(10) + pDAT(11) > 0) ThenMsgBox "图片尺寸超出"Exit SubEnd IfMe.Caption = ImageNamemand2.Enabled = TrueExit SubReadErr:CloseEnd SubPrivate Sub mand3_Click()On Error GoTo WriteErrDim IconName As StringWith monDialog1.Flags = &H802.DialogTitle = "保存".Filter = "图标文件(*.ico)|*.ico".ShowSaveIf .FileName = "" Then Exit SubIconName = .FileNameEnd WithOpen IconName For Binary As #1Put #1, , iDATPut #1, , pDATPut #1, , aDATCloseReDim iDAT(0)ReDim pDAT(0)ReDim aDAT(0)mand3.Enabled = FalsePicture2.Picture = LoadPicture(IconName)Exit SubWriteErr:CloseMsgBox "图标制作失败"End Sub3.代码分析①在 mand1_Click 过程中,使用二进制读入数据方法,从第15字节读起,这样就去掉了BMP文件头。
②在 mand3_Click 过程中,使用二进制写入数据方法,将ICON文件头、ICON图象信息块、读入的位图数据〔修改了其中几个字节的数据〕、AND位图数据〔全0数据)等,依次写入一个ico文件③mand2_Click 过程是本代码关键的关键 首先计算 AND位图的长度这就需要知道扫描线的长度和图象的高度,而计算扫描线长度还需知道图像的宽度本代码中,图像高度在原位图数据的 pDAT(8)元素中,图象宽度在原位图数据的 pDAT(4) 元素中,所以可归纳成代码中所示的计算公式 接着给 ICON文件头和 ICON图象信息块的元素赋值请注意 iDAT(6)和 iDAT(7),它们分别是图标的宽度和高度,由于它们都只占用 1个字节,故图标规格的最大值只能做到 255象素〔如果它们都分别占用 4 个字节的话,呵呵,那制作出来的图标是多么地惊人啊!〕icon 图像信息块中的图象长度数据元素 iDAT(14)—iDAT(17)要最后才赋值 接下来就是更改BMP信息头中的图像高度数据原元素中只是XOR位图的高度,而图标的数据结构要求这个值是XOR位图高度与AND位图高度之和 再修改 BMP信息头中的图象长度数据。
原元素中只是 XOR位图的长度,而图标的数据结构要求这个值是 XOR位图长度与 AND位图长度之和 最后修改 icon 图像信息块中的图象长度数据,也就是 iDAT(14)—iDAT(17) 元素的值〔这个长度数据本来占用 4个字节,但255×255象素的图标长度只要 3个字节就够了〕计算公式如下:icon图像信息块中的图象长度=XOR位图长度+AND位图长度+BMP信息头长度+调色板长度 特大图标的制作工作到此就全部完毕了,你一定迫不与待地想看看它的效果吧,可惜的是,不论多大的图标,在桌面或资源管理器中最大都只能显示72×72的尺寸,你只有在图片框中才能欣赏到它的丽容了不过不要垂头丧气,通过这个实验,你将会获得许多图标与位图的数据结构方面的知识,这不就是最大的收获吗?附:图标文件的数据结构之研究一、从图标的显示原理说起 一般图标都是由两个单独的位图组成的如果该图标是屏蔽背景色的话,那么,第一个位图是由黑色背景〔相关的颜色位全为 0〕与彩色图标图案组成的,该位图将与当前屏幕进行异或操作〔XOR〕,故称其为 XOR位图;第二个位图是由白色背景〔相关的颜色位全为1〕与黑色图标图案〔相关的颜色位全为0〕组成的,该位图将与当前屏幕进展。