putImageData alpha lost

3.2k Views Asked by At

i spend a lot of time to change color of png file with transparent background. I know how set color in getImageData(ctx,0,0,100,100).data; but when i want save new PNG image i've got white background...

i've got something like:

    var el = document.getElementById('before');
    var ctx = el.getContext('2d');
    var img=new Image();
img.src='src';
    ctx.drawImage(img,0,0,150,150);
    var imgData=ctx.getImageData(0, 0, 150, 150);
    for (var i=0;i<imgData.data.length;i+=4){
        imgData.data[i]=135;
        imgData.data[i+1]=222;
        imgData.data[i+2]=115;
    }
    var es = document.getElementById('after');
    var cts = es.getContext('2d');
    cts.putImageData(imgData,0,0);

EXAMPLE (i dont know why it was here putImageData)

in other project (ex. https://crosspop.in/croquis )it is posible, but i cant find where is solution.

Do You know how create canvas from modyfited getImageData with transparent background?

regards

2

There are 2 best solutions below

0
On BEST ANSWER

Your issue has nothing to do with alpha : while strange (you are changing every pixels of the image, even the transparent one) your algorithm works fine.
But you made the beginner's mistake forgot to watch the console : you'd have seen that the image's data cannot be accessed because of a Cross-Origin issue (CORS).
I modified your fiddle so that it uses a Base64 string for the image and it works fine :

http://jsfiddle.net/gamealchemist/6aZ7L/3/

var data = imgData.data;
for (var i = 0; i < data.length; i += 4) {
    if (data[i + 3]) {
        data[i] = 135;
        data[i + 1] = 222;
        data[i + 2] = 115;
    }
}

BUT in fact there's a much better way of re-coloring an image, that 1) avoids you to use imageData 2) is faster and 3) does not have CORS issue : use the globalCompositeOperation of the context, here you can for instance fill your canvas with green, then use a destination-in : each green pixel will be kept only if the copied image's pixel is not transparent.

http://jsfiddle.net/gamealchemist/6aZ7L/4/

function taintIt() {
    var es = document.getElementById('after');
    var cts = es.getContext('2d');
    cts.save();
    cts.fillStyle = 'rgb(135,222,115)';
    cts.fillRect(0, 0, 150, 150);
    cts.globalCompositeOperation = 'destination-in';
    cts.drawImage(img, 0, 0, 150, 150);
    cts.restore();
}

(By the way -admittedly a bit out of topic- i tried to draw with the pattern, it's quite fun : http://jsfiddle.net/gamealchemist/6aZ7L/6/embedded/result/ )

0
On

i add :

    cts.fillStyle = "red";
    cts.fillRect(0, 0, 120, 120);

juste before :

cts.putImageData(imgData, 0, 0);

in your exemple : http://jsfiddle.net/gamealchemist/6aZ7L/3/ putImageData ignore the alpha and still print a white backound ...