0

我花了很多时间来改变具有透明背景的 png 文件的颜色。我知道如何在 getImageData(ctx,0,0,100,100).data 中设置颜色;但是当我想保存新的PNG图像时,我有白色背景...

我有类似的东西:

    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);

示例 (我不知道为什么它在这里 putImageData)

在其他项目中(例如https://crosspop.in/croquis)它是可能的,但我找不到解决方案。

你知道如何从修改后的 getImageData 中创建具有透明背景的画布吗?

问候

4

2 回答 2

1

您的问题与 alpha 无关:虽然很奇怪(您正在更改图像的每个像素,甚至是透明的像素),但您的算法工作正常。
但是您犯了初学者的错误,忘记观看控制台:您会看到由于跨域问题 ( CORS )而无法访问图像的数据。
我修改了您的小提琴,使其使用 Base64 字符串作为图像并且工作正常:

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;
    }
}

但实际上有一个更好的方法来重新着色图像,1)避免你使用 imageData 2)更快,3)没有 CORS 问题:使用上下文的globalCompositeOperation,例如,你可以在这里填充你的带绿色的画布,然后使用目标输入:仅当复制图像的像素不透明时,才会保留每个绿色像素。

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();
}

(顺便说一句 - 诚然有点偏离主题 - 我试图用这种模式来绘制,这很有趣:http: //jsfiddle.net/gamealchemist/6aZ7L/6/embedded/result/

于 2014-05-21T04:53:14.473 回答
-1

我加 :

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

就在之前:

cts.putImageData(imgData, 0, 0);

在您的示例中:http: //jsfiddle.net/gamealchemist/6aZ7L/3/ putImageData 忽略 alpha 并仍然打印白色背景...

于 2014-12-14T18:45:48.197 回答