Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which haskell library will let me save a 2D array/vector to a png/jpg/gif... file?

I am playing around with haskell, starting with simple plotting programs to wet my feet. I need a library that will let me save a 2D array/vector to an image file. I don't want to write a list of colors. I want to use containers that are meant for array/vector like computations and can be (well, almost) automagically parallelized.

EDIT Ability to store color images is a must.

like image 891
rpg Avatar asked Mar 04 '11 08:03

rpg


2 Answers

I'd start with PGM library. This is a very simple uncompressed graymap format. Almost no additinal dependencies. You can convert PGM to other formats with ImageMagick or other tools.

PGM supports generic IArray interface, and should work with most of the standard Haskell arrays. You can easily parallelize array computations with Control.Parallel.Strategies.

PGM usage example:

ghci> :m + Data.Array Graphics.Pgm 
ghci> let a = accumArray (+) 0 ((0::Int,0::Int),(127,127)) [ ((i,i), 1.0::Double) | i <- [0..127] ]
ghci> arrayToFile "t.pgm" (fmap round a)

And this is the image:

t.pgm

Otherwise you may use Codec-Image-DevIL which can save unboxed arrays to many of the image formats. You'll need DevIL library too. And you'll need to convert all arrays to that particular type of them (UArray (Int, Int, Int) Word8).

Finally, if you want bleeding edge, you may consider repa parallel arrays and corresponding repa-io library, which can write them to BMP images. Unfortunately, today repa is not yet buildable with the new GHC 7.0.2 and doesn't give performance advantages on old GHC 6.12.

like image 92
sastanin Avatar answered Nov 15 '22 20:11

sastanin


A new combination is:

  • repa; for n-dimensional arrays, plus
  • repa-devil, for image loading in dozens of formats.

Repa is the only widely used array library that is automatically parallelized.

An example, from the repa tutorial, using readImage and writeImage, to read an image, rotate it, and write it back out, in whatever format:

import System.Environment
import Data.Word
import Data.Array.Repa hiding ((++))
import Data.Array.Repa.IO.DevIL

main = do
    [f] <- getArgs
    runIL $ do
        v   <- readImage f
        writeImage ("flip-"++f) (rot180 v)

rot180 :: Array DIM3 Word8 -> Array DIM3 Word8
rot180 g = backpermute e flop g
    where
        e@(Z :. x :. y :. _)   = extent g

        flop (Z :. i         :. j         :. k) =
             (Z :. x - i - 1 :. y - j - 1 :. k)
like image 44
Don Stewart Avatar answered Nov 15 '22 19:11

Don Stewart