2014-10-05 103 views
2

我需要利用彼此,其α值加起來爲1。混合兩個圖像HTML5畫布

例如頂部上的相同的圖像的2個版本:
- imageA具有0.4α,而imageB具有0.6的alpha。
- 期望的結果是完全不透明的圖像(每個像素的α爲1.0),其顯示爲imageB的60%混合物和imageA的40%混合物。

但是,我認爲,在默認情況下HTML5的Canvas使用低於1阿爾法繪製不是增加對alpha混合的圖像以外的混合模式,所以兩兩件事不會加起來1
我已經嘗試了所有的不同合成模式以及Adobe混合模式,但沒有一個具有所需的結果。
一個簡單的測試用例是繪製一個品紅rect兩次,兩者的alpha都是0.5。我的願望是所產生的像素是rgb(255, 0, 255)。但是,結果略顯透明。

有沒有人知道某種方式來實現這個結果?

回答

2

•如果你看一下有關默認混合模式的canvas'context2D規範(「源在」):

http://dev.w3.org/fxtf/compositing-1/#simplealphacompositing

你會看到使用的公式是(我改名爲變量清晰度):

colorOut = prevColor x prevAlpha + newColor x newAlpha x (1 - prevAlpha) 

而對於所得的α:

αlphaOut = prevAlpha + newAlpha x (1 - prevAlpha) 

注意到,
a)出乎意料地,公式不是線性的(歸因於:newAlpha x(1-prevAlpha)因子)。
b)一個點有兩個較小的r,g,b值還原的α。所以當重新使用它時, 將爲最終圖像貢獻平方(0.6)== 0.36。 (...完全違反直覺......)

•那麼60%/ 40%的抽籤會發生什麼?

1)圖片A用alpha = 60%繪製。上述 的公式給出:

colorOut = color_A * 0.6 ; 
alphaOut = 0.6 ; 

2)圖像B被繪製具有α= 40%

colorOut = color_A * 0.6 * 0.6 + color_B x 0.4 x (0.4); 
alphaOut = 0.6 + 0.4 * 0.4; 

所以最終公式==>

colorOut = 0.36 * color_A + 0.16 * color_B ; 
alphaOut = 0.76 ; 

你看,這不是在所有您預期的60/40混合。

•如何解決?

1)你可以用getImageData/putImageData手工完成。請注意Cross-Origin問題:如果您的圖片不是來自您的域,他們的imageData將是空的。對於表演,與畫布(= GPU)相比,下注50+的減速因子。根據圖像尺寸/計算能力/瀏覽器的不同,「實時」(= 60fps)可能無法實現。但你完全可以控制。

2)但是,如果你現在看 'ligther' 複合模式,看來我們有我們的人:現在

http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators_plus

公式爲:

colorOut = prevColor x prevAlpha + newColor x newAlpha 

而對於導致阿爾法:

αlphaOut = prevAlpha + newAlpha 

您會發現這是一個簡單的「加號」運算符,完美滿足您的要求。
所以解決方法是:
- 保存ctx。
- 設置較輕的複合模式。
- 以60%alpha繪製第一幅圖像。
- 以40%alpha繪製第二張圖片。
- 還原ctx。

最後的話:如果你想檢查最終α是正確的(== 255),使用該種功能:

function logAlpha(ctx,x,y) { 
    var imDt = ctx.getImageData(x,y,1,1).data; 
    if (!(imDt[0] || imDt[1] || imDt[2])) console.log('null point. CORS issue ?'); 
    console.log(' point at (' +x+ ',' +y+ ') has an alpha of ' + imDt[3]) ; 
} 
+0

「較輕」爲我工作。非常感謝!非常翔實的答案。 – phosphoer 2014-10-05 19:55:01