利用bmp位图制作ICO

0001 利用bmp位图制作ICO 收藏
0002 
0003 
0004 
0005 ' 1.制造原理
0006 '   调色板模式的ico文件的数据结构,可分为 6 部分:
0007 ' 1.ICON文件头(6字节)
0008 ' 2.ICON图象信息块(16字节)
0009 ' 3.BMP信息头(40字节)
0010 ' 4.调色板(16色为64字节,256色为1024字节)
0011 ' 5.XOR位图
0012 ' 6.AND位图
0013 
0014 '   而调色板模式的bmp文件的数据结构可分为 4 部分:
0015 ' 1.BMP文件头(14字节)
0016 ' 2.BMP信息头(40字节)
0017 ' 3.调色板(16色为64字节,256色为1024字节)
0018 ' 4.XOR位图
0019 
0020 '   分析可知,ico图标与bmp位图有三个相同的部分(注:真彩图标与真彩位图的数据结构
0021 ' 均没有调色板部分,所以是两个相同的部分),而且这三个部分是最重要的部分。因此,我
0022 ' 们只要去掉 bmp位图的 BMP文件头,再加上ICON文件头、ICON图象信息块和AND位图,就可
0023 ' 以轻松制作出255×255象素以内的任何规格的图标了。然而……且慢,有一点却是很不轻松
0024 ' 的:如果你想制作背景透明(屏蔽背景色)的图标,那么你还需要对 XOR位图的数据动大手
0025 ' 术,更不轻松的是,AND 位图的数据也必须符合相应的要求,这是相当困难的;而制作有背
0026 ' 景色的图标的话,XOR 位图部分我们可以原封不动,AND 位图全是 0,只要计算出它的长度
0027 ' 来即可添加到 XOR位图数据的后面,这是很容易实现的。所以,下面我所讲的,都是制作有
0028 ' 背景色的图标。
0029 '   ICON文件头结构很简单,一共只有3个数据共6个字节,我们要给其中的“资源类型”和
0030 ' “图象个数” 2个数据均赋值为 1。
0031 '   ICON 图象信息块有 7个数据共16字节,有5个数据要赋值:图标宽度、图标高度、颜色
0032 ' 计数、图像数据块的长度、图象数据块相对于文件头部的偏移量。要赋值的 5个数据中,图
0033 ' 象数据块相对于文件头部的偏移量是固定的,图像数据块的长度需要计算,其余 3个数据可
0034 ' 从 BMP 信息头中获得资料。
0035 '   AND 位图的长度必须根据从 BMP 信息头中获得的有关数据计算。
0036 '   此外,还要更改 BMP 信息头中的 2个数据:一个是图象长度数据(要加上 AND 位图的
0037 ' 长度),另一个是图像高度数据(这只要简单地将原数据×2即可)。
0038 '   OK,一切都准备好了,万事俱备,只欠东风,下面就让东风劲吹吧。
0039 
0040 ' 2.编程
0041 '   新建一个窗体,添加一个公用对话框,两个图片框,三个按纽。
0042 '   窗体与图片框的ScaleMode属性均设为3,其中 Picture1 的 Autosize 属性设为 Ture。
0043 '   按纽的属性设置:
0044 ' Command1:Caption=打开图片
0045 ' Command2:Caption=数据处理,Enabled=False
0046 ' Command3:Caption=保存图标,Enabled=False
0047 
0048 代码如下:
0049 
0050 Option Explicit
0051 
0052 Dim pDAT() As Byte '源图数据
0053 Dim aDAT() As Byte 'AND位图数据
0054 Dim iDAT() As Byte 'icon文件头和图象信息块数据
0055 
0056 Private Sub Command2_Click()
0057     On Error GoTo 100
0058     Dim d As Long, c As Long
0059     Dim aLength As Long 'AND位图长度
0060 
0061     aLength = 4 * (pDAT(4) / 32 + Abs((pDAT(4) Mod 32) > 0)) * pDAT(8) '计算AND位图的长度
0062     ReDim aDAT(aLength - 1) As Byte
0063     ReDim iDAT(21) As Byte
0064 
0065     '给 icon文件头和 icon图象信息块的元素赋值
0066     iDAT(2) = 1 '资源类型
0067     iDAT(4) = 1 '图像个数
0068     iDAT(6) = pDAT(4) '图像宽
0069     iDAT(7) = pDAT(8) '图像高
0070     iDAT(8) = 16 * Abs(pDAT(14) = 4)
0071     iDAT(18) = 22 '图象数据块相对于文件头部的偏移量
0072 
0073     '更改BMP信息头中的图像高度数据
0074     d = 2 * pDAT(8)
0075     Select Case Len(Hex(d))
0076         Case 1, 2: pDAT(8) = d
0077         Case 3, 4: pDAT(9) = d / 256: pDAT(8) = d And 255
0078     End Select
0079 
0080     '更改BMP信息头中的图象长度数据
0081     c = pDAT(21): d = pDAT(20) + c * 256 + pDAT(22) * 65536 + aLength
0082     Select Case Len(Hex(d))
0083         Case 1, 2: pDAT(20) = d
0084         Case 3, 4: pDAT(21) = d / 256: pDAT(20) = d And 255
0085         Case 5, 6: c = d And 65535: pDAT(22) = d / 65536: pDAT(21) = c / 256: pDAT(20) = c And 255
0086     End Select
0087 
0088     '计算icon图像信息块中的图象长度数据
0089     Select Case pDAT(14) 'pDAT(14)=4为16色,=8为256色,=24为真彩
0090         Case 4: d = d + 40 + 64 '64是16色调色板长度,40是BMP信息头的长度
0091         Case 8: d = d + 40 + 1024 '1024是256色调色板长度
0092         Case 24: d = d + 40
0093     End Select
0094     Select Case Len(Hex(d))
0095         Case 1, 2: iDAT(14) = d
0096         Case 3, 4: iDAT(15) = d / 256: iDAT(14) = d And 255
0097         Case 5, 6: c = d And 65535: iDAT(16) = d / 65536: iDAT(15) = c / 256: iDAT(14) = c And 255
0098     End Select
0099 
0100     Command3.Enabled = True: Command2.Enabled = False
0101 End Sub
0102 
0103 Private Sub Command1_Click()
0104     On Error GoTo ReadErr
0105     Dim ImageName As String, fLength As Long, BJ As Boolean
0106     With CommonDialog1
0107         .DialogTitle = "打开"
0108         .Filter = "图片文件(*.bmp,*.jpg,*.gif)|*.bmp;*.jpg;*.gif"
0109         .ShowOpen
0110         If Len(.FileName) < 5 Then Exit Sub
0111         ImageName = .FileName
0112     End With
0113     Picture1.Picture = LoadPicture(ImageName)
0114     Picture2.Width = Picture1.Width: Picture2.Height = Picture1.Height
0115     Picture2.Picture = LoadPicture()
0116     If Right(LCase(ImageName), 3) <> "bmp" Then '如果不是位图,先存为位图,再读取
0117         BJ = True
0118         ImageName = App.Path & "/TempFile.bmp"
0119         SavePicture Picture1.Image, ImageName
0120     End If
0121     fLength = FileLen(ImageName) '获取文件长度
0122     ReDim pDAT(fLength - 15) As Byte
0123     Open ImageName For Binary As #1
0124     Get #1, 15, pDAT
0125     Close
0126     If BJ Then Kill ImageName '删除临时位图文件
0127     If (pDAT(5) + pDAT(6) + pDAT(7) + pDAT(9) + pDAT(10) + pDAT(11) > 0) Then
0128         MsgBox "图片尺寸超出"
0129         Exit Sub
0130     End If
0131     Me.Caption = ImageName
0132     Command2.Enabled = True
0133     Exit Sub
0134     ReadErr:
0135         Close
0136 End Sub
0137 
0138 Private Sub Command3_Click()
0139     On Error GoTo WriteErr
0140     Dim IconName As String
0141     With CommonDialog1
0142         .Flags = &H802
0143         .DialogTitle = "保存"
0144         .Filter = "图标文件(*.ico)|*.ico"
0145         .ShowSave
0146         If .FileName = "" Then Exit Sub
0147         IconName = .FileName
0148     End With
0149     Open IconName For Binary As #1
0150     Put #1, , iDAT
0151     Put #1, , pDAT
0152     Put #1, , aDAT
0153     Close
0154     ReDim iDAT(0)
0155     ReDim pDAT(0)
0156     ReDim aDAT(0)
0157     Command3.Enabled = False
0158     Picture2.Picture = LoadPicture(IconName)
0159     Exit Sub
0160     WriteErr:
0161         Close
0162         MsgBox "图标制作失败"
0163 End Sub
0164 
0165 ' 3.代码分析
0166 ' ①在 Command1_Click 过程中,使用二进制读入数据方法,从第15字节读起,这样就去掉了
0167 ' BMP文件头。
0168 
0169 ' ②在 Command3_Click 过程中,使用二进制写入数据方法,将ICON文件头、ICON图象信息块
0170 ' 、读入的位图数据(修改了其中几个字节的数据)、AND位图数据(全0数据)等,依次写入一
0171 ' 个ico文件
0172 
0173 ' ③Command2_Click 过程是本代码关键的关键。
0174 '   首先计算 AND位图的长度。这就需要知道扫描线的长度和图象的高度,而计算扫描线长度
0175 ' 还需知道图像的宽度。本代码中,图像高度在原位图数据的 pDAT(8)元素中,图象宽度在原位
0176 ' 图数据的 pDAT(4) 元素中,所以可归纳成代码中所示的计算公式。
0177 
0178 '   接着给 ICON文件头和 ICON图象信息块的元素赋值。请注意 iDAT(6)和 iDAT(7),它们
0179 ' 分别是图标的宽度和高度,由于它们都只占用 1个字节,故图标规格的最大值只能做到 255
0180 ' 象素(如果它们都分别占用 4 个字节的话,呵呵,那制作出来的图标是多么地惊人啊!)。
0181 ' icon 图像信息块中的图象长度数据元素 iDAT(14)—iDAT(17)要最后才赋值。
0182 
0183 '   接下来就是更改BMP信息头中的图像高度数据。原元素中只是XOR位图的高度,而图标的
0184 ' 数据结构要求这个值是XOR位图高度与AND位图高度之和。
0185 
0186 '   再修改 BMP信息头中的图象长度数据。原元素中只是 XOR位图的长度,而图标的数据结
0187 ' 构要求这个值是 XOR位图长度与 AND位图长度之和。
0188 
0189 '   最后修改 icon 图像信息块中的图象长度数据,也就是 iDAT(14)—iDAT(17) 元素的值
0190 ' (这个长度数据本来占用 4个字节,但255×255象素的图标长度只要 3个字节就够了)。计
0191 ' 算公式如下:
0192 
0193 ' icon图像信息块中的图象长度=XOR位图长度+AND位图长度+BMP信息头长度+调色板长度
0194 
0195 
0196 '   特大图标的制作工作到此就全部结束了,你一定迫不及待地想看看它的效果吧,可惜的
0197 ' 是,不论多大的图标,在桌面或资源管理器中最大都只能显示72×72的尺寸,你只有在图片
0198 ' 框中才能欣赏到它的丽容了。不过不要垂头丧气,通过这个实验,你将会获得许多图标及位
0199 ' 图的数据结构方面的知识,这不就是最大的收获吗?
0200 
0201 
0202 ' 附:图标文件的数据结构之研究
0203 
0204 ' 一、从图标的显示原理说起
0205 '   一般图标都是由两个单独的位图组成的。如果该图标是屏蔽背景色的话,那么,第一个
0206 ' 位图是由黑色背景(相关的颜色位全为 0)与彩色图标图案组成的,该位图将与当前屏幕进
0207 ' 行异或操作(XOR),故称其为 XOR位图;第二个位图是由白色背景(相关的颜色位全为1)
0208 ' 与黑色图标图案(相关的颜色位全为0)组成的,该位图将与当前屏幕进行与操作(AND),
0209 ' 故称其为 AND 位图。因此,图标的显示是通过两个步骤完成的:
0210 
0211 ' 步骤1.首先,AND 位图与当前屏幕进行 AND 操作;
0212 ' 步骤2.接着,XOR 位图与当前屏幕进行 XOR 操作。
0213 
0214 '   大家知道,任何数值与 1 进行AND操作的结果将等于原数值,而任何数值与 0 进行AND
0215 ' 操作的结果则是 0,因此在步骤1中,AND位图中的背景色(即白色 1)部分与屏幕经过 AND
0216 ' 操作后仍然保持屏幕的原色彩,而图案色(即黑色 0)部分则取代了原屏幕色。步骤 1结束
0217 ' 后,屏幕上将留下一个黑色的图标图案。在随后的步骤 2中,由于任何数值与 0 进行异或操
0218 ' 作的结果都等于原数值,因此,XOR 位图与屏幕经过异或操作后,彩色图案部分就取代了屏
0219 ' 幕上的黑色图标部分,而屏幕的背景色与 XOR位图中的黑色背景 0异或后仍保持原来的屏幕
0220 ' 色。步骤 2结束后,一个以屏幕色为背景的彩色图标图案就出现在屏幕上了(这也是我们通
0221 ' 常所说的“屏蔽背景色”或者说“背景色透明”),这就是图标显示的原理。
0222 
0223 ' 二、图标的图形
0224 '   图标的图形,实际上就是位图格式的图片,是一个标准的位图格式。Windows只要从BMP
0225 ' 信息头中获取信息就足够了,它据以解释在其后出现的数据应该如何处理。如果是调色板模
0226 ' 式,BMP 信息头后面的数据包含有调色板和像素点颜色索引,如果是真彩模式,其后的数据
0227 ' 直接就是像素点的 RGB 颜色值。
0228 '   调色板模式的位图文件是由BMP文件头、BMP信息头、调色板、数据区(又称位图点阵)
0229 ' 等几个部分组成的。
0230 '   而调色板模式的图标文件是由ICON文件头、ICON图像信息块、BMP信息头、调色板、数
0231 ' 据区(这个数据区比位图的数据区多了 AND 位图的数据,后面会讲到)。
0232 '   我们欣喜地看到,位图与图标的数据结构有很大一部分是相同的!了解了这一情况,我
0233 ' 们可以简单地把图标图形的结构理解为位图信息。这样,我们就有可能根本不需要真的去画
0234 ' 一幅图来制作图标,而只需要利用已有的位图,对关键数据进行程序填充或修改就可以了,
0235 ' 所编写的代码,直接按图标格式的要求,可把一个尺寸不大于 255×255 像素的任意位图,
0236 ' 封装成标准格式的图标(位图的宽高尺寸保持不变)。
0237 ' 三、图标的数据结构
0238 '   图标文件的数据结构可分为6部分,叙述如下:
0239 ' -----------------------------------------------------------------------
0240 ' 顺号 名称      长度(单位:字节)  说明
0241 ' -----------------------------------------------------------------------
0242 ' 1  ICON文件头   6       
0243 ' 2  ICON图象信息块 16          有多少个图像,则信息块也有多少个
0244 ' 3  BMP 信息头   40         
0245 ' 4  XOR 位图调色板 16色=64,256色=1024 真彩图标从此开始像素点的 RGB 值
0246 ' 5  XOR 位图               以调色板的索引值形式表示
0247 ' 6   AND 位图               以单色表示
0248 ' -----------------------------------------------------------------------
0249 ' 说明:
0250 ' 1.上表中的3-6部分合称图像数据块,其中5、6部分又合称为图像数据区(也称位图点阵)
0251 ' 2.不论何种规格的图标,其1-3部分的字节长度是固定的。
0252 ' 3.调色板是供XOR位图使用的,所以又称作XOR位图调色板。AND位图是不需要调色板的,因
0253 '  为它是单色的,即只有黑色和白色,所以又称作单色AND位图。
0254 ' 4.请注意第 2部分的图象信息块的说明,“有多少个图像”是什么意思呢?原来,在一个图
0255 '  标文件中,有可能存放几个图像(windows图标最多可有8个图像),但每个图像都有自己
0256 '  的 BMP 信息头、调色板、XOR 位图和 AND 位图,且它们的图像大小也可能不相同。以16
0257 '  色有 3 个图像的图标为例,其数据结构如下:
0258 ' -------------------------------------------------------------------------
0259 ' 顺号 名称        长度(字节) 说明
0260 ' -------------------------------------------------------------------------
0261 ' 1  文件头              6
0262 ' 2  图象1的图象信息块   16  
0263 ' 3  图象2的图象信息块   16
0264 ' 4  图象3的图象信息块   16
0265 ' 5  图象1的图象数据块   不定     其中BMP信息头和调色板固定为40和64字节
0266 ' 6  图象2的图象数据块   不定     同上
0267 ' 7  图象3的图象数据块   不定     同上
0268 ' -------------------------------------------------------------------------
0269 
0270 '   下面以内含1个图像、16色、16×16规格的图标为例详述(偏移量括号前为10进制,括
0271 ' 号内为16进制):
0272 ' ------------------------------------------------------------------------------------
0273 ' 偏移量  字节数 描述               典型值(16进制)
0274 ' ------------------------------------------------------------------------------------
0275 '  (一、文件头6字节)
0276 ' 000(000)2    保留的字节            00 00
0277 ' 002(002)2    资源类型             01 00 (01为图标,02为光标)
0278 ' 004(004)2    图象个数             01 00
0279 '  (二、图像信息块16字节)
0280 ' 006(006)1    图标宽度             10
0281 ' 007(007)1    图标高度             10
0282 ' 008(008)1    颜色计数             10(16色,02=单色,00=256色或真彩)
0283 ' 009(009)1    未用                00
0284 ' 010(00A)4    保留的              00 00 00 00
0285 ' 014(00E)4    图象数据块的长度                28 01 00 00(10进制=296)
0286 ' 018(012)4    图象数据块相对于文件头部的偏移量 16 00 00 00(10进制=22)
0287 '  (三、BMP信息头40字节)
0288 ' 022(016)4    BMP 信息头结构长度        28 00 00 00(10进制=40)
0289 ' 026(01A)4    图像宽度              10 00 00 00
0290 ' 030(01E)4    图像高度(XOR图高度+AND图高度) 20 00 00 00
0291 ' 034(022)2    位面板数                         01 00
0292 ' 036(024)2    每象素所占位数                   04 00(04=16色,8=256色,18=真彩)
0293 ' 038(026)4    象素数据的压缩类型        00 00 00 00(表示未压缩)
0294 ' 042(02A)4    位图点阵的长度          C0 00 00 00(10进制=192)
0295 ' 046(02E)16   未用               16个00.  
0296 '  (四、XOR位图的调色板64字节)
0297 ' 062(03E)1    蓝色分量
0298 ' 063(03F)1    绿色分量
0299 ' 064(040)1    红色分量
0300 ' 065(041)1    未用               00
0301 '   ……
0302 '  (五、XOR位图的数据128字节)
0303 ' 126(07E)128   XOR位图             
0304 '  (六、单色AND位图的数据64字节)
0305 ' 254(0FE)64   AND位图
0306 ' ------------------------------------------------------------------------------------
0307 ' 说明:
0308 ' 1.上表中有关长度的数据,遵循“低位在前,高位在后”的原则。如果有4个字节,那么后2
0309 '  个字节为高位,前2个字节为低位,并且每2个字节内也是“低位在前,高位在后”。例如
0310 '  偏移量为00E的图象数据块的长度是28 01 00 00,在计算时要把它们反过来,变成00 00
0311 '  01 28,实际就是16进制的128即10进制的296;再如12 34 56 78,那么实际计算时就是:
0312 '  78 56 34 12,即10进制的2018915346
0313 ' 2.偏移量为024的“每象素所占位数”是指象素在XOR位图中所占的字节位数(1个字节=8位)
0314 '  ,04表示每个象素占4位,换言之,就是说XOR位图中每个字节可表示2个象素。该数据如为
0315 '  01 00,则表示单色(黑白位图),04 00为16色,08 00为256色,18 00为24位真彩。
0316 ' 3.XOR位图每字节对应2个像素(16色)或1个像素(256色),它的排列规律是:倒向(最末行的
0317 '  像素在最前,而第一行的像素在最后,由此类推),行内像素按从左至右的顺序,字节高
0318 '  位表示靠左的像素。AND位图每字节对应8个象素(每位对应1个象素),排列规律与XOR位
0319 '  图相同。
0320 ' 4.真彩图标没有调色板,而是在第 3部分 BMP 信息头的后面直接存放像素的 RGB 值,24位
0321 '  真彩图标每 3个字节对应1个像素值,其中每个字节分别对应该像素的 R、G、B值。像素的
0322 '  排列规律与调色板模式的图标相同。
0323 ' 5.上表的第一、二、三部分中,凡字节数为1的数据,其数据类型为Byte,字节数为2的数据,
0324 '  其数据类型为Integer,字节数为4的数据,其数据类型为Long(第三部分中有16个未用的
0325 '  的字节,是4个Long类型的数据,它们在.bmp位图中是有作用的)。
0326 
0327 '   下面是各种图标(内含1个图像)的调色板、图像数据的长度及总长度,括号内是起始字
0328 ' 节的偏移量:
0329 ' 单位:字节
0330 ' ------------------------------------------------------
0331 ' 图标规格     调色板   XOR位图   AND位图  总长度
0332 ' ------------------------------------------------------
0333 ' 16 色16×16象素 (62) 64 (126) 128 (254) 64   318
0334 ' 16 色24×24象素 (62) 64 (126) 288 (414) 96   510
0335 ' 16 色32×32象素 (62) 64 (126) 512 (638) 128  766
0336 ' 16 色48×48象素 (62) 64 (126) 1152 (1278)384 1662
0337 ' 256色16×16象素 (62)1024 (1086) 256 (1342) 64 1406    
0338 ' 256色24×24象素 (62)1024 (1086) 576 (1662) 96 1758
0339 ' 256色32×32象素 (62)1024 (1086)1024 (2110)128 2238
0340 ' 256色48×48象素 (62)1024 (1086)2304 (3390)384 3774
0341 ' 真 彩16×16象素           (62)  768 (830) 64   894
0342 ' 真 彩24×24象素           (62) 1728 (1790) 96 1886
0343 ' 真 彩32×32象素           (62) 3072 (3134)128 3262
0344 ' 真 彩48×48象素           (62) 6912 (6974)384 7358
0345 ' ------------------------------------------------------
0346 ' 说明:
0347 ' 1.XOR位图的长度与图标尺寸及图标的颜色数均有关,AND位图的长度只与图标的尺寸有关,
0348 '  与图标的颜色数无关。
0349 ' 2.XOR位图每字节对应2个像素(16色)或1个像素(256色)
0350 ' 3.AND位图每4字节为一组(这里所说的“一组”,其标准名称为“一条扫描线”,扫描线的
0351 '  定义是:位图中的一行数据信息叫做一条扫描线),但48×48图标的 AND 位图每8个字节
0352 '  为一组。组内每个颜色位对应1个象素。注意:
0353 '  ①16×16图标每组的后2个字节不用,所以实际上是2字节(16位)对应一行16个象素
0354 '  ②24×24图标每组的最后1个字节不用,所以实际上是3字节(24位)对应一行24个象素
0355 '  ③32×32图标每组4个字节32位对应一行32个象素
0356 '  ④48×48图标每组的后2个字节不用,所以实际上是6字节(48位)对应一行48个象素
0357 ' 4.为什么位图数据中会有不用的字节呢,这不是浪费吗?原来,Windows 有一个规定,每一
0358 '  条扫描线必须结束于一个32位的边界,也就是说,一条扫描线的位长度(按位计算)必须
0359 '  能整除32,或字节长度必须能整除4(XOR、AND 位图都是如此)。举例来说,如果一条扫
0360 '  描线只有 8位,那么就要用空白的24位来补充,如果有48位,那么还必须用空白的16位来
0361 '  补充。
0362 ' 5.XOR位图每条扫描线长度取决于两个因素:图像的宽度值和颜色数。各种颜色的图标的XOR
0363 '  位图每条扫描线的长度如下表所示(单位:字节):
0364 
0365 ' ①16色图标:
0366 ' ----------------------
0367 ' XOR图象宽度 扫描线长度
0368 ' ----------------------
0369     ' 16象素   8
0370 ' 17--24象素   12    
0371 ' 25--32象素   16
0372 ' 33--40象素   20
0373 ' 41--48象素   24
0374 ' 49--56象素   28
0375 ' 57--64象素   32
0376 ' 65--72象素   36
0377 ' 71--80象素   40
0378 ' ……
0379 ' ----------------------
0380 '   可以归纳出计算公式是:
0381 '  16色XOR位图每条扫描线长度=4×(图象宽\8+Abs((图象宽 Mod 8)>0))
0382 
0383 ' ②256色图标:
0384 ' ----------------------
0385 ' XOR图象宽度 扫描线长度
0386 ' ----------------------
0387     ' 16象素   16
0388 ' 17--20象素   20    
0389 ' 21--24象素   24
0390 ' 25--28象素   28
0391 ' 29--32象素   32
0392 ' 33--36象素   36
0393 ' 37--40象素   40
0394 ' 41--44象素   44
0395 ' 45--48象素   48
0396 ' ……
0397 ' ----------------------
0398 '   可以归纳出计算公式是:
0399 '  256色XOR位图每条扫描线长度=4×(图象宽\4+Abs((图象宽 Mod 4)>0))
0400 
0401 ' ③真彩图标:
0402 ' ----------------------
0403 ' XOR图象宽度 扫描线长度
0404 ' ----------------------
0405 ' 16象素    48
0406 ' 17象素    52    
0407 ' 18象素    56
0408 ' 19象素    60
0409 ' 20象素     60
0410 ' 21象素    64
0411 ' 22象素    68
0412 ' 23象素    72
0413 ' 24象素    72
0414 ' ……
0415 ' ----------------------
0416 '   可以归纳出计算公式是:
0417 '  真彩XOR位图每条扫描线长度=4×(图象宽×3\4+Abs((图象宽×3 Mod 4)>0))
0418 
0419 ' 6.AND位图每条扫描线的长度只与图标图像的宽度值有关。如下表所示(单位:字节):
0420 ' ----------------------
0421 ' AND图象宽度 扫描线长度
0422 ' ----------------------
0423 ' 16--32象素   4    
0424 ' 33--64象素   8
0425 ' 65--96象素   12
0426 ' 97--128象素   16
0427 ' 129--160象素  20
0428 ' 160--192象素  24
0429 ' 192--224象素  28
0430 ' 224--255象素  32
0431 ' ----------------------
0432 '   可以归纳出计算公式是:
0433 '  AND位图每条扫描线长度=4×(图象宽\32+Abs((图象宽 Mod 32)>0))
0434 
0435 ' 7.要使背景透明,XOR位图的背景必须为黑色(对应的颜色位=0),图案为彩色,而 AND位
0436 '  图则背景必须为白色(对应的颜色位=1),图案为黑色(对应的颜色位=0)
0437 ' 8.XOR位图的彩色图形信息中存储的并不是颜色值,而是与调色板对应的索引值,从 0 开始
0438 '  编号。
0439 ' 四、图标的颜色
0440 '   调色板模式的图标,其颜色是由调色板确定的,而调色板是可以自行定义的。比如16色
0441 ' 图标,其调色板只要有16种颜色就行。下面是以 QBasic 的16种颜色作为调色板时,XOR 位
0442 ' 图调色板的16色索引值与 QBColor 的颜色值对照:
0443 ' ----------------------------------------------------
0444 ' 颜色  索引值 QBasic 调色板中的值(最后一个字节未用) 
0445 ' ----------------------------------------------------
0446 ' 黑色  0       0      00 00 00   00
0447 ' 深红  1       4      00 00 80   00
0448 ' 深绿  2       2      00 80 00   00
0449 ' 深黄  3       6      00 80 80   00
0450 ' 深蓝  4       1      80 00 00   00
0451 ' 深紫  5       5      80 00 80   00
0452 ' 深青  6       3      80 80 00   00
0453 ' 深灰  7       8      80 80 80   00
0454 ' 浅灰    8       7      C0 C0 C0   00
0455 ' 红色  9       C(12) 00 00 FF   00
0456 ' 绿色  A(10)   A(10) 00 FF 00   00
0457 ' 黄色  B(11)   E(14) 00 FF FF   00
0458 ' 蓝色  C(12)   9      FF 00 00   00
0459 ' 紫色  D(13)   D(13) FF 00 FF   00
0460 ' 青色  E(14)   B(11) FF FF 00   00
0461 ' 白色  F(15)   F(15) FF FF FF   00
0462 ' ----------------------------------------------------
0463 '   怎么个对应法呢?举个例来说,比如16×16象素图标的 XOR位图中某个字节值为81,那
0464 ' 就表示该字节所对应的2个象素,左边的象素为浅灰色而右边的象素为深红色。
0465 
0466 ' 五、一个具体的例子
0467 '   有一个16色16×16象素的图标,该图标是一个边长为16、边框为红色的空心正方形,其
0468 ' 全部数据如下:
0469 ' ------------------------------------------------------
0470 ' 偏移量 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0471 ' ------------------------------------------------------
0472 ' 000    00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01
0473 ' 010    00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00
0474 ' 020    00 00 01 00 04 00 00 00 00 00 C0 00 00 00 00 00
0475 ' 030    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0476 ' 040    00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00
0477 ' 050    00 00 80 00 80 00 80 80 00 00 80 80 80 00 C0 C0
0478 ' 060    C0 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00
0479 ' 070    00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 99 99
0480 ' 080    99 99 99 99 99 99 90 00 00 00 00 00 00 09 90 00
0481 ' 090    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0482 ' 0A0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0483 ' 0B0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0484 ' 0C0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0485 ' 0D0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0486 ' 0E0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0487 ' 0F0    00 00 00 00 00 09 99 99 99 99 99 99 99 99 00 00
0488 ' 100    00 00 7F FE 00 00 7F FE 00 00 7F FE 00 00 7F FE
0489 ' 110    00 00 7F FE 00 00 7F FE 00 00 7F FE 00 00 7F FE
0490 ' 120    00 00 7F FE 00 00 7F FE 00 00 7F FE 00 00 7F FE
0491 ' 130    00 00 7F FE 00 00 7F FE 00 00 00 00 00 00
0492 ' ------------------------------------------------------
0493 
0494 '   下面对位图部分的数据加以说明:
0495 ' 1.XOR位图最末一行的数据在07E-085这8个字节中,由于是一条红线,所以索引值均为9。
0496 ' 2.XOR位图倒数第二行的数据在086-08D这8个字节中,该行的首尾2个象素为红色,其余14个
0497 '  象素为背景色,所以086字节所对应象素的颜色索引值分别为9、0,而08D字节所对应象素
0498 '  的颜色索引值分别为0、9,因为要屏蔽背景色,所以除了红色外,其余均为黑色,黑色在
0499 '  调色板中的索引值为0。其余行的数据也照此分析。
0500 ' 3.AND位图最末一行的数据在0FE-101这4个字节中,后2个字节没用,前2个字节为00 00,
0501 '  因为要屏蔽背景色,AND位图的图象位必须为0(黑色),而不管这图象原来是什么颜色,
0502 '  所以,这一行是红线,相应的颜色位就全是0了。
0503 ' 4.AND位图倒数第二行的数据在102-105这 4个字节中,前2个字节对应该行的16个象素,其
0504 '  值为7F FE。先看7F,其二进制为 01111111,因为该行首个象素为红色,所以对应的最高
0505 '  位为0(黑色),跟着的7个象素都是背景色,而在AND位图中,要屏蔽背景色,那么背景色
0506 '  的对应位应该是白色,白色在单色中表示为1,所以这8个象素所表示的16进制值就是7F了。
0507 '  再看FE,其二进制值为 11111110,它对应的该行后8个象素,而该行最后1个象素是红色,
0508 '  所以对应的最低位为0(黑色),其它象素是背景色,所以对应的位都是1(白色)。
0509 ' 5.其它行的数据,可以比照上述的方法自行分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值