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:

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.