Blending Two Images With Html5 Canvas
Solution 1:
• If you look at the canvas'context2D specification about the default blending mode ('source-over'):
http://dev.w3.org/fxtf/compositing-1/#simplealphacompositing
You'll see the formula used is ( i renamed the variables for clarity) :
colorOut = prevColor x prevAlpha + newColor x newAlpha x (1 - prevAlpha)
And for resulting alpha :
αlphaOut = prevAlpha + newAlpha x(1 - prevAlpha)
Notice that, a) unexpectedly, the formula is not linear (due to : newAlpha x (1 - prevAlpha) factor ). b) a point has both smaller r,g,b values and reduced alpha. So when re-using it, it will contribute for square(0.6)==0.36 to the final image. (...completely counter-intuitive...)
• So what does happen for your 60% / 40% draws ?
1) image A is drawn with alpha = 60%. The formula above gives :
colorOut = color_A * 0.6;alphaOut = 0.6;
2) image B is drawn with alpha = 40%
colorOut = color_A * 0.6 * 0.6 + color_B x 0.4 x (0.4);alphaOut = 0.6 + 0.4 * 0.4;
So final formula is ==>
colorOut = 0.36 * color_A + 0.16 * color_B ;alphaOut = 0.76;
You see that's not at all the 60/40 mix you expected.
• How to fix ?
1) You can do it by hand using getImageData / putImageData. Be aware of the Cross-Origin issue : if your images don't come from your domain, their imageData will be empty. For performances, bet on a 50+ slow-down factor compared to the canvas (= the GPU) doing the job. 'real time' (=60fps) might not be possible depending on image size/computing power/browser. But you have full control.
2) But if you now look at the 'ligther' composite mode, it seems we have our guy :
http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators_plus
Formula is now :
colorOut = prevColor x prevAlpha + newColor x newAlpha
And for resulting alpha :
αlphaOut = prevAlpha + newAlpha
You see that this is a simple 'plus' operator, perfect for your requirement. So solution is : - save ctx. - set lighter composite mode. - draw first image at 60% alpha. - draw second image at 40% alpha. - restore ctx.
Last words : if you want to check that the final alpha is right (==255), use that kind of function :
functionlogAlpha(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] ) ;
}
Post a Comment for "Blending Two Images With Html5 Canvas"