5

I'm looking for a way to find the average of an unspecified number of colors. I spent a lot of time looking for a way to do this. First I tried converting my colors to CMYK and averaging them, but that didn't provide the result I expected. Then I saw that in several different places, converting the colors to CIE L*a*b* space and then averaging is the preferred way of doing this. So I looked up how to convert RGB colors to LAB space and converted into Javascript the necessary algorithms to make this happen.

Now that I have my colors in LAB space, I thought it would be as simple as finding the average of my colors, so I wrote this function to do the trick:

color.mixRGB = function() {
    var cols = Array.prototype.slice.call(arguments),
        i = cols.length,
        lab = {l: 0, a: 0, b: 0};

    while(i--) {
        if (typeof cols[i].r === "undefined" && typeof cols[i].g === "undefined" && typeof cols[i] === "undefined") {
            console.log("Not enough parameters supplied for color " + i + ".");
            return;
        }

        if(cols[i].r === 0 && cols[i].g === 0 && cols[i].b === 0) {
            cols.splice(i, 1);
        } else {
            cols[i] = color.RGBtoLAB(cols[i]);
            lab.l += cols[i].l;
            lab.a += cols[i].a;
            lab.b += cols[i].b;            
        }
    }

    lab.l /= cols.length;
    lab.a /= cols.length;
    lab.b /= cols.length;

    return color.LABtoRGB(lab);
};

If I enter RGB (255, 0, 0) and RGB(0, 0, 255) into the function, I get RGB(202, -59, 136). This color is nothing near what Color Hexa says is the average of those two RGBs, which is RGB (128, 0, 128), a.k.a purple.

I went back over all my code, and so far I've managed to determine that the problem does not lie with any of my conversion algorithms by double- and triple-checking them against Color Hexa and EasyRGB. That means either a) the issue must lie with how I'm averaging the colors or b) I've been misinformed and I shouldn't attempt to mix colors in CIE L*a*b* space.

What exactly am I missing here? Using my current algorithm, why is averaging RGB (255, 0, 0) and RGB (0, 0, 255) not giving me the same results that Color Hexa (or even visual estimation) provides? (here's a fiddle of my problem)

4

2 回答 2

4

Lets say you have your colors defined by R0, G0, B0 and R1, G1, B1. Then blended/average color will have following RGB values:

RA = (R0+R1)/2;
GA = (G0+G1)/2;
BA = (B0+B1)/2;

Thats it, basically.

于 2013-07-06T21:35:11.473 回答
2

A null return means there has been an error.

color.mixRGB = function() {
   var cols = Array.prototype.slice.call(arguments),
       i = cols.length,
       rTotal = 0, gTotal = 0, rTotal = 0, colTotal = 0;

   while(i--) {
       // NOTE: you had && in your code, I think they should be ||
       if (typeof cols[i].r === "undefined" || typeof cols[i].g === "undefined" || typeof cols[i] === "undefined") {
            console.log("Not enough parameters supplied for color " + i + ".");
            return null;
        }
        colTotal++;
        rTotal += cols[i].r;
        gTotal += cols[i].g;
        bTotal += cols[i].b;
    }
    if(colTotal === 0) return null;

    // I am not sure what you are trying to return, just build it up with your rgb values
    return (new color(Math.round(rTotal / colTotal), Math.round(gTotal / colTotal), Math.round(bTotal / colTotal)));
};
于 2013-07-06T21:44:52.650 回答