Client-side color replacement on an image

November 16, 2012

This function can be used to perform client-side color replacement on an image. Since it copies image data to a hidden canvas, the image MUST be from the same domain due to same-domain policy.

It expects 3 parameters, <img> , colFrom and colTo. Colors must be specified as an {r:0,g:0,b:0} object

function replaceImageColor(obj,colFrom,colTo) {
    // a separate img tag is created to calculate dimensions
    // it is also used to make sure image data is loaded 
    // before using context.drawImage
    var img = document.createElement("img");
    img.onload = function() { 
        var canvas = document.createElement("canvas");
        canvas.width = this.offsetWidth;
        canvas.height = this.offsetHeight;

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

        // image is no longer required 
        this.parentNode.removeChild(this);

        // do color replacement
        var imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
        var data = imageData.data;

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

            if((r == colFrom.r) &&
               (g == colFrom.g) &&
               (b == colFrom.b)) {

                data[x] = colTo.r;
                data[x+1] = colTo.g;
                data[x+2] = colTo.b;
            } 
        }

        ctx.putImageData(imageData,0,0);
        obj.src = canvas.toDataURL();

        // canvas is no longer required
        canvas = null;
    }

    img.src = obj.src;
    img.style.visibility = "hidden";
    // image needs to be appended to body 
    // for retrieval of offsetWidth / offsetHeight
    document.body.appendChild(img);
}

Usage

var img = document.getElementById('myImage');
replaceImageColor(img,
{ // from color
    r: 220,
    g: 160,
    b: 50
},
{ // to color
    r: 50,
    g: 120,
    b: 180
});

Working Example

(hover over the icons)

Partially based on my answer on Stack Overflow here: http://stackoverflow.com/a/13419444/149636