Many image processing algorithms are defined for grayscale (or else monochromatic) images.



Task

Extend the data storage type defined on this page to support grayscale images.

Define two operations, one to convert a color image to a grayscale image and one for the backward conversion.

To get luminance of a color use the formula recommended by CIE:

 L  =  0.2126 × R   +   0.7152 × G   +   0.0722 × B 

When using floating-point arithmetic make sure that rounding errors would not cause run-time problems or else distorted results when calculated luminance is stored as an unsigned integer.




\ grayscale bitmap (without word-alignment for scan lines)
 
\ bdim, bwidth, bdata all work with graymaps
 
: graymap ( w h -- gmp )
  2dup * bdata allocate throw
  dup >r 2! r> ;
 
: gxy ( x y gmp -- addr )
  dup bwidth rot * rot + swap bdata + ;
 
: g@ ( x y gmp -- c ) gxy c@ ;
: g! ( c x y bmp -- ) gxy c! ;
 
: gfill ( c gmp -- )
  dup bdata swap bdim * rot fill ;
 
: gshow ( gmp -- )
  dup bdim
  0 do cr
    dup 0 do
      over i j rot g@ if [char] * emit else space then
    loop
  loop
  2drop ;
 
\ RGB <-> Grayscale
: lum>rgb ( 0..255 -- pixel )
   dup 8 lshift or
   dup 8 lshift or ;
 
: pixel>rgb ( pixel -- r g b )
  256 /mod 256 /mod ;
: rgb>lum ( pixel -- 0..255 )
  pixel>rgb
   722 *   swap
  7152 * + swap
  2126 * + 10000 / ;
 
: bitmap>graymap ( bmp -- gmp )
  dup bdim graymap
  dup bdim nip 0 do
    dup bwidth 0 do
      over i j rot b@ rgb>lum
      over i j rot g!
    loop
  loop nip ;
 
: graymap>bitmap ( gmp -- bmp )
  dup bdim bitmap
  dup bdim nip 0 do
    dup bwidth 0 do
      over i j rot g@ lum>rgb
      over i j rot b!
    loop
  loop nip ;