I have completely transparent image and i want to get rgb data for each pixel.
Think of it as a hidden picture.
The usual approach of manipulating image data in javascript is
ctx.drawImage(img, 0, 0);
However if i access the canvas data after the draw, all of the pixels are black. I have verified that i can make the picture visible with php GD.
Any ideas on how to do it in js?
Edit: i know that i could get a js library that directly parses image data but i am looking for a solution withoult libraries.
In canvas API, every pixel with an alpha of 0 is treated as black transparent pixel.
var c = document.createElement('canvas');
var ctx = c.getContext('2d');
c.width = c.height = 1;
ctx.fillStyle = 'rgba(0,255,0,0)'
ctx.fillRect(0,0,1,1)
var i = ctx.getImageData(0,0,1,1)
console.log('after fillRect:',i.data);
i.data[2] = 255;
ctx.putImageData(i,0,0);
console.log('after putImageData', ctx.getImageData(0,0,1,1).data);
console.log('passed imageData', i.data);
i.data[3] = 1;
ctx.putImageData(i,0,0);
console.log('after non transparent', ctx.getImageData(0,0,1,1).data);
This is because, for performances, browsers do pre-multiply the colors as greatly explained in pleup's answer, which, in this case, allows it to completely omit transparent pixels in drawing operations, and to only set it to transparent black for putImageData
.
Any way, even if you were able to set colors to non black transparent pixels, the export methods would probably reconvert it back to transparent black ones.
Canvas underlying buffer store pixel using premultiplied alpha.
When you draw rgba pixels, RGB part is multiplied by alpha value before being written to buffer.
eg: (in ARGB) 0x8080FF40 will be stored as 0x80408020
The canvas specification expect the result of getImageData to be un-premultiplied. It mean that the value read from the buffer is now divided by the alpha value, to get back the "original" RGB value.
First the convertion is lossy, because premultiplied value lose precision.
Secondely, the fully transparent pixel is the extreme case of "fully destructive loss of precision" because RGB value is store to buffer as zero, and cannot be retreived by un-premultipy it.