How can I get the color halfway between two colors?

Solution 1:

As Mr Lister just said, it is easy to automate the calculation with any programming language :

  1. Separate your two colors into their 3 color numbers for Red, Green, Blue : (r1,g1,b1) and (r2,g2,b2).
    • For example #15293E, #012549 become ("15", "29", "3E"), ("01", "25", "49")

  2. Convert each color string into an integer, specifying explicitly that you are parsing a hexadecimal-based representation of a number.
    • For example ("15", "29", "3E") becomes (21, 41, 62)

  3. Calculate the average (r',g',b') = ( (r1+r2)/2, (g1+g2)/2, (b1+b2)/2 ).
    • For example ( (21+1)/2, (41+37)/2, (62+73)/2) = (11, 39, 67)

  4. Convert them again to strings , specifying explicitly that you are generating two-digit hexadecimal representations (pad with a zero when necessary).
    • For example (11, 39, 67) -> ("0B", "27", "43")

  5. Concatenate a hash character followed by the 3 strings
    • For example ("0B", "27", "43") -> "#0B2743"

Edit : Implementation is not "very easy" as I initially stated. I took the time to write the code in several languages on Programming-Idioms .

Solution 2:

I use this website to do this task for me: ColorBlender.

The mid-color will be #0B2744.

Solution 3:

With LESS

If you use the latest LESS CSS preprocessor then you'll notice there is a function (mix()) that does this:

mix(#15293E, #012549, 50%)

Outputs: #0b2744.

Solution 4:

If you need to do this generically, and expect the middle colour to be visually accurate in more cases (i.e. the visual colour and tone of the mid point should "look right" to a human viewer), then as suggested above you may want to convert from RGB to HSV or HSL before calculating the mid point, and then convert back afterwards. This may differ significantly from averaging RGB values directly.

Here is some JavaScript code for the conversion to/from HSL that I found on a brief search, and that on a brief check appears to do the right thing:

github.com/mjackson/mjijackson.github.com/blob/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.txt

https://web.archive.org/web/20170919064926/https://github.com/mjackson/mjijackson.github.com/blob/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.txt

Just apply the rgbToHsl function to your two r,g,b colour vectors, average the two resulting vectors, and apply hslToRgb to that . . .

Solution 5:

Handy-Dandy Function

function padToTwo(numberString) {
    if (numberString.length < 2) {
        numberString = '0' + numberString;
    }
    return numberString;
}

function hexAverage() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function (previousValue, currentValue) {
        return currentValue
            .replace(/^#/, '')
            .match(/.{2}/g)
            .map(function (value, index) {
                return previousValue[index] + parseInt(value, 16);
            });
    }, [0, 0, 0])
    .reduce(function (previousValue, currentValue) {
        return previousValue + padToTwo(Math.floor(currentValue / args.length).toString(16));
    }, '#');
}

console.log(hexAverage('#111111', '#333333')); // => #222222
console.log(hexAverage('#111111', '#222222')); // => #191919
console.log(hexAverage('#111111', '#222222', '#333333')); // => #222222
console.log(hexAverage('#000483', '#004B39')); // => #00275e