《2022年2022年解读ico文件 2.pdf》由会员分享,可在线阅读,更多相关《2022年2022年解读ico文件 2.pdf(8页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、解读图标文件图标文件是一种特殊的位图,它的大小固定(16*16 或 32*32 像素大小),且支持透明的特性。图标的格式也有24 位、 8 位和 4 位几种不同的格式,它与位图最大的区别是:位图无法支持透明而图标可以。那图标是怎样做到这一点的呢?原来,图标采用对图像扫描两遍的方式进行记录位图信息的,第一遍扫描每个像素上的颜色数据完成后,重新以 1位位图的方式对图像进行第二次扫描,并以辅助信息的方式追加在文件的后面,这样,图标文件的结构就比位图文件多了辅助信息这部分(见图)。图标文件头位图信息头系统调色盘 图片信息辅助信息icofileheader bmpinfoheader rgbquad r
2、gbdata fby (14bytes) (40bytes) 为了使图标的某些部分变得透明,在第一遍扫描时,把这部分的颜色值改为黑色,在第二遍扫描时,这部分的颜色为白色,不透明的部分为黑色(0 为黑色, 1 为白色)。这样,图标的背景就变透明了。我们以 32*32 像素大小的图标为例来计算一下图标文件的大小:种类文件头信息头调色盘图片信息辅助信息文件大小24bit 22 40 0 32*32*3 128 3262 8bit 22 40 4*256 32*32 128 2238 4bit 22 40 4*16 32*32/2 128 766 编程举例:(保存为24 位透明图标)我们熟悉图标文件的
3、组成,就可以用照片来创建自己的高品质的带透明背景的图标了,为了简化程序代码,在下例的程序中,我省去了图像的操作,仅保留了把一幅32*32 像素大小,带白色背景的24 位位图,转化成24 位透明图标的代码。用 VB6 新建一个工程,命名为WriteIcoFile.vbp 。添加一个窗体WriteIcoFile.frm ,caption=” WriteIcoFile”。添加图片框picture1, scalemode=3-pixel;autoredraw=true;autosize=true;borderstyle=0-none 。添加一个按钮command1 的 caption=”BmpToIc
4、o ”,添加两个标签 Label1,label2。粘贴代码:Option Explicit Private Type ICONFILEHEADER 22bytes idReserved As Integer 为 0 idType As Integer 为 1 idCount As Integer 文件中图标个数,为1 bWidth As Byte 宽,为 16 或 32 bHeight As Byte 高,为 16 或 32 bColorCount As Byte 调色盘颜色数量:16 或 255 或 0 bReserved As Byte 为 0 wPlanes As Integer 为 1
5、 wBitCount As Integer 每个像素占的位数dwBytesInRes As Long 图标文件后四项总字节数名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 8 页 - - - - - - - - - dwImageOffset As Long 图标文件头长度,为22 End Type Private Type BITMAPINFOHEADER 40 bytes biSize As Long 信息头的长度,为40 biWidth As Long 宽biHei
6、ght As Long 扫描两遍,值为实实际高度的2 倍biPlanes As Integer 为 1 biBitCount As Integer 每个像素占的位数biCompression As Long 为 0 biSizeImage As Long 图标文件后三项总字节数biXPelsPerMeter As Long 为 0 biYPelsPerMeter As Long 为 0 biClrUsed As Long 为 0 biClrImportant As Long 为 0 End Type Private Type RGBQUAD 4bytes调色盘中颜色rgbBlue As Byt
7、e rgbGreen As Byte rgbRed As Byte rgbReserved As Byte End Type Private Type RGBDATA 24bitcolor图像信息中每一个像素包含的RGB b As Byte g As Byte r As Byte End Type Private Sub Command1_Click() 保存为 24 位透明图标If Picture1.Height = 32 And Picture1.Width = 32 Then Dim ifh As ICONFILEHEADER ICOfileheader Dim bih As BITMA
8、PINFOHEADER Dim rgbd() As RGBDATA Dim rgbl() As Long Dim fby() As Byte Open App.Path & temp.ico For Binary As #1 设置图标文件头的值ifh.idReserved = 0 ifh.idCount = 1 ifh.idType = 1 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 8 页 - - - - - - - - - ifh.bHeight = 32 ifh
9、.bWidth = 32 ifh.bColorCount = 0 ifh.bReserved = 0 ifh.wPlanes = 1 ifh.wBitCount = 24 ifh.dwBytesInRes = 3240 ifh.dwImageOffset = Len(ifh) Put #1, , ifh 设置图片信息头的值bih.biSize = Len(bih) bih.biWidth = 32 bih.biHeight = 64 ! bih.biPlanes = 1 bih.biBitCount = 24 bih.biCompression = 0& bih.biSizeImage = 3
10、200 bih.biXPelsPerMeter = 0& bih.biYPelsPerMeter = 0& bih.biClrUsed = 0& bih.biClrImportant = 0& Put #1, , bih Dim i, j, k As Integer Dim by, byy As Long by = 16777215 ReDim rgbd(1023) 申请 1024 个像素的RGB 空间 从左下角逐行扫描For i = 0 To 31 For j = 0 To 31 byy = Picture1.Point(j, 31 - i) 获得图像上某一点的颜色Long 值If byy
11、= by Then 如果该点为白色(16777215=RGB (255,255,255)rgbd(k).r = 0 rgbd(k).g = 0 rgbd(k).b = 0 Else rgbd(k).b = Int(byy / 65536) byy = byy - rgbd(k).b * 65536 rgbd(k).g = Int(byy / 256) rgbd(k).r = byy Mod 256 End If k = k + 1 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3
12、页,共 8 页 - - - - - - - - - Next Next Put #1, , rgbd 计算图标的辅助信息,白色背景部分对应的位的值为1 ReDim fby(127) k = 0 For i = 0 To 31 For j = 0 To 3 每个字节包含8 个像素的1 位信息byy = 0 If Picture1.Point(j * 8 + 7, 31 - i) = by Then byy = 1 If Picture1.Point(j * 8 + 6, 31 - i) = by Then byy = byy + 2 If Picture1.Point(j * 8 + 5, 31
13、 - i) = by Then byy = byy + 4 If Picture1.Point(j * 8 + 4, 31 - i) = by Then byy = byy + 8 If Picture1.Point(j * 8 + 3, 31 - i) = by Then byy = byy + 16 If Picture1.Point(j * 8 + 2, 31 - i) = by Then byy = byy + 32 If Picture1.Point(j * 8 + 1, 31 - i) = by Then byy = byy + 64 If Picture1.Point(j * 8
14、, 31 - i) = by Then byy = byy + 128 fby(k) = byy k = k + 1 Next Next Put #1, , fby Close #1 Label1.Caption = 成功创建 & App.Path & temp.ico Else Label1.Caption = 图片大小应为32*32 End If End Sub Private Sub Form_Load() Label2.Caption = 本例程序展示了图标创建的巅峰水平(能写出24 位的透明的标准图标) & vbCrLf & 为了简化程序,程序中只展示了将32*32 带白色背景的的2
15、4 位位图转化成图标文件的代码。 & vbCrLf & 您如果想创建自已的图标,可以用自己做的图片代替同目录下的temp.bmp & vbCrLf & 即可做出属于自己的高品质图标。 Picture1.Picture = LoadPicture(App.Path & temp.bmp) End Sub 编程原理:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 8 页 - - - - - - - - - 窗体导入时,导入同目录下的24 位位图 “temp.bmp”, com
16、mand1 按下时,判断图片大小是否为32*32,为图标文件头和位图信息头赋值,利用Picture1 的 Point(x,y) as long 方法,从左下角逐行扫描,获得图像的像素颜色的long 值,然后经过计算,转换成rgbd(),来获得图像的 24 位图像信息,需注意的是,把白色背景的值,改为黑色的值(r=0;g=0,b=0 ),接着,再重新扫描,把白色背景的值设为1,不透明部分值设为0 ,经过计算获得图像的1位图像信息,最后写入同目录下的“temp.ico ”。Long 与(R,G,B) 之间的转换:我说明一下二进制和十进制的转换问题,我们在利用图片框Picture1 的 PSet (
17、x,y), col和 Point(x,y) 来描绘图像和获得图像颜色值时,使用的是Long 类型的数据, 而 24 位位图文件中的颜色信息是以(R,G,B)Bytes 类型的数据存储的,在(R,G,B)与 Long 互换的计算中,需要用到二进制与十进制的转换。R=255 G=255 B=255 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 128 64 32 16 8 4 2 1 这样每 8 位上的数加起来就有255 RGB(b,g,r)就是把3 个 8 位二进制连成1 个 24 位的数1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
18、 1 1 1 1 1 1 1 1 1 8388608 .65536512 256 8 4 2 1 这样 24 位上的数加起来就有16777215 即 RGB( 255,255,255) =16777215 R=1 G=1 B=1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 这样每 8 位上的数加起来就有1 RGB(b,g,r)把 3 个 8 位二进制连成1 个 24 位的数0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 65536 0
19、0 0 0 0 0 0 256 0 0 0 0 0 0 0 1 这样 24 位上的数加起来就有65739 即 RGB (1,1,1)=65793 我通过举几个例子来说明这方面的知识:把( R,G,B)转换成Long 用 RGB( b,g,r)就可以完成。(用算式:b *65536 + g *256 + r 来计算也可以)那怎样把Long 转换成( R,G,B)呢?我们可以用逆运算的计算方法来完成,用上面举的例了来说,如果一个颜色的Long 值为 65793 B=Int(Long/65536) =Int(1.00392) =1 G=Int(Long B * 65536) / 256) =Int(
20、257 / 256) = 1 R=(Long R * 65536) Mod 256 = 257 Mod 256 =1 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 8 页 - - - - - - - - - 经过计算, Long 值为 65793,可转换成(1,1, 1)。编程举例 2:(保存为8 位 256 色不透明图标)在上面的窗体中,添加一个按钮command2 ,caption= ”Save256ColorIco ”,编写代码:Private Sub Comma
21、nd2_Click() 保存为 8 位 256 色不透明图标If Picture1.Height = 32 And Picture1.Width = 32 Then Dim ifh As ICONFILEHEADER ICOfileheader Dim bih As BITMAPINFOHEADER Dim rgbq(255) As RGBQUAD Dim rgbby(1023) As Byte Dim fby(127) As Byte Open App.Path & temp2.ico For Binary As #1 ifh.idReserved = 0 ifh.idCount = 1 i
22、fh.idType = 1 ifh.bHeight = 32 ifh.bWidth = 32 ifh.bColorCount = 255 ifh.bReserved = 0 ifh.wPlanes = 1 ifh.wBitCount = 8 ifh.dwBytesInRes = 2216 ifh.dwImageOffset = Len(ifh) Put #1, , ifh bih.biSize = Len(bih) bih.biWidth = 32 bih.biHeight = 64 ! bih.biPlanes = 1 bih.biBitCount = 8 bih.biCompression
23、 = 0& bih.biSizeImage = 2176 bih.biXPelsPerMeter = 0& bih.biYPelsPerMeter = 0& bih.biClrUsed = 0& bih.biClrImportant = 0& 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 8 页 - - - - - - - - - Put #1, , bih Dim i, j, k As Integer Dim r, g, b, ra, ga, ba, lIndex A
24、s Integer Dim by, byy As Long by = 16777215 创建调色盘中的颜色(创建216 个,其余为初始值0,0,0,0)For b = 0 To 255 Step 51 For g = 0 To 255 Step 51 For r = 0 To 255 Step 51 With rgbq(lIndex) .rgbRed = r: .rgbGreen = g: .rgbBlue = b End With lIndex = lIndex + 1 Next r Next g Next b Put #1, , rgbq For i = 0 To 31 For j = 0
25、 To 31 byy = Picture1.Point(j, 31 - i) If byy = by Then rgbby(k) = 0 Else 算出某点上的R,G,B 的值b = Int(byy / 65536) byy = byy -b * 65536 g = Int(byy / 256) r = byy Mod 256 算出该点上的颜色在调色盘中的ID 号,并存入像素流rgbby() 中ra = Cint(r/51) ga = Cint(g/51) ba = Cint(b/51) rgbby(k) = ba * 36 + ga * 6 + ra End If k = k + 1 Nex
26、t Next Put #1, , rgbby 不对 fby() 赋值,那么fby() 中的每个数值都为初始值0 ,图标没有透明部分Put #1, , fby 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 8 页 - - - - - - - - - Close #1 Label1.Caption = 成功创建 & App.Path & temp2.ico Else Label1.Caption = 图片大小应为32*32 End If End Sub 用计算的方法获得像素
27、流:调色盘中的颜色可以自由创建,我们把每一种颜色分成5档共 6 个不同的值( 0,52,102,153,204,255),然后按一定的排列顺序,组成0215 共 216 种不同的颜色。接着我们在扫描图片时,获得每个像素上的颜色Long ,用计算的方法算出(R,G,B)的值, 再根据上面创建调色盘的方法,计算出与该点颜色相近的调色盘中的某一个颜色,在调色盘中排列的序号ID ,把这个ID 值存入 Byte 类型的 rgbby() 数组中,就形成了像像素流。必须注意的是,由于位图和图标的像素流是倒置的,所以,除了要从左下角开始扫描外,还要在保存的过程中把RGB 倒置成 BGR。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 8 页 - - - - - - - - -