按照圖像處理--GIF和靜態圖的疊加和圖像處理--GIF和靜態圖疊加(二)的思路,已經可以實現GIF和靜態圖的疊加了,但是我們已經知道,GIF最高支持8位256色,那麼如果原圖是真彩色的,則在生成最終效果圖時,就涉及到真彩色到256的降色。真彩色是24位的,有2^24種顏色,每個像素用3個字節標識一個顏色,R、G、B各佔一個字節,而256色每個像素只用一個字節從調色板中索引一種顏色,調色板最多有256種顏色。將2^24種顏色降爲256種顏色,降色的過程被成爲色彩量化。可想而知,色彩空間的減小必然造成大量的色彩丟失,進而造成一些像素找不到原來的顏色值,那麼對於這種像素點,就需要給它找一個和原來顏色最接近的新顏色,記錄新顏色在256色調色板中的索引。
256的調色板有兩種,標準調色板和由當前圖片得到的自定義調色板。後者的意思是,使用將被量化的圖片定製出一個調色板,這個調色板由將被量化圖片中使用頻率最高的256種顏色組成,這樣可以在量化時,使儘可能多的像素在調色板中準確的找到和量化前該像素顏色值完全一樣的顏色,結果就是量化後色彩丟失最少。
所以,一個好的色彩量化過程分兩步:1、根據圖片定製調色板;2、遍歷像素,對於每一個像素,從調色板中找最接近的顏色,記錄該顏色索引。
那麼如何定製一個調色板呢?
最簡單的方式也最容易想到:
1、創建一個鏈表,每一個節點記錄顏色的RGB值,以及該顏色在原圖像素矩陣中出現的次數Count。
2、遍歷原圖(真彩色)的像素矩陣,對於每一個像素,如果它的顏色在鏈表中存在,則把該節點中Count加1,如果它的顏色在鏈表中不存在,則新建該顏色節點。
3、遍歷完後,按照Count對鏈表堆排序,得到前256個節點。這256個節點中的RGB值就是定製的調色板了。
這種方式好簡單,但實在是太坑爹了...順序訪問的效率可想而知。
於是有了第二種方法:八叉樹方式建立調色板。
比如顏色A,它的RGB爲F361A4,在三維色彩空間,使用座標R:F3、G:61、B:A4可以唯一確定這個顏色。怎麼樣才能將顏色空間從三維映射到一維呢?因爲這樣就是線性的了。方法還是有的,對於每一個顏色值,將RGB分量的每一個Bit位,可以按照下面的公式操作Result = R | (G<<1) | (B<<1) ,則Result可以看作是一個長度爲8的數組,每個元素值在0~8之間,得到如下表格:
R | 0xF3 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
G | 0x61 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
B | 0xA4 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
Result | 5 | 3 | 7 | 1 | 0 | 4 | 1 | 3 |
則該Result在一個八叉樹中,可以如下標識該顏色:
八叉樹最多有8層,每一層有8個節點,那麼一個滿八叉樹的葉子節點就有8^8共2^24個節點。這些恰好是真彩色的顏色總數,也就是說一個滿八叉樹的葉子節點可以一一對應到真彩色的每一種顏色。經過上面顏色空間三維到一維的映射,Result值就可以通過這棵樹找到屬於自己的葉子節點,也就是自己的顏色。而樹的插入、查找速度都是很快的,所以用八叉樹作爲數據結果建立調色板,是一種不錯的選擇。
在實際操作生成256色調色板的過程中,先被讀入的256種顏色作爲初始化顏色建立起樹,然後一旦有新的顏色出現時,就要進行顏色歸併,保證任何時刻都不會超過256種顏色。這樣可以降低開銷。
問題是超過256時怎麼歸併呢?只有合理歸併,才能更好的保證圖片質量,下面是幾個歸併條件:
( 1) 深度最大的子樹首先選擇。在色彩八叉樹中, 深度爲8 的葉子結點表示了色彩空間中
一個準確顏色, 非葉結點代表了色彩空間的子空間, 非葉結點深度與其代表顏色區間大小成
反比, 與其表示的顏色準確度成正比, 在最大深度子樹上歸併, 相當於在最小顏色子空間上
做歸併, 所代表的色度空間越小, 歸併的顏色越相近, 代表色失真度越小, 色彩近似優化程
度越高。
( 2) 深度相同頻度最小先歸約。按頻度序列思想, 在多個深度相同的同層可歸約點中, 應
先歸併當前代表最少色素數目的結點。這樣使得使用頻率低的用較接近的代表色填充, 而頻
率高結點未被歸併, 則用最接近的色彩填充, 這樣, 最大區域將填上最小誤差的色彩, 以保
持原始圖像上細微差別。
( 3) 取被歸併子樹均值作代表色, 將所有被歸併結點色彩與頻度求和取均值作爲代表色,
使代表色儘可能靠近頻度高的色彩, 增強代表色的逼真度。
參考論文《基於八叉樹結構的色彩量化算法》
經過上面的處理,就可以得到定製後的調色板,使用該調色板進行量化,可以得到比較好的效果。
量化就比較簡單了,按照三維空間兩點之間距離的方式,對於原圖中的每一個像素點M(R、G、B),遍歷調色板中的256種顏色,對於調色板顏色N(r、g、b),機選MN的距離d,找到可以使距離d最小的N,則記錄N的索引即可。如果d爲0,則說明,該顏色在量化中沒有被去掉,可想而知,這個顏色在原圖中出現的頻率是很高的。
下面貼幾張圖比較下使用調準調色板和定製調色板量化效果:
原圖:
標準調色板量化後:
定製調色板量化後:
最後說明一下:如果直接使用GDI+讀入真彩色圖,再保存成256色圖gif,效果是這樣的:
可以看到效果還不錯,但是整體上有種“浮雕”的感覺,有很多顆粒,稱爲抖動。因爲GDI+使用了標準調色板+誤差擴散,誤差擴散下一次再說吧。