content: -- Copyright (c) 2000 Galois Connections, Inc.
  -- All rights reserved.  This software is distributed as
  -- free software under the license in the file "LICENSE",
  -- which is included in the distribution.
  
  module Pixmap where
  
  import Data.Char
  import System.IO hiding (try)
  import Text.ParserCombinators.Parsec
  
  readPPM f
    = do  h <- openFile f ReadMode
          s <- hGetContents h
          case (parse parsePPM f s) of
            Left err -> error (show err)
            Right x  -> return x
  
  writePPM f ppm
    = do  h <- openFile f WriteMode
          let s = showPPM (length (head ppm)) (length ppm) ppm
          hPutStr h s
  
  -- parsing
  
  parsePPM
    = do  string "P6"
          whiteSpace
          width <- number
          whiteSpace
          height <- number
          whiteSpace
          colormax <- number
          whiteSpace
          cs <- getInput
          return (chop width (chopColors cs))
  
  chopColors [] = []
  chopColors (a:b:c:ds) = (ord a, ord b, ord c) : chopColors ds
  
  chop n [] = []
  chop n xs = h : chop n t
      where (h, t) = splitAt n xs
  
  number
    = do  ds <- many1 digit
          return (read ds :: Int)
  
  whiteSpace
    = skipMany (simpleSpace <|> oneLineComment <?> "")
      where simpleSpace = skipMany1 (oneOf " \t\n\r\v")
            oneLineComment =
                do  char '#'
                    skipMany (noneOf "\n\r\v")
                    return ()
  
  -- printing
  
  showPPM :: Int -> Int -> [[(Int,Int,Int)]] -> String
  showPPM wid ht pss
    = header ++ concat [[chr r, chr g, chr b] | ps <- pss, (r, g, b) <-ps]
    where
      header = "P6\n#Galois\n" ++ show wid ++ " " ++ show ht ++ "\n255\n"
  showPPM _ _ _ = error "incorrect length of bitmap string"
  