Gray scale conversion

RGB image

Color digital images are made of pixels, themselves made of combinations of primary colors.

An RGB image has three channels: red, green, and blue that are the three primary colors that match with the color receptors in the human eye.

RGB images are used in computer displays and commonly in digital and electronic video devices.

A channel in this context is the grayscale image made of just one of these primary colors. So an RGB image has three channels (red, green, blue) and each of them is associated with its corresponding luminance, represented by a grayscale image.

The luminance is the luminous intensity of a source of light in a given direction, divided by the apparent surface of this source in this same direction.

Such a decomposition of the image in channels is illustrated by the image below:

Color to grayscale conversion

In Yuv space, Y represents the component of luminance and u v the components of chrominance.

Mainly because of the sensitivity of the sensors of the retina, the sensitivity of the human eye is not the same one on the whole of the spectrum of colors, and so the component of brightness is a weighted average by the relative human sensitivity of the primary colors.

For digital video devices, a commonly used formula is the one below:

Y = 0.3*R + 0.59*G + 0.11*B

The Y value is scaled in range 0 to 255 and stored in three channels of each pixel to produce the grayscale image:

This is the formula I use in my pno code and all computations are made using 32 bit fixed point operations (20:12). as shown below:


HB++ code

Private  Rc As Long       '0.30, format 20:12, 32 bits 
Private  Gc As Long       '0.59, format 20:12, 32 bits 

Private  Bc As Long       '0.11, format 20:12, 32 bits 
'Coefficients for luminance computation 
'fixed point format 20:12 
'fixed point = 12  <=> 2^12 = 4096 

Rc = SwapLong(Clng(4096*0.3)) 
Gc = SwapLong(Clng(4096*0.59)) 

Bc = SwapLong(Clng(4096*0.11)) 


C code

#define FixedPoint  12   // We use 20:12 fixed point computation
//Get source color
RGB = (((long)(Psource[is]) & 0xFF)<< 8)|(Psource[is+1] & 0xFF);
R = (RGB >> 8) & 0x00F8;
G = (RGB >> 3) & 0x00FC;
B = (RGB << 3) & 0x00F8;

// Gray = 0.3R + 0.59G + 0.11B
Gray  = (R * CtG->Rc)>> FixedPoint;
Gray += (G * CtG->Gc)>> FixedPoint;
Gray += (B * CtG->Bc)>> FixedPoint;
if (Gray>255) Gray=255;

//Set source color - 65536 colors
Psource[is] = (R<<3)|(G>>3);
Psource[is+1]= (G<<5)|(B);