1. 程式人生 > >ico檔案結構及顯示

ico檔案結構及顯示

因為編寫一個圖示編輯程式,分析了一下圖示的檔案格式,頗有一些心得,寫出
來與各位兄弟共享。(筆者注:以下所說的圖示均為調色盤模式的圖示,真彩圖標會特別注
明)

一、從圖示的顯示原理說起
  每個圖示都是由兩個單獨的點陣圖組成的。如果該圖示是遮蔽背景色的話,那麼,

第二個點陣圖是由白色背景(相關的顏 色位全為1)與黑色圖示圖案(相關的顏色位全為0)組成的,

該點陣圖將與當前螢幕顯示通過 與操作(AND)結合起來,故稱其為AND點陣圖。

第一個 點陣圖是由黑色背景(相關的顏色位全為 0)與彩色圖示圖案組成的,該點陣圖將與當前螢幕顯
示通過異或操作(XOR)結合起來,故稱其為XOR點陣圖;因此,圖示的顯示是通過兩個步驟完成的:
1.當前螢幕顯示與AND點陣圖通過AND操作結合起來;
2.當前螢幕顯示與XOR點陣圖通過XOR操作結合起來。
  大家知道,1與任何數值AND操作的結果將維持原數值,而0與任何數值AND操作的結果則
是0,因此在步驟1中,AND點陣圖中的白色(1)與螢幕顯示經過AND操作後被原色彩遮蔽,而黑
色(0)則將原色彩遮蔽。步驟1結束後,螢幕上將留下一個黑色的圖示圖案。在隨後的步驟
2中,由於0與任何數值異或的結果都將是原數值,因此,XOR點陣圖與螢幕顯示經過異或操作後,
點陣圖和螢幕中的黑色部分都將被各自對應的彩色部分遮蔽。步驟2結束後,一個形狀不規則的
圖示圖案就出現在螢幕上了,這就是圖示顯示的原理。

二、圖示的圖形
  圖示的圖形,實際上就是點陣圖格式的圖片,是一個標準的點陣圖格式。Windows只要從BMP
資訊頭中獲取資訊就足夠了,它據以解釋在其後出現的資料應該如何處理。如果是調色盤模
式,其後的資料包含有調色盤和畫素點顏色索引,如果是真彩色,其後的資料直接就是畫素
點的 RGB 顏色值。
  而點陣圖檔案是由檔案頭、BMP 資訊頭、調色盤、資料區(又稱點陣圖點陣)等幾個部分組
成的。知道了這個情況,我們可以簡單地把上面敘述的圖示圖形結構理解為點陣圖資訊。這樣,
我們就有可能根本不需要真的去畫一幅圖,而只需要對關鍵資料進行程式填充就可以了,所
編寫的程式碼,直接按圖示格式的要求,可把一個只要尺寸不大於255×255畫素的任意點陣圖,
封裝成標準格式的圖示(真實的點陣圖寬高尺寸保持不變,所以可以做出最大255×255的圖示
來)。

三、圖示的資料結構
  圖示檔案的資料結構可分為6部分,其資料結構如下:
-----------------------------------------------------------------------
順號 名稱      長度(單位:位元組)  說明
-----------------------------------------------------------------------
1  檔案頭     6        
2  圖象資訊塊   16          有多少個影象,則資訊塊也有多少個
3  BMP 資訊頭   40          
4  XOR 點陣圖調色盤 16色=64,256色=1024  真彩圖標從此開始畫素點的 RGB 值 
5  XOR 點陣圖               以調色盤的索引值形式存放
6   AND點陣圖  
-----------------------------------------------------------------------
說明:
1.上表中的3-6部分合稱影象資料塊,其中5、6部分又合稱為影象資料區(也稱點陣圖點陣)
2.不論何種規格的圖示,其1-3部分的位元組長度是固定的。
3.請注意第 2部分的圖象資訊塊的說明,“如果有多少個影象”是什麼意思呢?原來,在一
 個圖示檔案中,有可能存放幾個影象(windows圖示最多可有8個影象),但每個影象都有
 自己的調色盤、XOR 點陣圖和 AND 點陣圖,且它們的影象大小也可能不相同。以16色有3個圖
 像為例,其資料結構如下:
----------------------------------------------------------------- 
 
  順號 名稱        長度 說明
-----------------------------------------------------------------
1  檔案頭              6
2  圖象1的圖象資訊塊   16  
3  圖象2的圖象資訊塊   16
4  圖象3的圖象資訊塊   16
5  圖象1的圖象資料塊   不定 其中BMP資訊頭和調色盤固定為40和64位元組
6  圖象2的圖象資料塊   不定 同上
7  圖象3的圖象資料塊   不定 同上
------------------------------------------------------------------

  下面以內含1個影象、16色、16×16規格的圖示為例詳述(偏移量括號前為10進位制,括
號內為16進位制):
----------------------------------------------------------------------------
偏移量  位元組數  描述               典型值(16進位制)
----------------------------------------------------------------------------
 (一、檔案頭6位元組)
000(000)2    保留的位元組            00 00
002(002)2    資源型別             01 00 (01為圖示,02為游標)
004(004)2    圖象個數             01 00
 (二、影象資訊塊16位元組) 
006(006)1    圖示寬度             10
007(007)1    圖示高度             10
008(008)1    顏色計數             10(02=單色, 00≥256色)
009(009)1    未用                00
010(00A)4    保留的              00 00 00 00
014(00E)4    圖象資料塊的長度                28 01 00 00(10進位制=296)
018(012)4    圖象資料塊相對於檔案頭部的偏移量 16 00 00 00(10進位制=22)
 (三、BMP資訊頭40位元組)
022(016)4    BMP 資訊頭結構長度        28 00 00 00(10進位制=40) 
026(01A)4    影象寬度              10 00 00 00
030(01E)4    影象高度(XOR圖高度+AND圖高度) 20 00 00 00
034(022)2    位面板數                         01 00
036(024)2    每象素所佔位數                   04 00
038(026)4    象素資料的壓縮型別        00 00 00 00(表示未壓縮)
042(02A)4    圖象資料的長度          C0 00 00 00(10進位制=192)
046(02E)16   未用               16個00
 (四、XOR點陣圖的調色盤64位元組)
062(03E)1    藍色分量 
063(03F)1    綠色分量 
064(040)1    紅色分量 
065(041)1    未用               00 
  ……
 (五、XOR點陣圖的資料) 
126(07E)128   XOR點陣圖              
 (六、單色AND點陣圖的資料)
254(0FE)64   AND點陣圖
-----------------------------------------------------------------------------
說明:
1.上表中有關長度的資料,遵循“低位在前,高位在後”的原則。例如偏移量為00E的圖象數
 據塊的長度是28 01 00 00,在計算時要把它們反過來,變成00 00 01 28,實際就是16進
 制的128即10進位制的296。
2.偏移量為024的“每象素所佔位數”是指每個象素在XOR點陣圖中所佔的位數(1個位元組=8位)
 ,04表示每個象素佔4位,換言之,就是說XOR點陣圖中每個位元組可表示2個象素。該資料如為
 01 00,則表示單色(黑白點陣圖),04 00為16色,08 00為256色,18 00為24位真彩。
3.XOR點陣圖每位元組對應2個畫素(16色)或1個畫素(256色),它的排列規律是:倒向(最末行的
 畫素在最前,由此類推),行內畫素按從左至右的順序,位元組高位表示靠左的畫素。AND位
 圖每位元組對應8個象素(每位對應1個象素),排列規律與XOR點陣圖相同。
4.真彩圖標沒有調色盤,而是在第 3部分 BMP 資訊頭的後面直接存放畫素的 RGB 值,24位
 真彩圖標的每 3個位元組對應1個畫素值,其中每個位元組分別對應該畫素值的R、G、B值。像
 素排列規律與調色盤模式的圖示相同 

  下面是各種圖示的調色盤、影象資料的長度及總長度,括號內是偏移量:

單位:位元組
------------------------------------------------------
圖示規格     調色盤   XOR點陣圖   AND點陣圖  總長度
------------------------------------------------------
16 色16×16象素 (62)  64  (126)  128  (254)  64   318
16 色24×24象素 (62)  64 (126)  288 (414)  96   510
16 色32×32象素 (62)  64 (126)  512 (638) 128  766
16 色48×48象素 (62)  64 (126) 1152  (1278)384  1662
256色16×16象素 (62)1024 (1086) 256  (1342) 64 1406    
256色24×24象素 (62)1024 (1086) 576 (1662) 96 1758
256色32×32象素 (62)1024 (1086)1024  (2110)128  2238
256色48×48象素 (62)1024 (1086)2304  (3390)384 3774
------------------------------------------------------
說明:
1.XOR點陣圖每位元組對應2個畫素(16色)或1個畫素(256色)
2.AND點陣圖每4位元組為一組(48×48圖示的AND點陣圖每8個位元組為一組),組內每個顏色位對
 應1個象素。注意:
 ①16×16圖示每組的後2個位元組不用,所以實際上是2位元組(16位)對應一行16個象素
 ②24×24圖示每組的最後1個位元組不用,所以實際上是3位元組(24位)對應一行24個象素
 ③32×32圖示每組4個位元組32位對應一行32個象素
 ④48×48圖示每組的後2個位元組不用,所以實際上是6位元組(48位)對應一行48個象素
3.為什麼AND點陣圖中會有不用的位元組呢,這不是浪費嗎?原來,Windows有一個規定,每一條
 掃描線(點陣圖中的一行資料資訊叫做一條掃描線)必須結束於一個32位的邊界。也就是說,
 一條掃描線的位長度(按位計算)必須能整除32,或位元組長度必須能整除4,也就是說,如
 果只有8位,那麼拿空白的24位來補充,如果只有48位,那麼也就拿空白的16位來補充。
4.要使背景透明,XOR點陣圖的背景必須為黑色(對應的顏色位=0),圖案為彩色,而 AND位
 圖則背景必須為白色(對應的顏色位=1),圖案為黑色(對應的顏色位=0)
5.XOR點陣圖的彩色圖形資訊中儲存的並不是顏色值,而是與調色盤對應的索引值,從 0 開始
 編號。

四、圖示的顏色
  調色盤模式的圖示,其顏色是由調色盤確定的,而調色盤是可以自行定義的。比如16色
圖示,其調色盤只要有16種顏色就行。下面是以 QBasic 的16種顏色作為調色盤時,XOR 位
圖調色盤的16色索引值與 QBColor 的顏色值對照:
----------------------------------------------------
顏色  索引值  QBasic 調色盤中的值(最後一個位元組未用) 
----------------------------------------------------
黑色  0       0      00 00 00   00
深紅  1       4      00 00 80   00
深綠  2       2      00 80 00   00
深黃  3       6      00 80 80   00
深藍  4       1      80 00 00   00
深紫  5       5      80 00 80   00
深青  6       3      80 80 00   00
深灰  7       8      80 80 80   00
淺灰    8       7      C0 C0 C0   00
紅色  9       C(12)  00 00 FF   00
綠色  A(10)   A(10)  00 FF 00   00
黃色  B(11)   E(14)  00 FF FF   00
藍色  C(12)   9      FF 00 00   00
紫色  D(13)   D(13)  FF 00 FF   00
青色  E(14)   B(11)  FF FF 00   00
白色  F(15)   F(15)  FF FF FF   00
----------------------------------------------------

  怎麼個對應法呢?舉個例來說,比如 XOR點陣圖中某個位元組值為81,那就表示該位元組所對應的2個象素,左邊的象素為淺灰色而右邊的象素為深紅色。

五、一個具體的例子
  有一個16色16×16象素的圖示,該圖示是一個紅色的大“口”字形,其全部資料如下:
------------------------------------------------------
偏移量 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
------------------------------------------------------
000    00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01
010    00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00
020    00 00 01 00 04 00 00 00 00 00 C0 00 00 00 00 00
030    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
040    00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00
050    00 00 80 00 80 00 80 80 00 00 80 80 80 00 C0 C0
060    C0 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00
070    00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 99 99
080    99 99 99 99 99 99 90 00 00 00 00 00 00 09 90 00
090    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0A0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0B0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0C0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0D0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0E0    00 00 00 00 00 09 90 00 00 00 00 00 00 09 90 00
0F0    00 00 00 00 00 09 99 99 99 99 99 99 99 99 00 00
100    00 00 7F FE 00 00 7F FE 00 00 7F FE 00 00 7F FE
110    00 00 7F FE 00 00 7F FE 00 00 7F FE 00 00 7F FE
120    00 00 7F FE 00 00 7F FE 00 00 7F FE 00 00 7F FE
130    00 00 7F FE 00 00 7F FE 00 00 00 00 00 00
------------------------------------------------------

  下面對點陣圖部分的資料加以說明:
1.XOR點陣圖最末一行的資料在07E-085這8個位元組中,由於是一條紅線,所以索引值均為9
2.XOR點陣圖倒數第二行的資料在086-08D這8個位元組中,該行的首尾2個象素為紅色,其餘14個
 象素為背景色,所以086位元組所對應象素的顏色索引值分別為9、0,而08D位元組所對應象素
 的顏色索引值分別為0、9,因為要遮蔽背景色,所以除了紅色外,其餘均為黑色,黑色在
 調色盤中的索引值為0。其餘行的資料也照此分析。
3.AND點陣圖最末一行的資料在0FE-101這4個位元組中,後2個位元組沒用,前2個位元組為00 00,
 因為要遮蔽背景色,AND點陣圖的圖象位必須為0(黑色),而不管這圖象原來是什麼顏色,
 所以,這一行是紅線,相應的顏色位就全是0了。
4.AND點陣圖倒數第二行的資料在102-105這 4個位元組中,前2個位元組對應該行的16個象素,其
 值為7F FE。先看7F,其二進位制為 01111111,因為該行首個象素為紅色,所以對應的最高
 位為0(黑色),跟著的7個象素都是背景色,而在AND點陣圖中,要遮蔽背景色,那麼背景色
 的對應位應該是白色,白色在單色中表示為1,所以這8個象素所表示的16進位制值就是7F了。
 再看FE,其二進位制值為 11111110,它對應的該行後8個象素,而該行最後1個象素是紅色,
 所以對應的最低位為0(黑色),其它象素是背景色,所以對應的位都是1(白色)。
5.其它行的資料,諸位兄弟可以比照上述的方法自行分析。