diff --git a/Codec-Image-DevIL.cabal b/Codec-Image-DevIL.cabal
--- a/Codec-Image-DevIL.cabal
+++ b/Codec-Image-DevIL.cabal
@@ -4,7 +4,7 @@
     Provides functions readImage and writeImage, which can read
     and write many image formats from/to an RGBA array of values
     to work with.
-Version: 0.1
+Version: 0.2.0
 Stability: experimental
 Synopsis: An FFI interface to the DevIL library
 License: BSD3
@@ -14,7 +14,7 @@
 Build-Type: Simple
 Cabal-Version: >= 1.2
 Library
-    Build-Depends: base, array
+    Build-Depends: base<=4, array
     Exposed-Modules: Codec.Image.DevIL
     Extensions: ForeignFunctionInterface, CPP
     Build-Tools: hsc2hs
diff --git a/Codec/Image/DevIL.hsc b/Codec/Image/DevIL.hsc
--- a/Codec/Image/DevIL.hsc
+++ b/Codec/Image/DevIL.hsc
@@ -1,7 +1,7 @@
 module Codec.Image.DevIL
-    (ilInit
-    ,readImage,writeImage
-    ,Word8
+    ( ilInit
+    , readImage, writeImage, writeImageFromPtr
+    , Word8
     )
 where
 
@@ -31,6 +31,7 @@
 newtype ImageName = ImageName { fromImageName :: ILuint }
 
 
+-- | Initialize the library.
 foreign import CALLTYPE "ilInit" ilInitC :: IO ()
 foreign import CALLTYPE "ilOriginFunc" ilOriginFuncC :: ILenum -> IO ILboolean
 foreign import CALLTYPE "ilEnable" ilEnableC :: ILenum -> IO ILboolean
@@ -42,6 +43,7 @@
     ilEnableC (#const IL_ORIGIN_SET)
     return ()
 
+-- | Reads an image into an RGBA array.  Indices are (row,column,color-channel).
 readImage :: FilePath -> IO (UArray (Int,Int,Int) Word8)
 readImage x =
   do [inname] <- ilGenImages 1
@@ -51,6 +53,7 @@
      ilDeleteImages [inname]
      return a
 
+-- | Writes an RGBA array to a file.  Indices are (row,column,color-channel).
 writeImage :: FilePath -> UArray (Int,Int,Int) Word8 -> IO ()
 writeImage f a =
   do [outname] <- ilGenImages 1
@@ -135,13 +138,15 @@
 -- array indices are (x,y,channel) where channel: 0=Red, 1=Green, 2=Blue, 3=Alpha
 toArrayRGBA :: IO (UArray (Int,Int,Int) Word8)
 toArrayRGBA = do
-    width  <- ilGetIntegerC il_IMAGE_WIDTH
-    height <- ilGetIntegerC il_IMAGE_HEIGHT
-    let bounds = ((0,0,0), (fromIntegral width-1, fromIntegral height-1, 3))
+    -- Arrays are stored in row major, so we have to be fiddly with
+    -- our use of terminology.
+    columns <- ilGetIntegerC il_IMAGE_WIDTH
+    rows <- ilGetIntegerC il_IMAGE_HEIGHT
+    let bounds = ((0,0,0), (fromIntegral rows-1, fromIntegral columns-1, 3))
     ar <- newArray_ bounds
     withStorableArray ar $ \p -> do
         ilCopyPixelsC 0 0 0 
-                      (fromIntegral width) (fromIntegral height) 1 
+                      (fromIntegral columns) (fromIntegral rows) 1 
                       il_RGBA il_UNSIGNED_BYTE 
                       (castPtr p)
     listArray bounds <$> lazyElems ar
@@ -156,12 +161,30 @@
 -- same as toArrayRGBA
 fromArrayRGBA :: UArray (Int,Int,Int) Word8 -> IO ()
 fromArrayRGBA dat = do
-    let ((0,0,0), (maxx,maxy,3)) = bounds dat
+    let ((0,0,0), (maxrow,maxcol,3)) = bounds dat
     ar <- unsafeThaw dat
     withStorableArray ar $ \p -> do
-        ilTexImageC (fromIntegral maxx+1) (fromIntegral maxy+1) 1
+        ilTexImageC (fromIntegral maxcol+1) (fromIntegral maxrow+1) 1
                     4 il_RGBA il_UNSIGNED_BYTE
                     (castPtr p)
     return ()
+
+-- | Write an image from a pointer to raw RGBA data.  Careful!  
+-- The size tuple is (rows, columns), not (width, height).
+writeImageFromPtr :: FilePath -> (Int,Int) -> Ptr Word8 -> IO ()
+writeImageFromPtr f (rows,cols) p = do 
+    [outname] <- ilGenImages 1
+    ilBindImage outname
+    fromPtrRGBA (rows,cols) p
+    ilSaveImage f
+    ilDeleteImages [outname]
+
+fromPtrRGBA :: (Int,Int) -> Ptr Word8 -> IO ()
+fromPtrRGBA (rows,cols) p = do
+    ilTexImageC (fromIntegral cols) (fromIntegral rows) 1
+                4 il_RGBA il_UNSIGNED_BYTE
+                (castPtr p)
+    return ()
+
 
 -- vim: ft=haskell :
