9

I used many formulas to convert from RGB to grayscale, but didn't get good results compared to GIMP.

I already tested the following formulas:

gray = (int)(0.299 * r + 0.587 * g + 0.144 * b);

gray = (int)(0.299 * r + 0.587 * g + 0.114 * b);

gray = (int)(0.2126 * r + 0.7152 * g + 0.0722 * b);

gray = (int) (0.35*r + 0.50*g + 0.15*b);

gray = ((r * 61) + (g * 174) + (b * 21)) / 256;

gray = (int)((4897 * r + 9617 * g + 1868 * b) >> 14);

gray = r; if(g > gray) gray = g; if(b > gray) gray = b;
user2000255
  • 91
  • 1
  • 1
  • 3
  • I don't think this is really on-topic here, since it's a (subjective) graphics question rather than a programming question. That said, GIMP is open-source, so did you consider just looking at what it does? – Useless Mar 28 '13 at 15:50
  • Can you not just use `libgimp` to do it for you? – teppic Mar 28 '13 at 15:53
  • Since the eye have a maximum of sensitivity at green, it's seems like first or fourth formula right. – Eddy_Em Mar 28 '13 at 15:57

3 Answers3

15

In order to correctly convert RGB to grayscale, you should transform the gamma corrected R,G and B values into the linear color space, apply the conversion in the linear space, and then apply a gamma correction to the result.

The sRGB colorspace has a transform that only approximates a gamma curve. See the Wikipedia article for the particulars. Wikipedia also has a specific section on the subject of sRGB to grayscale.

Basically, to convert a sRGB component to linear format:

double sRGB_to_linear(double x) {
    if (x < 0.04045) return x/12.92;
    return pow((x+0.055)/1.055, 2.4);
}

Then, to convert sRGB to linear grayscale:

double R_linear = sRGB_to_linear(R/255.0);
double G_linear = sRGB_to_linear(G/255.0);
double B_linear = sRGB_to_linear(B/255.0);
double gray_linear = 0.2126 * R_linear + 0.7152 * G_linear + 0.0722 * B_linear;

Then, apply the sRGB gamma correction again:

double linear_to_sRGB(double y) {
    if (y <= 0.0031308) return 12.92 * y;
    return 1.055 * pow(y, 1/2.4) - 0.055;
}

I.e.

double gray_color = round(linear_to_sRGB(gray_linear) * 255);
digitalvision
  • 2,552
  • 19
  • 23
  • Could you give me a reference or equation? – user2000255 Mar 28 '13 at 15:57
  • I found the math equation from Wikipedia site below the Converting color to grayscale title. But i don't understand what it means. Thanks you. – user2000255 Mar 28 '13 at 16:11
  • 1
    Those coefficients (0.2126, 0.7152 and 0.0722) are originally from the linear-RGB -> XYZ space transformation matrix (the middle row of the matrix, which computes the Y). The resulting "intensity" value is actually the 'Y' value from the XYZ vector. https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation – R. Navega Jul 01 '17 at 12:58
2

There is a GIMP tutorial that describes several different ways that The GIMP can convert a color image to grayscale. One method is a weighted desaturation like you've tried already, and the article gives some weights that can be used to approximate The GIMP's conversion.

The GIMP's gegl library, which is the basis for all of its image operations, has a rather elaborate mechanism for converting color to greyscale, which takes into account the color of neighboring pixels and uses an iterative approach that seems to emulate the process of developing black and white photographs.

Martin Atkins
  • 62,420
  • 8
  • 120
  • 138
1

The gimp help for the desaturate tool states three available formulas corresponding to the options named "Lighness", "Luminosity" and "Average". Those would be:

Lightness: 0.5 * (max(R,G,B) + min(R,G,B))

Luminosity: (0.21 * R) + (0.72 * G) + (0.07 * B)

Average: (R + G + B)/3

vlz
  • 911
  • 1
  • 10
  • 18