javascript HTML5 Canvas:更改图像颜色

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24405245/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 02:43:27  来源:igfitidea点击:

HTML5 Canvas: Change Image Color

javascriptcsshtmlcanvashtml5-canvas

提问by Mohit Pandey

I have an image(in greyscale form) of which i want to change the color(user specific). Since its quite difficult to change the color of a greyscale image, i come with an approach.

我有一个图像(灰度形式),我想更改其颜色(特定于用户)。由于更改灰度图像的颜色非常困难,因此我提出了一种方法。

Image is divided into two parts.

图像分为两部分。

  1. One is the image with white color.
  2. Second, a semi transparent image with grayscale.
  1. 一种是白色的图像。
  2. 其次,具有灰度的半透明图像。

Now, i place both image on top of each other(with white image on below and greyscale image on top) such that when i change the color of white image, it will be visible to user.

现在,我将两个图像放在一起(下面是白色图像,顶部是灰度图像),这样当我更改白色图像的颜色时,用户就可以看到它。

Problem: This approach works for me, except one issue. When i color the white image, it will pixellete from corners.

问题:这种方法对我有用,除了一个问题。当我给白色图像上色时,它会从角落开始像素化。

JSFiddle: http://jsfiddle.net/pandey_mohit/BeSwL/

JSFiddle:http: //jsfiddle.net/pandey_mohit/BeSwL/

JSFiddle contains three images for capsules:

JSFiddle 包含三个胶囊图像:

  1. Top Capsule Part White Image (for coloring)
  2. Bottom Capsule Part White Image (for coloring)
  3. Semi Transparent Image for 3D effect (using grayscale)
  1. 顶部胶囊部分白色图像(用于着色)
  2. 底部胶囊部分白色图像(用于着色)
  3. 用于 3D 效果的半透明图像(使用灰度)

Select red, green or blue color to see the issue.

选择红色、绿色或蓝色以查看问题。

function hexToRgb(color) {
    var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
    color = color.replace(shorthandRegex, function(m, r, g, b) {
        return r + r + g + g + b + b;
    });

    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
    return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
    } : {
        r: 0,
        g: 0,
        b: 0
    };
}

function colorImage(imgId,hexaColor) {
    // create hidden canvas (using image dimensions)
    var imgElement = document.getElementById(imgId);

    var canvas = document.createElement("canvas");
    canvas.width = imgElement.width;
    canvas.height = imgElement.height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(imgElement,0,0);

    var imageData = ctx.getImageData(0,0,canvas.width,canvas.height);

    var data = imageData.data;

    // convert image to grayscale
    var rgbColor = hexToRgb(hexaColor);

    for(var p = 0, len = data.length; p < len; p+=4) {
        if(data[p+3] == 0)
           continue;
        data[p + 0] = rgbColor.r;
        data[p + 1] = rgbColor.g;
        data[p + 2] = rgbColor.b;
        data[p + 3] = 255;
    }
    ctx.putImageData(imageData, 0, 0);

    // replace image source with canvas data
    imgElement.src = canvas.toDataURL();
}

// changing color of capsule on select event
document.getElementById('sel_top').onchange = function(){
    colorImage('img_top', this.value);
}
document.getElementById('sel_bottom').onchange = function(){
    colorImage('img_bottom', this.value);
}

回答by Philipp

Your recoloring algorithm sets the 4th byte of each RGBA quartet to 255, which discards the alpha channel of the overlay and breaks the anti-aliasing around the edges of the image. Keeping the alpha channel of the original gives you better results:

您的重新着色算法将每个 RGBA 四重奏的第 4 个字节设置为 255,这将丢弃叠加层的 alpha 通道并破坏图像边缘周围的抗锯齿。保留原始的 alpha 通道会给你更好的结果:

for(var p = 0, len = data.length; p < len; p+=4) {
    data[p + 0] = rgbColor.r;
    data[p + 1] = rgbColor.g;
    data[p + 2] = rgbColor.b;
}

JSFiddle with the lines commented out

注释掉的行的 JSFiddle