I am trying to set individual pixels in the HTML canvas by using putImageData(). When I do this and then immediately read those pixels back out using getImageData(), the RBG values I just set have been changed! See example:
var ct = canvas.getContext('2d');
var image = ct.getImageData(0,0,1,1);
var data = image.data;
data[0] = 200; //r
data[1] = 100; //g
data[2] = 50; //b
data[3] = 25; //a
console.log(data); //[200, 100, 50, 25] Yeah :)
ct.putImageData(image,0,0);
var debug = ct.getImageData(0,0,1,1);
console.log(debug.data); //[204, 102, 51, 25] Boo :(
If I set the alpha channel to 255 (no transparency) then the RGB values aren't altered. If I set the alpha channel to 0 (transparent) then the RGB comes back as 0,0,0. Obviously it has something to do with transparency. It probably has something to do with the RGB color space and math.
I am trying to figure out why this happens or at least be able to predict the results in some way. Can someone please clue me in about what is going on here?
It is due to the process of compositing and in particular with premultiplying the alpha channel. The standard states:
Due to the lossy nature of converting to and from premultiplied alpha colour values, pixels that have just been set using putImageData() might be returned to an equivalent getImageData() as different values.
It's a relative deep and wide topic, but if you want to dive into the particulars for the math behind it, I would recommend looking at the Porter-Duff algorithms found at this link. See in particular blending and alpha compositing. Considering also that the browser uses 8-bit integer values in these formulas.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With