简体   繁体   中英

HTML5 Canvas: Change Image Color

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.

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 contains three images for capsules:

  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)

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

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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM