Using the data storage type defined on this page for raster images, read an image from a PPM file (binary P6 prefered).
(Read the definition of PPM file on Wikipedia.)

Task: Use write ppm file solution and grayscale image solution with this one in order to convert a color image to grayscale one.

T Colour
   Byte r, g, b
 
   F (r, g, b)
      .r = r
      .g = g
      .b = b
 
   F ==(other)
      R .r == other.r & .g == other.g & .b == other.b
 
V black = Colour(0, 0, 0)
V white = Colour(255, 255, 255)
 
T Bitmap
   Int width, height
   Colour background
   [[Colour]] map
 
   F (width = 40, height = 40, background = white)
      assert(width > 0 & height > 0)
      .width = width
      .height = height
      .background = background
      .map = (0 .< height).map(h -> (0 .< @width).map(w -> @@background))
 
   F fillrect(x, y, width, height, colour = black)
      assert(x >= 0 & y >= 0 & width > 0 & height > 0)
      L(h) 0 .< height
         L(w) 0 .< width
            .map[y + h][x + w] = colour
 
   F set(x, y, colour = black)
      .map[y][x] = colour
 
   F get(x, y)
      R .map[y][x]
 
   F togreyscale()
      L(h) 0 .< .height
         L(w) 0 .< .width
            V (r, g, b) = .get(w, h)
            V l = Int(0.2126 * r + 0.7152 * g + 0.0722 * b)
            .set(w, h, Colour(l, l, l))
 
   F writeppmp3()
      V magic = "P3\n"
      V comment = "# generated from Bitmap.writeppmp3\n"
      V s = magic‘’comment‘’("#. #.\n#.\n".format(.width, .height, 255))
      L(h) (.height - 1 .< -1).step(-1)
         L(w) 0 .< .width
            V (r, g, b) = .get(w, h)
            s ‘’= ‘   #3 #3 #3’.format(r, g, b)
         s ‘’= "\n"
      R s
 
F tokenize(fstr)
   [String] tokens
   L(line) fstr.split("\n")
      I !line.starts_with(‘#’)
         L(t) line.split(‘ ’, group_delimiters' 1B)
            tokens.append(t)
   R tokens
 
F ppmp3tobitmap(fstr)
   V tokens = tokenize(fstr)
   V tokeni = -1
   F nexttoken()
      @tokeni++
      R @tokens[@tokeni]
   assert(‘P3’ == nexttoken(), ‘Wrong filetype’)
   V width  = Int(nexttoken())
   V height = Int(nexttoken())
   V maxval = Int(nexttoken())
   V bitmap = Bitmap(width, height, Colour(0, 0, 0))
   L(h) (height - 1 .< -1).step(-1)
      L(w) 0 .< width
         V r = Int(nexttoken())
         V g = Int(nexttoken())
         V b = Int(nexttoken())
         bitmap.set(w, h, Colour(r, g, b))
 
   R bitmap
 
V ppmtxt = |‘P3
             # feep.ppm
             4 4
             15
              0  0  0    0  0  0    0  0  0   15  0 15
              0  0  0    0 15  7    0  0  0    0  0  0
              0  0  0    0  0  0    0 15  7    0  0  0
             15  0 15    0  0  0    0  0  0    0  0  0
             ’
 
V bitmap = ppmp3tobitmap(ppmtxt)
print(‘Grey PPM:’)
bitmap.togreyscale()
print(bitmap.writeppmp3())