packages feed

Codec-Image-DevIL (empty) → 0.1

raw patch · 3 files changed

+194/−0 lines, 3 filesdep +arraydep +basesetup-changed

Dependencies added: array, base

Files

+ Codec-Image-DevIL.cabal view
@@ -0,0 +1,25 @@+Name: Codec-Image-DevIL+Description:+    Provides a very simple interface to the DevIL image library.+    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+Stability: experimental+Synopsis: An FFI interface to the DevIL library+License: BSD3+Category: Codecs+Author: Luke Palmer+Maintainer: lrpalmer@gmail.com+Build-Type: Simple+Cabal-Version: >= 1.2+Library+    Build-Depends: base, array+    Exposed-Modules: Codec.Image.DevIL+    Extensions: ForeignFunctionInterface, CPP+    Build-Tools: hsc2hs+    Extra-Libraries: IL+    if os(windows)+        CPP-Options: -DCALLTYPE=stdcall+    else+        CPP-Options: -DCALLTYPE=ccall
+ Codec/Image/DevIL.hsc view
@@ -0,0 +1,167 @@+module Codec.Image.DevIL+    (ilInit+    ,readImage,writeImage+    ,Word8+    )+where++import Data.Int+import Data.Word++import Foreign hiding (newArray)+import Foreign.C++import Data.Array.Storable+import Data.Array.Unboxed+import Control.Applicative+import Control.Monad++import System.IO.Unsafe (unsafeInterleaveIO)++#include "IL/il.h"+++type ILuint    = #type ILuint+type ILsizei   = #type ILsizei+type ILboolean = #type ILboolean+type ILenum    = #type ILenum+type ILint     = #type ILint+type ILubyte   = #type ILubyte++newtype ImageName = ImageName { fromImageName :: ILuint }+++foreign import CALLTYPE "ilInit" ilInitC :: IO ()+foreign import CALLTYPE "ilOriginFunc" ilOriginFuncC :: ILenum -> IO ILboolean+foreign import CALLTYPE "ilEnable" ilEnableC :: ILenum -> IO ILboolean++ilInit :: IO ()+ilInit = do+    ilInitC+    ilOriginFuncC (#const IL_ORIGIN_LOWER_LEFT)+    ilEnableC (#const IL_ORIGIN_SET)+    return ()++readImage :: FilePath -> IO (UArray (Int,Int,Int) Word8)+readImage x =+  do [inname] <- ilGenImages 1+     ilBindImage inname+     ilLoadImage x+     a <- toArrayRGBA+     ilDeleteImages [inname]+     return a++writeImage :: FilePath -> UArray (Int,Int,Int) Word8 -> IO ()+writeImage f a =+  do [outname] <- ilGenImages 1+     ilBindImage outname+     fromArrayRGBA a+     ilSaveImage f+     ilDeleteImages [outname]++foreign import CALLTYPE "ilGenImages" ilGenImagesC+  :: ILsizei -> Ptr ILuint -> IO ()+++ilGenImages :: Int -> IO [ImageName]+ilGenImages num = do+    ar <- newArray (0, num-1) 0+    withStorableArray ar $ \p -> do+        ilGenImagesC (fromIntegral num) p+    map ImageName <$> getElems ar+++foreign import CALLTYPE "ilBindImage" ilBindImageC :: ILuint -> IO ()++ilBindImage :: ImageName -> IO ()+ilBindImage (ImageName name) = ilBindImageC name+++foreign import CALLTYPE "ilDeleteImages" ilDeleteImagesC+    :: ILsizei -> Ptr ILuint -> IO ()++ilDeleteImages :: [ImageName] -> IO ()+ilDeleteImages names = do+    ar <- newListArray (0, length names-1) (fromImageName <$> names)+    withStorableArray ar $ \p -> do+        ilDeleteImagesC (fromIntegral $ length names) p+++foreign import CALLTYPE "ilLoadImage" ilLoadImageC :: CString -> IO ILboolean++ilLoadImage :: FilePath -> IO Bool+ilLoadImage file = do+    (0 /=) <$> withCString file ilLoadImageC+++foreign import CALLTYPE "ilSaveImage" ilSaveImageC :: CString -> IO ILboolean++ilSaveImage :: FilePath -> IO Bool+ilSaveImage file = do+    (0 /=) <$> withCString file ilSaveImageC+++foreign import CALLTYPE "ilConvertImage" ilConvertImageC+    :: ILenum -> ILenum -> IO Bool++foreign import CALLTYPE "ilGetInteger" ilGetIntegerC+    :: ILenum -> IO ILint++foreign import CALLTYPE "ilCopyPixels" ilCopyPixelsC+    :: ILuint -> ILuint -> ILuint   -- x y z+    -> ILuint -> ILuint -> ILuint   -- w h depth+    -> ILenum -> ILenum             -- format type+    -> Ptr ()                       -- data (copy into this pointer)+    -> IO ()++foreign import CALLTYPE "ilSetPixels" ilSetPixelsC+    :: ILuint -> ILuint -> ILuint   -- x y z+    -> ILuint -> ILuint -> ILuint   -- w h depth+    -> ILenum -> ILenum             -- format type+    -> Ptr ()                       -- data (copy from this pointer)+    -> IO ()++foreign import CALLTYPE "ilTexImage" ilTexImageC+    :: ILuint -> ILuint -> ILuint   -- w h depth+    -> ILubyte -> ILenum -> ILenum  -- numberOfChannels format type+    -> Ptr ()                       -- data (copy from this pointer)+    -> IO Bool++il_RGBA = (#const IL_RGBA) :: ILenum+il_UNSIGNED_BYTE = (#const IL_UNSIGNED_BYTE) :: ILenum+il_IMAGE_HEIGHT = (#const IL_IMAGE_HEIGHT) :: ILenum+il_IMAGE_WIDTH  = (#const IL_IMAGE_WIDTH)  :: ILenum++-- 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))+    ar <- newArray_ bounds+    withStorableArray ar $ \p -> do+        ilCopyPixelsC 0 0 0 +                      (fromIntegral width) (fromIntegral height) 1 +                      il_RGBA il_UNSIGNED_BYTE +                      (castPtr p)+    listArray bounds <$> lazyElems ar++lazyElems ar = do+    ixs <- range <$> getBounds ar+    go ixs+  where+    go [] = return []+    go (ix:ixs) = unsafeInterleaveIO $ liftM2 (:) (readArray ar ix) (go ixs)++-- same as toArrayRGBA+fromArrayRGBA :: UArray (Int,Int,Int) Word8 -> IO ()+fromArrayRGBA dat = do+    let ((0,0,0), (maxx,maxy,3)) = bounds dat+    ar <- unsafeThaw dat+    withStorableArray ar $ \p -> do+        ilTexImageC (fromIntegral maxx+1) (fromIntegral maxy+1) 1+                    4 il_RGBA il_UNSIGNED_BYTE+                    (castPtr p)+    return ()++-- vim: ft=haskell :
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain