大家可以在網上搜尋相關的主題啊,你可以搜尋到一堆,不過似乎沒有那一個講的很全面,我這裡抽空整理和測試一下資料,分享給大家。
我們假定有2個32位的圖層,圖層BG和圖層FG,其中圖層BG是背景層(位於下部),圖層FG是前景層(位於上部),我們摸索其混合後的顏色的計算公式。
我們取一個點的畫素做分析:
其中BG層某點的顏色為: B1 = 168 G1 = 99 R1= 114 A1 = 70
其中FG層某點的顏色為: B2= 80 G2 = 71 R2= 162 A2 = 135
場景一:兩個圖層直接疊加
即混合模式為正常,前景的不透明度為100%,如下所示:
得到的混合結果為 B = 97 G = 76 R = 153 A = 168
注意這些資料的格式都是 Format32bppArgb,而非Format32bppPArgb,即沒有進行預乘的ARGB資料。
根據這些資料進行推算,得出以下規律,首先是結果色的A值計算公式如下:
其中ClampToByte函式的作用為限制括號內的資料在0和255之間,如果大於255,則取255,如果小於0,則取0值。
按照此公式複核下上面的結果看下:
結果正確。
對於RGB各分量,計算公式要複雜很多,經過推到和測試結果如下(以B分量為例):
把資料帶入核算一下:
同理:
公式完全正確。
上面的計算如果要保證精度,則A值需要用浮點數儲存,這樣可能在某些場合下造成計算瓶頸,如果要全部用整數運算,可利用用Matlab的符號運算在做簡化。
在matlab中用如下程式碼做測試:
syms B1 A1 B2 A2; B =( B1 * A1 + B2 * A2 - A1 * A2 / 255 * B1) / (A1 + A2 - A1 * A2 / 255); simplify(B)
得到結果:
B1 - (255*A2*(B1 - B2))/(255*A2 - A1*(A2 - 255))
這個結果只有一個除法,而且可以看到除法的分子和分母的資料也不會大於int32所能表達的範圍。這樣可藉助於整數的除法實現結果。
場景二:僅僅改變圖層混合模式
我們僅僅改變前景色圖層的混合模式,而不改變其不透明度。以正片疊底模式為例,如下圖所示:
此時前述兩個顏色的混合值如下所示:
B = 91 G = 67 R = 133 A = 168
注意到A值並沒有任何的變化。
此時,我們定義一個函式F,表示混合模式對兩種的顏色影響,F(X, Y)表示某種混合模式下兩種顏色值X和Y的混合結果,對於正片疊底,F(X,Y)的計算方法為:
F(X,Y) = X * Y / 255;
經過測試,這個時候的RGB分量的混合公式為:
把資料帶入核算一下:
G和R的值就不進行重複的核算了。
這個計算式用Maltab去簡化的話基本沒有任何效果。
場景三:僅僅改變圖層的不透明度
如下所示設定,前景層的不透明度為70%。
此時前述兩個顏色的混合值如下所示:
B = 108 G = 80 R = 147 A = 139
所有的顏色都變了。
還是先來看A值,經過測試比對,此時A值的計算公式為:
其中O表示不透明度的值,有效範圍是[0,100]。
核算一下:
對於A值,我們可以認為不透明度首先修改了改成的Alpha,然後再拿這個新的Alpha和底層的Alpha進行正常的混合。
對於RGB各分量,經過推到和測試結果如下(以B分量為例):
核算一下:
正確無誤。
場景四:同時改變圖層混合模式和不透明度
如下所示設定,同時設定混合模式為正片疊底,不透明度為70%。
此時前述兩個顏色的混合值如下所示:
B = 103 G = 72 R = 130 A = 139
可以看到,A值和混合模式沒啥關係,之和不透明度有關,直接用只改變不透明度時的公式:
那麼RGB的變化,從前面的幾個公式中可以猜測肯定是先下面這個式子了:
測試下:
完全正確。
那麼在寫程式碼的時候,我們最需要優化的就是這個情況的公式。不過用matlab測試這個公式沒啥好優化的。
上述公式裡其實有些ClampToByte函式是可以不需要的。
上傳下我用於測試兩個小的32點陣圖像了供有興趣的朋友測試。
圖片非常小啊,注意仔細觀察並下載。
如果想時刻關注本人的最新文章,也可關注公眾號: