[Haskell] image writing library
Remi Turk
rturk at science.uva.nl
Thu Aug 5 08:44:58 EDT 2004
On Thu, Aug 05, 2004 at 02:07:02PM +0200, Ketil Malde wrote:
>
> Hi,
>
> I would like to write an (Array (Int,Int) Int) to a file in some kind
> of image format. I implemented (quick and very dirty) XBM output, but
> it would be nice to have some colors, and anyway, I can't seem to show
> the XBMs as grayscale.
>
> I've searched around a bit, but the only stuff I could find was
> defunct references to GIF writer, Jeroen Fokker's JPEG stuff (which
> may still work, but I don't want JPEG compression), and the PPM
> support in Andrew Cooke's Pancito.
>
> Ripping out the latter currently seems to be the best bet, not sure
> how closely tied it is to the rest of the code. So, before I start,
> does anybody know any other libraries or programs that could be used?
I once wrote a mini PPM read/write library for a
markov-like-chains-in-images fun project.
with the following basic API:
type Image = Matrix Color
withColor :: ((Int, Int, Int) -> (Int, Int, Int)) -> Color -> Color
-- The Int-argument gives the maximum number for a color value: usually 255
readPPM :: String -> (Int, Image)
showPPM :: Int -> Image -> String
Though it's quite horribly slow it does work:
Prelude PPM Matrix> (maxColor, img) <- readPPM `fmap` readFile "/tmp/foo.ppm"
Prelude PPM Matrix> let img' = amap (withColor $ \(r,g,b) -> (r,g,b)) img
Prelude PPM Matrix> writeFile "/tmp/bar.ppm" $ showPPM maxColor img'
bar.ppm == foo.ppm afterwards.
The Matrix module merely reexports some IArray instance.
(DiffUArray, in my program)
Happy hacking,
Remi
--
Nobody can be exactly like me. Even I have trouble doing it.
-------------- next part --------------
{-
Copyright (C) 2004 Remi Turk <rturk at science.uva.nl>
-}
module Matrix (
Matrix,
Location,
module Array
) where
-- DiffArrays are MUCH faster (in this case, usually)
--import Array
import Data.Array.Diff as Array
--import Data.Array.Unboxed as Array
type Location = (Int, Int)
type Matrix a = DiffUArray Location a
-------------- next part --------------
{-
Copyright (C) 2004 Remi Turk <rturk at science.uva.nl>
-}
module PPM (
Color,
Image,
readPPM,
showPPM,
withColor,
fromColor,
toColor
) where
import Char
import Text.ParserCombinators.Parsec
import Data.Bits
import Matrix
--type Color = (Int, Int, Int)
type Color = Int
type Image = Matrix Color
withColor :: ((Int, Int, Int) -> (Int, Int, Int)) -> Color -> Color
withColor f = toColor . f . fromColor
toColor :: (Int, Int, Int) -> Color
fromColor :: Color -> (Int, Int, Int)
{-
toColor = id
fromColor = id
-}
toColor (r,g,b) = (r `shiftL` 16) .|. (g `shiftL` 8) .|. b
fromColor col = (col `shiftR` 16, (col `shiftR` 8) .&. 0xFF, col .&. 0xFF)
skip parser = parser >> return ()
magicNo = string "P6" >> return () <?> "magicNo"
comment = char '#' >> skipMany (noneOf "\n") >> skip newline <?> "comment"
whitespace = skipMany1 (satisfy isSpace) <?> "whitespace"
number = many1 (satisfy isDigit) <?> "number"
separator = many1 (whitespace <|> comment)
readPPM :: String -> (Int, Image)
readPPM s = case parse parser "readImage" s of
Left err -> error (show err)
Right image -> image
where
parser :: GenParser Char st (Int, Image)
parser = do
magicNo;
separator
width <- read `fmap` number; separator
height <- read `fmap` number; separator
maxColor <- read `fmap` number; newline
pixels <- many pixel
let
bounds = ((1, 1), (width, height))
locs = [(x,y) | y <- [1..height], x <- [1..width]]
return (maxColor, array bounds (zip locs pixels))
pixel = do
r <- anyChar
g <- anyChar
b <- anyChar
return $ toColor (ord r, ord g, ord b)
showPPM :: Int -> Image -> String
showPPM maxColor image
= showString
(unlines ["P6", show w, show h, show maxColor])
$ map chr $ concatMap (f . fromColor)
$ map (image!) locs
where
f (r,g,b) = [r,g,b]
(_,(w,h)) = bounds image
locs = [(x,y) | y <- [1..h], x <- [1..w]]
More information about the Haskell
mailing list