在Canvas中更改彩色图像

10

我想在画布中更改图像的颜色。

这是该图像:

enter image description here

您可以看到图像是透明的,我尝试使用PutImgData,但我的透明部分正在改变颜色。有没有办法仅更改汽车和货币的颜色? 我使用了以下代码:

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    image = document.getElementById("testImage");
canvas.height = canvas.width = 100;
ctx.fillStyle = 'red';
ctx.fillRect(10,10,20,10);
ctx.drawImage(image,0,0);

var imgd = ctx.getImageData(0, 0, 45, 45),
    pix = imgd.data;

for (var i = 0, n = pix.length; i <n; i += 4) {
    if(pix[i+3]==0)
  {continue;}
    pix.length[i]=r|pix.length[i];
  pix.length[i+1]=g|pix.length[i+1];
  pix.length[i+2]=b|pix.length[i+2];
   pix[i + 3] = 255;
}

ctx.putImageData(imgd, 0, 0);
1个回答

36

要手动混合颜色,您需要应用不同的公式来混合前景(新颜色)和背景(图像),以保留抗锯齿像素(顺便说一下:问题中包含的图像实际上不是透明的,但我猜您只是试图使用实心棋盘背景来说明透明度?)。

我建议采用不同的方法,这种方法是CORS安全且更快(也更简单) -

有几种方法可以做到这一点:一种是先绘制所需颜色,然后将合成模式设置为destination-in,然后再绘制图像;或者先绘制图像,将合成模式设置为source-in,然后再绘制颜色。

以下示例使用第一种方法将以下图像着色为蓝色:

image

var img = new Image; img.onload = draw; img.src = "//i.stack.imgur.com/cZ0gC.png";
var ctx = c.getContext("2d");

function draw() {
  // draw color
  ctx.fillStyle = "#09f";
  ctx.fillRect(0, 0, c.width, c.height);
  
  // set composite mode
  ctx.globalCompositeOperation = "destination-in";
  
  // draw image
  ctx.drawImage(this, 0, 0);
}
<canvas id=c></canvas>

使用第二种方法的示例:

var img = new Image; img.onload = draw; img.src = "//i.stack.imgur.com/cZ0gC.png";
var ctx = c.getContext("2d");

function draw() {
  // draw image
  ctx.drawImage(this, 0, 0);

  // set composite mode
  ctx.globalCompositeOperation = "source-in";

  // draw color
  ctx.fillStyle = "#09f";
  ctx.fillRect(0, 0, c.width, c.height);
}
<canvas id=c></canvas>

要将计算机模式重置回正常状态,请使用:

// reset comp. mode
ctx.globalCompositeOperation = "source-over";

getImageData() 类似,该技术的缺点是在执行此过程期间,您的画布只能包含该图像的内容。如果需要对图像进行着色并与其他内容混合,则可以使用离屏画布来处理,然后将该画布绘制回主画布。


如果我使用这个解决方案,会使透明颜色变成画布背景吗? - Dương Đỗ Đại
@DươngĐỗĐại 是的,画布后面的任何东西都会透过来(示例)。但是,如果您打算在画布内部填充背景,则需要执行其他步骤(示例)。 - user1693593
如果我有两个图像,一个是透明的,一个不在坐标(0,0)上。那么不透明的那个会在透明的那个图像后面,但透明的图像仍然会显示出背景颜色吗? - Dương Đỗ Đại
@DươngĐỗĐại 这不是原问题的一部分,我认为我已经为这个问题提供了所需的信息。请考虑接受答案并开一个新问题来表达新的意图。 - user1693593
谢谢你!!!! - Merlyn007
这是一个非常优雅和有用的解决方案! - Perry Monschau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接