栗子現場直播 千篇一栗
有很多簡單的道理,若不是被遺忘,不是察覺不到,就是知易行難。

2008年10月16日 星期四

透明的顏色

  其實好久以前,就已經在 DonKat 發現了一個繪圖問題。直到近來出手研究的時候,才發現問題頗叫人頭痛。  如果大家留意一下上圖的話,就會發現藍波邊沿有一條白圈,而紅波則沒有。
  這兩個波,分別來自不同的 png 檔,而這兩個檔本來都沒有那一條白邊,但卻有很細微的差異。

  電腦的顏色資料,最一般是 RGB 值。如果涉及到透明的使用,還會有 alpha 值,加起來就是 ARGB 。這個是電腦繪圖的基本知識。
  而所謂的全透明色, A 值就是 0 。至於 RGB ,在 A=0 的情況下,理論上不論是甚麼值都不會對顯示有任何影響。這個也是很基本知識。
  然而,如果把圖片改變大小,旋轉,扭曲的時候,使用了錯誤或過份簡單的計算方法,即使 A=0 , RGB 值也會影響到輸出結果。
  例如一幅只有兩個 pixel 的圖,兩點的顏色分別是 #FF0000 及全透明。如果我們把這兩個 pixel 合併為一個 pixel ,理論上應該會得到一點 50% 透明度的 #FF0000 ,即為 #7FFF0000 。但是,如果電腦只是直接把 ARGB 四個值分開計平均數,就會得到錯誤的答案。
  例如,在全透明色數值是 #00000000 的時候,和 #FFFF0000 的平均值會成為 #7F7F0000 ,即變成 50% 半透的 #7F0000 ,和我剛才的答案不一樣。
  又或者,在全透明色數值是 #00FFFFFF 的時候,和 #FFFF0000 的平均值會成為 #7FFF7F7F ,即為 50% 半透的 #FF7F7F ,和我的答案及上一個答案也不一樣。
  因此,當我們要計算顏色時, A 值固然可以用平均值計算,但計算 RGB 時則要考慮到 A 值的比重。

  回到我最初的問題。我圖中藍球之所以出現白邊,是因為繪圖程式自動把全透明色填為 #00FFFFFF 。而紅球的圖檔,因為我在背景填上 1% 的黑色,所以背景是 #03000000 (估計)。因為和原圖都是黑色邊界的關係,所以對原圖沒有影響。但是,如果想做到最好的效果,看來要另外找程式為全透明部份填上 #00000000 才行。

1 則留言:

Ben Lau 提到...

對了,關於你在Barcamp時提過的Image tearing/vsync問題,我找到編文章解得很清淅,你下次再講talk時或許會有用:

http://www.hardforum.com/showthread.php?t=928593