Images copyright © 1998, Glenn Randers-Pehrson. Permission is granted to reproduce and use the images and included Fortran program for any purpose.
The files mixrgb.png, mix045.png, and mix100.png demonstrate conversion of a color PNG to grayscale.
mixrgb.png is the source, which contains 216 color patches (the so-called "browser safe" palette) against a gray background. It has a gamma of 0.45455, or 1/2.2, as do the two grayscale images.
There are six blocks, each containing a 6 by 6 matrix of patches, with increasing amounts of red from left to right and increasing amounts of green from top to bottom. Each 6 by 6 group has an increasing amount of blue. Pure black is at the top left corner and pure white is at the lower left corner of the entire assembly. The other saturated colors appear at the remaining three corners of the upper left group and remaining three corners of the lower right group.
Y = 0.212671 * R + 0.715160 * G + 0.072169 * B (1)We approximate this with
Y = 0.211 * R + 0.715 * G + 0.074 * B (2)which can be expressed with integers as
Y = (54 * R + 183 * G + 19 * B)/256 (3)As recommended in the ColorFAQ, the mixing was done in a linear colorspace. The 8-bit-per-channel RGB colors were converted to the linear space by normalizing to 1.0, raising to the power 2.2, and 255. Then Y was computed to get the luminance. Grayscale pixels were determined by normalizing the Y value to 1.0, raising it to the power 1/2.2, and multiplying by 255. Conversion to and from the linear colorspace was actually done with a 16-bit lookup table, which produces the same result (after reducing to 8 bits) as performing equation (3) in 32-bit floating point arithmetic. In fact, 14-bit tables could have been used with the same result. In order to use the 16-bit tables, the 8-bit samples were multiplied by 256 and the low bytes filled with 0x80.
There is a little strip of colored or grayscale pixels in the top left corner of each image for easy determination of the resulting palette after the various conversions. You can use ImageMagick's
"convert -compress none mix100.png mix100.pgm"and then use a text editor or text viewer to examine the first 216 pixels.
The original color image was produced with the following Fortran program, which produced a NetPBM PGM file that was subsequently converted to PNG with ImageMagick's "convert". Conversion to grayscale, and final compression of the color image, were done with a modified version of "pngcrush" and a test version of libpng-1.0.2a.
program make_216_pgm c (c) Glenn Randers-Pehrson, July 1998 implicit integer (a-z) write(*,'(a2)')'P3' write(*,*)'600 400 255' do n=0,1 c top border if(n .eq. 0) then npix = 600 - 216 do green = 0,255,51 do blue = 0,255,51 do red = 0,255,51 write(*,'(3i4)') red, green, blue enddo enddo enddo else npix = 600 endif do k=1,8 do i=1,npix write(*,*)' 128 128 128' enddo npix=600 enddo do green = 0,255,51 do k=1,24 do blue = n*3*51, (3*n+2)*51, 51 do i = 1, 8 write(*,*) ' 128 128 128' enddo do red = 0,255,51 do i = 1, 24 write(*,'(3i4)') red, green, blue enddo do i = 1, 8 write(*,*) ' 128 128 128' enddo enddo enddo enddo c bottom border do i=1,4800 write(*,*)' 128 128 128' enddo enddo enddo end