Formulas for Calculating Greyscale

There are many

A

colour on screen – most computer screens – is produced from dots of red, green and blue light in different brightnesses. This will vary from monitor to monitor depending on which red, which green and which blue, and how relatively bright each of those inputs is in order to create any given hue. Some software allows the colourspace to be defined, therefore a given combination of brightness levels of the red, green and blue light may not always look the same on a single monitor, as it may have been adjusted for the colourspace.
Among it all, we need a not-too-complicated formula for converting a colour image to greyscale, especially to establish the relative brightness of each pixel or area. I have standardised on the following choices:

EXPLANATION

The RIGHTMOST two: Lightness and Average, are a single formula as explained below. For the CENTRAL block: sRGB, YIQ and CIE XYZ; the Red, Green and Blue (R G B) values (or levels of brightness) are multiplied by a factor. Then what happens depends on what is selected on the left-side option.

gamma: the R, G and B values are run through the gamma formula as shown below. Sometimes called the gamma-decompress, weighted sum then gamma-recompress method.

squared: each R, G and B value is squared (i.e. raised to the power of 2), then multiplied by its factor, the three values are added together, and the square root taken of the result. This gives an outcome that is closer to the gamma calculation (for the same mulitplication factors) than simple linear, so is a none-too-bad quick and simple option (see Greyscale Comparisons).

linear: each R, G and B value is multiplied by its factor, the three values are added together to get the greyscale result. This is a linear result, so takes no account of the difference in perception between darker and lighter brightnesses.

gamma exponent: if blank, this is 2.4, but could be modified to see the effects. It applies only if gamma is selected.

sRGB: factors R: 0.2235, G: 0.7154, B: 0.0611.

YIQ: factors R: 0.299, G: 0.587, B: 0.114.

CIE XYZ: factors R: 0.2125, G: 0.7154, B: 0.0721.

note: normally only the sRGB factors would be run through a gamma calculation, but there’s no harm in seeing the effects of other factors doing so too.

note: the YIQ factors applied linearly are those recommended by the WWW consortium (W3C) for determining colour contrast of text on web pages, see W3C Working Draft Checkpoint 2.1. Why they did so is a mystery as it is among the least satisfactory of the options for that particular job. See Text Readability in Colour.

Lightness: this is a simple linear formula made by adding the highest of the red, green and blue brightness levels to the lowest, and dividing the result by 2.

Average: a simple linear formula made by adding the red, green and blue brightness levels together and dividing the result by 3.

NOTE

All of these options ‘work’. Each will each produce a brightness level between 0 and 255, that can be used to make a greyscale by setting each of the red, green and blue values to that brightness level. On a photograph converted to greyscale, each option will produce a result that looks like greyscale. But for many colours each will produce a different brightness level, which may be significant depending on what the results are being used for.FORMULAS

Gamma

The gamma formula uses a classic linear to sRGB and sRGB to linear conversion. Mathematically that can be seen on the page A close look at the sRGB formula and in structural code on Optimizing conversion between sRGB and linear.

Gamma function in Javascript:

/* Inverse of sRGB "gamma" function. ********************** */

function inv_gam_sRGB( ic) {

var c = ic/255.0;

return c <= 0.04045 ? c/12.92 : Math.pow(((c+0.055)/(1.055)),2.4);
>

}

/* sRGB "gamma" function ******************************** */

function gam_sRGB(vi) {

var v=vi<=0.0031308 ? vi * 12.92 : 1.055*Math.pow(vi,1.0/2.4)-0.055
>

return (v*255);

}

/* GRAY VALUE ("brightness") *************************** */

function gamma_grey(r, g, b, rY, gY, bY) {

return gam_sRGB( rY*inv_gam_sRGB(r) + gY*inv_gam_sRGB(g) + bY*inv_gam_sRGB(b) );

}

You get a brightness (i.e. greyscale) value by calling:

brightness_value = gamma_grey(R, G, B, red factor (e.g. 0.2235 for classic sRGB), green factor (e.g. 0.7154), blue factor (e.g. 0.0611);

You’ll find that gives you a brightness value that is equivalent to Photoshop’s greyscale conversion (well I do).

Values 0-255 calculated as sRGB give a curve, which is said to be very useful for adjusting colours on photographs, but it is a curve that it inverse to what we need when comparing two brightnesses. The sRGB curve with an exponent of 2.4 looks like this:

With this curve the brightnesses get less the higher the colour value, not more, so we need the inverse of this:

That is the chart for 0-255 through the *inv_gam_sRGB* formula.

Graphic Example