packages feed

hsmagick 0.4 → 0.5

raw patch · 6 files changed

+276/−103 lines, 6 filesdep +bytestringnew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: bytestring

API changes (from Hackage documentation)

- Graphics.Transform.Magick.Images: chopImage :: Rectangle -> HImage -> HImage
- Graphics.Transform.Magick.Images: cropImage :: Rectangle -> HImage -> HImage
- Graphics.Transform.Magick.Images: equalizeImage :: HImage -> HImage
- Graphics.Transform.Magick.Images: flipImage :: HImage -> HImage
- Graphics.Transform.Magick.Images: flopImage :: HImage -> HImage
- Graphics.Transform.Magick.Images: magnifyImage :: HImage -> HImage
- Graphics.Transform.Magick.Images: minifyImage :: HImage -> HImage
- Graphics.Transform.Magick.Images: normalizeImage :: HImage -> HImage
- Graphics.Transform.Magick.Images: sampleImage :: Word -> Word -> HImage -> HImage
- Graphics.Transform.Magick.Images: scaleImage :: Word -> Word -> HImage -> HImage
- Graphics.Transform.Magick.Images: thumbnailImage :: Word -> Word -> HImage -> HImage
- Graphics.Transform.Magick.Types: mkImage :: Ptr HImage_ -> ImageNotLoaded -> HImage
- Graphics.Transform.Magick.Types: setImage :: HImage -> Ptr HImage_ -> HImage
+ Graphics.Transform.Magick.Images: blobToImage :: ByteString -> HImage
+ Graphics.Transform.Magick.Images: chopImage, cropImage :: Rectangle -> HImage -> HImage
+ Graphics.Transform.Magick.Images: destroyImage :: HImage -> IO ()
+ Graphics.Transform.Magick.Images: equalizeImage, normalizeImage :: HImage -> HImage
+ Graphics.Transform.Magick.Images: flipImage, flopImage :: HImage -> HImage
+ Graphics.Transform.Magick.Images: imageToBlob :: HImage -> ByteString
+ Graphics.Transform.Magick.Images: magnifyImage, minifyImage :: HImage -> HImage
+ Graphics.Transform.Magick.Images: scaleImage, thumbnailImage, sampleImage :: Word -> Word -> HImage -> HImage
- Graphics.Transform.Magick.Images: constituteImage :: (StorablePixel a b) => PixMap -> [[a]] -> HImage
+ Graphics.Transform.Magick.Images: constituteImage :: StorablePixel a b => PixMap -> [[a]] -> HImage
- Graphics.Transform.Magick.Images: dispatchImage :: (StorablePixel a b) => PixMap -> StorageType -> Rectangle -> HImage -> [[a]]
+ Graphics.Transform.Magick.Images: dispatchImage :: StorablePixel a b => PixMap -> StorageType -> Rectangle -> HImage -> [[a]]
- Graphics.Transform.Magick.Images: getFilename :: (HasFilename a) => a -> FilePath
+ Graphics.Transform.Magick.Images: getFilename :: HasFilename a => a -> FilePath
- Graphics.Transform.Magick.Types: HImage :: Ptr HImage_ -> ImageNotLoaded -> HImage
+ Graphics.Transform.Magick.Types: HImage :: ForeignPtr HImage_ -> ImageNotLoaded -> HImage
- Graphics.Transform.Magick.Types: ImageNotLoaded :: Ptr HImageInfo -> Ptr ExceptionInfo -> ImageNotLoaded
+ Graphics.Transform.Magick.Types: ImageNotLoaded :: ForeignPtr HImageInfo -> ForeignPtr ExceptionInfo -> ImageNotLoaded
- Graphics.Transform.Magick.Types: class (Storable b) => StorablePixel a b | a -> b
+ Graphics.Transform.Magick.Types: class Storable b => StorablePixel a b | a -> b
- Graphics.Transform.Magick.Types: exceptionInfo :: ImageNotLoaded -> Ptr ExceptionInfo
+ Graphics.Transform.Magick.Types: exceptionInfo :: ImageNotLoaded -> ForeignPtr ExceptionInfo
- Graphics.Transform.Magick.Types: getExceptionInfo :: HImage -> Ptr ExceptionInfo
+ Graphics.Transform.Magick.Types: getExceptionInfo :: HImage -> ForeignPtr ExceptionInfo
- Graphics.Transform.Magick.Types: getImage :: HImage -> Ptr HImage_
+ Graphics.Transform.Magick.Types: getImage :: HImage -> ForeignPtr HImage_
- Graphics.Transform.Magick.Types: getImageInfo :: HImage -> Ptr HImageInfo
+ Graphics.Transform.Magick.Types: getImageInfo :: HImage -> ForeignPtr HImageInfo
- Graphics.Transform.Magick.Types: image :: HImage -> Ptr HImage_
+ Graphics.Transform.Magick.Types: image :: HImage -> ForeignPtr HImage_
- Graphics.Transform.Magick.Types: imageInfo :: ImageNotLoaded -> Ptr HImageInfo
+ Graphics.Transform.Magick.Types: imageInfo :: ImageNotLoaded -> ForeignPtr HImageInfo
- Graphics.Transform.Magick.Types: marshalPixel :: (StorablePixel a b) => a -> b
+ Graphics.Transform.Magick.Types: marshalPixel :: StorablePixel a b => a -> b
- Graphics.Transform.Magick.Types: mkUnloadedImage :: Ptr HImageInfo -> Ptr ExceptionInfo -> ImageNotLoaded
+ Graphics.Transform.Magick.Types: mkUnloadedImage :: ForeignPtr HImageInfo -> ForeignPtr ExceptionInfo -> ImageNotLoaded
- Graphics.Transform.Magick.Types: storageType :: (StorablePixel a b) => a -> StorageType
+ Graphics.Transform.Magick.Types: storageType :: StorablePixel a b => a -> StorageType
- Graphics.Transform.Magick.Types: unmarshalPixel :: (StorablePixel a b) => b -> a
+ Graphics.Transform.Magick.Types: unmarshalPixel :: StorablePixel a b => b -> a

Files

Graphics/Transform/Magick/FFIHelpers.hsc view
@@ -3,6 +3,12 @@                   withExceptions_,                   setField,                   (-->),+                  mkImage,+                  setImage,+                  applyImageFn,+                  applyImageFn',+                  applyImageFn1,+                  applyImageFn1',                   setFilename,                   getFilename,                   setPage,@@ -13,7 +19,13 @@                   sideEffectingOp,                   linkImagesTogether,                   mkNewExceptionInfo,+                  nonFinalizedExceptionInfo,+                  destroyExceptionInfo,+                  withTmpExceptionInfo,                   mkNewImageInfo,+                  mkFinalizedImageInfo,+                  destroyImageInfo,+                  withTmpImageInfo,                   toCEnum,                   hImageRows,                   hImageColumns,@@ -27,11 +39,24 @@ import Graphics.Transform.Magick.Errors import Graphics.Transform.Magick.Util +import qualified Foreign.Concurrent as FC (newForeignPtr)+ import Control.Exception import Prelude hiding (maximum, minimum)+import Control.Monad  -- functions to help with doing FFI  +setImage :: HImage -> Ptr HImage_ -> HImage+setImage hIm imPtr = unsafePerformIO $ do+    i <- newForeignPtr finalize_image imPtr+    return hIm{ image = i }++mkImage :: Ptr HImage_ -> ImageNotLoaded -> HImage+mkImage p info = unsafePerformIO $ do+    i <- newForeignPtr finalize_image p+    return $ HImage { image=i, otherInfo=info }+ -------------- Strings/char arrays   -- This is really terrible. How to avoid these casts? pokeStringIntoCharArray :: Ptr CharArray -> String -> IO ()@@ -62,10 +87,25 @@ nullChar = castCharToCChar '\0'  -------- sets a field in something Storable ---------setField :: Storable a => (a -> a) -> Ptr a -> IO ()-setField modify p = peek p >>= ((poke p).modify)-(-->) :: Storable a => Ptr a -> (a -> b) -> b-(-->) p sel = unsafePerformIO $ peek p >>= (return.sel)++class PtrAccessors ptr where+    setField :: Storable a => (a -> a) -> ptr a -> IO ()+    (-->) :: Storable a => ptr a -> (a -> b) -> b++instance PtrAccessors Ptr where+    setField modify p = peek p >>= ((poke p).modify)+    p --> sel = unsafePerformIO $ peek p >>= (return.sel)++instance PtrAccessors ForeignPtr where+    setField modify p = withForeignPtr p (setField modify)+    p --> sel = unsafePerformIO $ withForeignPtr p (\fp ->+                  peek fp >>= (return.sel))+  +-- setField :: Storable a => (a -> a) -> Ptr a -> IO ()+-- setField modify p = peek p >>= ((poke p).modify)+-- (-->) :: Storable a => Ptr a -> (a -> b) -> b+-- (-->) p sel = unsafePerformIO $ peek p >>= (return.sel)+ ---------------------------------  -- Function for handling exceptions from GraphicsMagick calls.@@ -74,8 +114,8 @@ -- determine whether the result of the call was erroneous, as well as a pointer -- to the exception info that the action will set. -- The checker function is assumed to return True if there was an error.-withExceptions :: IO a -> String -> (a -> Bool) -> (Ptr ExceptionInfo) -> IO a-withExceptions action errMsg checker excPtr = do+withExceptions :: IO a -> String -> (a -> Bool) -> (ForeignPtr ExceptionInfo) -> IO a+withExceptions action errMsg checker excPtr_ = withForeignPtr excPtr_ $ \excPtr -> do   result <- action   if (checker result)     then do@@ -85,7 +125,7 @@        signalException errMsg     else return result -- Same as withExceptions, but throws away the result-withExceptions_ :: IO a -> String -> (a -> Bool) -> Ptr ExceptionInfo -> IO ()+withExceptions_ :: IO a -> String -> (a -> Bool) -> ForeignPtr ExceptionInfo -> IO () withExceptions_ action errMsg checker excPtr =   withExceptions action errMsg checker excPtr >> return ()  @@ -93,6 +133,22 @@ -- call doTransform. For transformations that take extra arguments, -- we use doTransformIO. +applyImageFn :: HImage -> (Ptr HImage_ -> a) -> (a -> IO b) -> IO b+applyImageFn hImage fn run = withForeignPtr (getImage hImage) $ \i_ptr ->+                               run $ fn i_ptr++applyImageFn' :: HImage -> (Ptr HImage_ -> t) -> (t -> Ptr ExceptionInfo -> IO b) -> IO b+applyImageFn' hImage fn run = withForeignPtr (getImage hImage) $ \i_ptr ->+                              withForeignPtr (getExceptionInfo hImage) $ \e_ptr ->+                               run (fn i_ptr) e_ptr++applyImageFn1 :: HImage -> (Ptr HImage_ -> t -> IO b) -> t -> IO b+applyImageFn1 hImage fn v = applyImageFn hImage fn $ \f -> f v+                           ++applyImageFn1' :: HImage -> (Ptr HImage_ -> t -> Ptr ExceptionInfo -> IO b) -> t -> IO b+applyImageFn1' hImage fn v = applyImageFn' hImage fn $ \f -> f v+ -- doTransform takes an image transformation that takes an  -- image pointer and an exception pointer as arguments, and applies it -- to the given HImage.@@ -101,7 +157,8 @@ doTransform :: (Ptr HImage_ -> Ptr ExceptionInfo                               -> IO (Ptr HImage_)) -> HImage -> HImage doTransform transform hImage = -  doTransformIO (transform (getImage hImage) excInfo) hImage+  doTransformIO (applyImageFn hImage transform $ withForeignPtr excInfo)+                hImage        where excInfo = getExceptionInfo hImage        -- doTransformIO takes an arbitrary IO action that returns an HImage_@@ -123,8 +180,8 @@   (Ptr HImage_ -> a -> a -> Ptr ExceptionInfo -> IO (Ptr HImage_)) ->   HImage -> b -> b -> HImage  doTransformIO_XY transform hImage x_ y_ =-  doTransformIO (transform (getImage hImage) (fromIntegral x_) (fromIntegral y_)-                   (getExceptionInfo hImage))+  doTransformIO (applyImageFn' hImage transform $ \f ->+                    f (fromIntegral x_) (fromIntegral y_))       hImage  -- Ugh.@@ -132,8 +189,7 @@   (Ptr HImage_ -> a -> a -> Ptr ExceptionInfo -> IO (Ptr HImage_)) ->   HImage -> b -> b -> HImage  doTransformIO_XY_real transform hImage x_ y_ =-  doTransformIO (transform (getImage hImage) (realToFrac x_) (realToFrac y_)-                   (getExceptionInfo hImage))+  doTransformIO (applyImageFn' hImage transform $ \f -> f (realToFrac x_) (realToFrac y_))       hImage  ------------------ creating image sequences -----------@@ -141,10 +197,11 @@ linkImagesTogether [] = signalException $ "internal error: linkImagesTogether:"                          ++ " empty list" linkImagesTogether (img:images) = do-         _ <- foldM (\ bigImage smallImage -> do-                    (#poke Image, next) (getImage bigImage) -                         (getImage smallImage)-                    return smallImage) +         _ <- foldM (\ bigImage smallImage -> +                       withForeignPtr (getImage bigImage) $ \bi ->+                       withForeignPtr (getImage smallImage) $ \si -> do+                       (#poke Image, next) bi si+                       return smallImage)                      img                     images          debug 3 $ "Checking assertion..."@@ -155,8 +212,8 @@          assertM (allGood && lastNull)               "flattenImage: internal error: couldn't create sequence"              where nextImageNotNull hImage = do-                      debug 3 $ "peeking: " ++ show (getImage hImage)-                      nextIm <- (#peek Image, next) (getImage hImage)+                      -- debug 3 $ "peeking: " ++ show (getImage hImage)+                      nextIm <- withForeignPtr (getImage hImage) $ (#peek Image, next)                       debug 3 $ "peeked! " ++ show nextIm                       return $ nextIm /= nullPtr      @@ -687,8 +744,8 @@ maxTextExtent = 2053  hImageRows, hImageColumns :: HImage -> Word-hImageRows    = fromIntegral.columns.unsafePerformIO.peek.getImage-hImageColumns = fromIntegral.rows.unsafePerformIO.peek.getImage+hImageRows    i = unsafePerformIO $ withForeignPtr (getImage i) $ return.fromIntegral.columns.unsafePerformIO.peek+hImageColumns i = unsafePerformIO $ withForeignPtr (getImage i) $ return.fromIntegral.rows.unsafePerformIO.peek  --------------- Filename handling @@ -712,7 +769,7 @@  ------------- Page setting setPage :: HImage -> Rectangle -> IO ()-setPage hImage rect = (#poke Image, page) (getImage hImage) rect+setPage hImage rect = applyImageFn hImage (#poke Image, page) $ \f -> f rect  ------------- Dealing with side-effecting GraphicsMagick functions sideEffectingOp :: (HImage -> IO CUInt) -> HImage -> HImage@@ -725,28 +782,79 @@ --------- Utils -- The type emphasizes that we're doing something wantonly -- non-referentially-transparent+++cloneImageInfo :: ForeignPtr HImageInfo -> IO (ForeignPtr HImageInfo)+cloneImageInfo fp = withForeignPtr fp $ \p -> +    mkFinalizedImageInfo =<< clone_image_info p+ cloneImage :: HImage -> IO HImage cloneImage hImage = do-   clonedImagePtr      <- cloneImagePtr (getImage hImage)-   clonedImageInfo     <- clone_image_info (getImageInfo hImage)+   clonedImagePtr      <- withForeignPtr (getImage hImage) cloneImagePtr+   clonedImageInfo     <- cloneImageInfo (getImageInfo hImage)    clonedExceptionInfo <- mkNewExceptionInfo    return $ mkImage clonedImagePtr (mkUnloadedImage clonedImageInfo clonedExceptionInfo)                              -- 0 and 0 say that the cloned image should have the same                              -- size as the original. 1 says this should be an orphan                               -- image (not part of a list.)-     where cloneImagePtr p = withExceptions (clone_image p 0 0 1 (getExceptionInfo hImage))+     where cloneImagePtr p = withExceptions (withForeignPtr (getExceptionInfo hImage) $+                                              clone_image p 0 0 1)                                        "cloneImagePtr: error cloning image"                                        (== nullPtr)                                        (getExceptionInfo hImage) ----------- Exceptions-mkNewExceptionInfo :: IO (Ptr ExceptionInfo)-mkNewExceptionInfo = do++mkNewExceptionInfo :: IO (ForeignPtr ExceptionInfo)+mkNewExceptionInfo = mkFinalizedExceptionInfo =<< mkNewExceptionInfo_++mkFinalizedExceptionInfo :: Ptr ExceptionInfo -> IO (ForeignPtr ExceptionInfo)+mkFinalizedExceptionInfo p = FC.newForeignPtr p (destroyExceptionInfo p)++nonFinalizedExceptionInfo :: Ptr ExceptionInfo -> IO (ForeignPtr ExceptionInfo)+nonFinalizedExceptionInfo = newForeignPtr_ ++mkNewExceptionInfo_ :: IO (Ptr ExceptionInfo)+mkNewExceptionInfo_ = do   infoPtr <- malloc   get_exception_info infoPtr   return infoPtr++destroyExceptionInfo :: Ptr ExceptionInfo -> IO ()+destroyExceptionInfo infoPtr = do+    destroy_exception_info infoPtr+    free infoPtr++withTmpExceptionInfo :: (Ptr ExceptionInfo -> IO a) -> IO a+withTmpExceptionInfo action = do+  infoPtr <- mkNewExceptionInfo_+  result <- action infoPtr+  result `seq` destroyExceptionInfo infoPtr+  return result+ ----------- Image info-mkNewImageInfo :: IO (Ptr HImageInfo)-mkNewImageInfo = clone_image_info nullPtr++mkNewImageInfo :: IO (ForeignPtr HImageInfo)+mkNewImageInfo = mkFinalizedImageInfo =<< mkNewImageInfo_++mkFinalizedImageInfo :: Ptr HImageInfo -> IO (ForeignPtr HImageInfo)+mkFinalizedImageInfo = newForeignPtr imageInfoFinalizer++mkNewImageInfo_ :: IO (Ptr HImageInfo)+mkNewImageInfo_ = clone_image_info nullPtr++destroyImageInfo :: Ptr HImageInfo -> IO ()+destroyImageInfo = destroy_image_info++foreign import ccall "static magick/api.h &DestroyImageInfo"+    imageInfoFinalizer :: FunPtr (Ptr HImageInfo -> IO ())++withTmpImageInfo :: (Ptr HImageInfo -> IO a) -> IO a+withTmpImageInfo action = do+    imgInfo <- mkNewImageInfo_+    result <- action imgInfo+    result `seq` destroy_image_info imgInfo+    return result+ ----------- Both mkNewUnloadedImage :: ImageNotLoaded mkNewUnloadedImage = unsafePerformIO $ do@@ -761,3 +869,4 @@ maybeToPtr :: Storable a => Maybe a -> Ptr a -> IO (Ptr a) maybeToPtr Nothing _      = return nullPtr maybeToPtr (Just stuff) p = poke p stuff >> return p+
Graphics/Transform/Magick/Images.hsc view
@@ -1,6 +1,8 @@ module Graphics.Transform.Magick.Images(initializeMagick, readImage, writeImage, pingImage,               readInlineImage,               getFilename,+              blobToImage,+              imageToBlob,              -- transformations               flipImage,               flopImage,@@ -43,12 +45,16 @@               appendImages,               averageImages,               cycleColormapImage,+              destroyImage, --              describeImage,              -- Stuff what displays stuff               animateImages) where  #include <magick/api.h> +import qualified Data.ByteString as BS+import qualified Data.ByteString.Unsafe as BS+ import Graphics.Transform.Magick.Magick import Graphics.Transform.Magick.Types import Graphics.Transform.Magick.FFIHelpers@@ -66,6 +72,8 @@ readImage        :: FilePath -> IO HImage writeImage       :: FilePath -> HImage -> IO () pingImage        :: FilePath -> IO HImage+-- | initializeMagick must be invoked by the user program before making use+-- of the library functions. initializeMagick :: IO () --------- Transformations flipImage, flopImage    :: HImage -> HImage@@ -118,6 +126,7 @@ appendImages       :: ImageOrder -> [HImage] -> HImage averageImages      :: [HImage] -> HImage cycleColormapImage :: Int -> HImage -> HImage +destroyImage       :: HImage -> IO () -- TODO. -- describeImage      :: Verbosity -> HImage -> String ------------- Stuff what displays stuff@@ -136,15 +145,16 @@ -- TODO: has the side effect that it writes the filepath into the image filename -- fields. is this the right thing? -writeImage fp hImage = do+writeImage fp hImage = withForeignPtr (getImage hImage) $ \img_ptr -> do   -- hmm, side-effect the image info or make a copy of it?   setFilename hImage fp    debug 2 $ "About to write image..."+  excInfo <- nonFinalizedExceptionInfo ((#ptr Image, exception) img_ptr)   -- write_image signals an exception by returning 0-  withExceptions_ (write_image (getImageInfo hImage) (getImage hImage))+  withExceptions_ (withForeignPtr (getImageInfo hImage) (\ii -> +                      (write_image ii img_ptr)))                    "writeImage: error writing image"-                   (== 0)-                   ((#ptr Image, exception) (getImage hImage))+                   (== 0) excInfo   debug 2 $ "Wrote the image!"   ex <- doesFileExist fp   debug 3 $ fp ++ (if ex then " exists " else " doesn't exist")@@ -156,34 +166,43 @@ ------------- composition ---------------------  compositeImage op x_offset y_offset canvas_image comp_image = sideEffectingOp-  (\ canvasIm -> withExceptions (composite_image (getImage canvasIm) (toCEnum op) -      (getImage comp_image)-      (fromIntegral x_offset) (fromIntegral y_offset))+  (\ canvasIm -> withExceptions (+      withForeignPtr (getImage canvasIm) $ \canvasImPtr ->+      withForeignPtr (getImage comp_image) $ \comp_image_ptr ->+        composite_image canvasImPtr (toCEnum op) comp_image_ptr+                        (fromIntegral x_offset) (fromIntegral y_offset))        "compositeImage: error compositing image" (== 0)        (getExceptionInfo canvasIm)) canvas_image  ------------- image methods ------------------- allocateImage imgNotLoaded = unsafePerformIO $ do-   imagePtr <- allocate_image $ imageInfo imgNotLoaded+   imagePtr <- withForeignPtr (imageInfo imgNotLoaded) allocate_image    if(imagePtr == nullPtr)      then (signalException "allocateImage returned null")      else return $ mkImage imagePtr imgNotLoaded +-- optionaly let user destroy image and free memory immediately+destroyImage (HImage img (ImageNotLoaded info exc)) = do+  finalizeForeignPtr img+  finalizeForeignPtr info+  finalizeForeignPtr exc+ setImageColormap clrs hImage = sideEffectingOp -  (\ im -> allocate_image_colormap (getImage im) (fromIntegral clrs))+  (\ im -> applyImageFn1 im allocate_image_colormap (fromIntegral clrs))   hImage  newImageColormap clrs = unsafePerformIO $ do   let hImage = allocateImage mkNewUnloadedImage-  withExceptions_ (allocate_image_colormap (getImage hImage)-    (fromIntegral clrs)) "setImageColormap: error setting colormap" (== 0)+  withExceptions_ (applyImageFn1 hImage allocate_image_colormap (fromIntegral clrs)) +    "setImageColormap: error setting colormap" (== 0)     (getExceptionInfo hImage)   return hImage  -- should require list to be nonempty appendImages order images@(img:_) = unsafePerformIO $ do   linkImagesTogether images-  iPtr <- withExceptions (append_images (getImage img) (toCEnum order) (getExceptionInfo img)) "appendImage: error appending"+  iPtr <- withExceptions (applyImageFn1' img append_images (toCEnum order))+            "appendImage: error appending"             (== nullPtr) (getExceptionInfo img)   return $ setImage img iPtr appendImages _ [] = unsafePerformIO $ signalException "appendImages: empty list"@@ -194,7 +213,7 @@ -- hmm, appendImages and averageImages look a lot alike... averageImages images@(img:_) = unsafePerformIO $ do   linkImagesTogether images-  iPtr <- withExceptions (average_images (getImage img) (getExceptionInfo img))+  iPtr <- withExceptions (applyImageFn' img average_images id)             "averageImages: error averaging" (== nullPtr) (getExceptionInfo img)   return $ setImage img iPtr averageImages []  = unsafePerformIO $ signalException "averageImages: empty list"@@ -202,7 +221,7 @@ -- TODO: should really abstract the patterns of "returns boolean" and -- "may return null pointer" cycleColormapImage amount img = sideEffectingOp-  (\ im -> cycle_colormap_image (getImage im) (fromIntegral amount))+  (\ im -> applyImageFn1 im cycle_colormap_image (fromIntegral amount))   img  {- @@ -223,7 +242,8 @@ ------------- Stuff what displays stuff animateImages images@(img:_) = do   linkImagesTogether images-  withExceptions_ (animate_images (getImageInfo img) (getImage img)) +  withExceptions_ (withForeignPtr (getImageInfo img) (\ii ->+                    (applyImageFn img (animate_images ii) id)))      "animateImages: error animating" (== 0) (getExceptionInfo img) animateImages [] = return () ------------- genericReadImage - not exported@@ -238,11 +258,13 @@     String -> IO HImage genericReadOp prepareImageInfo theAction errStr = do    infoPtr <- mkNewExceptionInfo-   image_info <- clone_image_info nullPtr+   image_info <- mkNewImageInfo    let theImage = mkUnloadedImage image_info infoPtr    prepareImageInfo theImage-   iPtr <- withExceptions (theAction image_info infoPtr) -             errStr (== nullPtr) infoPtr+   iPtr <- withForeignPtr image_info $ \ii_ptr -> +           withForeignPtr infoPtr    $ \exc_ptr ->+             withExceptions (theAction ii_ptr exc_ptr) +                           errStr (== nullPtr) infoPtr    return $ mkImage iPtr theImage  ----------------------------------------------  @@ -269,8 +291,7 @@  -- rotates an image by an arbitrary number of degrees rotateImage degrees hImage = doTransformIO-  (rotate_image (getImage hImage) (realToFrac degrees) -    (getExceptionInfo hImage))+  (applyImageFn1' hImage rotate_image (realToFrac degrees))   hImage  affineTransform affineMatrix hImage = unsafePerformIO $ do@@ -279,8 +300,7 @@     (\ matrixP -> do           poke matrixP affineMatrix           return $ doTransformIO-                    (affine_transform (getImage hImage) matrixP-                     (getExceptionInfo hImage))+                    (applyImageFn1' hImage affine_transform matrixP)                     hImage)  -- cuts the specified rectangle out of the image,@@ -337,16 +357,17 @@ -- the stupid argument names are due to these names being already taken -- as record fields. resizeImage cols rws fltr blr hImage = -   doTransformIO (resize_image (getImage hImage) (fromIntegral cols) -                   (fromIntegral rws) (toCEnum fltr) -                   (realToFrac blr) (getExceptionInfo hImage))+   doTransformIO (applyImageFn' hImage resize_image $ \f -> f +                    (fromIntegral cols) +                     (fromIntegral rws) (toCEnum fltr) +                     (realToFrac blr))       hImage ------------ enhancements -- TODO: the contrastImage call only increases or decreases by a -- given increment. perhaps want to change our API to specify -- an amount of contrast contrastImage increaseOrDecrease hImage = sideEffectingOp -  (\ im -> contrast_image (getImage im) sharpen) hImage +  (\ im -> applyImageFn1 im contrast_image sharpen) hImage       where sharpen = case increaseOrDecrease of                        IncreaseContrast -> 1                        DecreaseContrast -> 0@@ -355,27 +376,29 @@ normalizeImage = simpleOp normalize_image  gammaImage (PixelPacket { red=gRed, green=gGreen, blue=gBlue }) hImage = -  sideEffectingOp (\ im -> withCString levelStr (gamma_image (getImage im))) +  sideEffectingOp (\ im -> applyImageFn im gamma_image $ withCString levelStr)         hImage     where levelStr = commaSep [gRed, gGreen, gBlue]  levelImage (Level { black=lBlack, mid=lMid, white=lWhite }) hImage =-    sideEffectingOp (\ im -> withCString levelStr (level_image (getImage im)))+    sideEffectingOp (\ im -> +      applyImageFn im level_image $ withCString levelStr)          hImage              where levelStr = commaSep [lBlack, lMid, lWhite]  levelImageChannel chanTy (Level { black=lBlack, mid=lMid, white=lWhite })    hImage = sideEffectingOp (\ im -> -    level_image_channel (getImage im) (toCEnum chanTy) -         (realToFrac lBlack) (realToFrac lMid) (realToFrac lWhite)) hImage+            applyImageFn im level_image_channel $ \ f ->+    f (toCEnum chanTy) (realToFrac lBlack) +      (realToFrac lMid) (realToFrac lWhite)) hImage  modulateImage (Modulation{ brightness=b, saturation=s, hue=h }) hImage =     sideEffectingOp (\ im ->-       withCString modStr (modulate_image (getImage im))) hImage+      applyImageFn im modulate_image $ withCString modStr) hImage      where modStr = commaSep [b, s, h]  negateImage whatToNegate hImage = -    (sideEffectingOp (\ im -> negate_image (getImage im) whatToDo) hImage)+    (sideEffectingOp (\ im -> applyImageFn1 im negate_image whatToDo) hImage)        where whatToDo = case whatToNegate of                           AllPixels -> 0                           GrayscalePixels -> 1  @@ -395,15 +418,16 @@    debug 3 $ "width = " ++ show wdth ++ " height = " ++ show hght ++ " sz = " ++ (show (pixelSize pixMap) ++ " len = " ++ show (length aScanline))    iPtr <- withExceptions (withArray (map marshalPixel (concat pixels)) (\ pixelArray ->       withCString (show pixMap) $  -        (\ mapStr -> constitute_image -                       wdth-                       -- this is kind of weak... the pixmap-                       -- says how many numbers represent each pixel. seems bad.-                       -- we should have a better type system for this.-                       hght-                       mapStr -                       (toCEnum (storageType (head aScanline)))-                       pixelArray eInfo))) "constituteImage: error" (== nullPtr) eInfo+        (\ mapStr -> withForeignPtr eInfo $+                       constitute_image +                         wdth+                         -- this is kind of weak... the pixmap+                         -- says how many numbers represent each pixel. seems bad.+                         -- we should have a better type system for this.+                         hght+                         mapStr +                         (toCEnum (storageType (head aScanline)))+                         pixelArray))) "constituteImage: error" (== nullPtr) eInfo    iInfo <- mkNewImageInfo    return $ mkImage iPtr (mkUnloadedImage iInfo eInfo)     -- TODO: freeing pixelArray and other memory?@@ -420,10 +444,11 @@      (allocaArray len (\ pixelArray ->        withCString (show pixMap) $          (\ mapStr -> do-             withExceptions_ (dispatch_image (getImage hImage) (fromIntegral x_offset) -              (fromIntegral y_offset) (fromIntegral cols) -              (fromIntegral rws) mapStr (toCEnum storType) pixelArray-              (getExceptionInfo hImage)) "dispatchImage: error" (== 0) +             withExceptions_ (applyImageFn' hImage dispatch_image $ \f -> +               f (fromIntegral x_offset) (fromIntegral y_offset) +                  (fromIntegral cols) (fromIntegral rws) mapStr +                  (toCEnum storType) pixelArray) +                "dispatchImage: error" (== 0)                  (getExceptionInfo hImage)              pixelList <- peekArray (fromIntegral len) pixelArray              let blobs = map unmarshalPixel pixelList@@ -461,8 +486,8 @@         (\ pixelArray -> (alloca (\ importInfo -> (alloca (\ optionsPtr -> do            optsPtr <- maybeToPtr options optionsPtr            -- this side-effects the image, so we need to make a copy-           res <- (import_image_pixel_area (getImage theImage) -             (toCEnum quantumType) (fromIntegral quantumSize) pixelArray optsPtr+           res <- (applyImageFn theImage import_image_pixel_area $ \f -> +             f (toCEnum quantumType) (fromIntegral quantumSize) pixelArray optsPtr              importInfo)             bytes_imported <- (#peek ImportPixelAreaInfo, bytes_imported) importInfo            assertM (bytes_imported == length pixels) @@ -474,7 +499,7 @@   genericReadOp (const (return ()))     (\ image_info exception_info ->        (withCString cleanedUpString (\ content_str ->-             read_inline_image image_info content_str exception_info)))+           read_inline_image image_info content_str exception_info)))    "readInlineImage: error reading inline content"       where cleanedUpString = insertComma (deleteNewlines                     (deleteEqualsSignLine base64content))@@ -492,23 +517,50 @@                  (firstLine:secondLine:restLines) ->                      unlines (firstLine:((',':secondLine):restLines))                  _ -> s++blobToImage :: BS.ByteString -> HImage+blobToImage bs = unsafePerformIO $ do+    genericReadOp (const (return ()))+      (\image_info exception_info ->+        BS.unsafeUseAsCStringLen bs (\(ptr, len) ->+          blob_to_image image_info (castPtr ptr) (fromIntegral len) +                        exception_info))+      "blobToImage: error loading image from blob"++imageToBlob :: HImage -> BS.ByteString+imageToBlob img = unsafePerformIO $ +    withTmpImageInfo $ \imgInfo ->+    alloca $ \sizePtr -> do+        excInfo <- mkNewExceptionInfo+        dat <- withExceptions (applyImageFn1' img (image_to_blob imgInfo) sizePtr)+                               "imageToBlob: unable to encode image"+                               (==nullPtr)+                               excInfo+        len <- fromIntegral `fmap` peek sizePtr+        BS.unsafePackCStringFinalizer (castPtr dat) len (free dat)+ --------- helpers (private) ------------ simpleOp :: (Ptr HImage_ -> IO CUInt) -> HImage -> HImage-simpleOp op im = sideEffectingOp (op.getImage) im+simpleOp op im = sideEffectingOp +                  (\hImage -> +                    withForeignPtr (getImage hImage) $ \ii_ptr -> +                      op ii_ptr) im  withRectangle :: Rectangle ->   (Ptr HImage_ -> Ptr Rectangle -> Ptr ExceptionInfo -> IO (Ptr HImage_)) ->  HImage -> IO HImage withRectangle rect transform hImage = do-  -- Does this actually free the memory?+  -- Does this actually free the memory? +  -- Steffen: Yes, this will free the memory   (rectPtr::ForeignPtr Rectangle) <- mallocForeignPtr   -- This was causing a segfault so it\'s temporarily commented out.   -- TODO: Worry about memory freeing.+  -- Steffen: this is not needed, mallocForeignPtr already installs a+  --          correct finalizer   --addForeignPtrFinalizer p_free rectPtr   withForeignPtr rectPtr $      (\ rectP -> do         poke rectP rect        return $ doTransformIO-                  (transform (getImage hImage) rectP -                     (getExceptionInfo hImage))+                  (applyImageFn1' hImage transform rectP)                   hImage)
Graphics/Transform/Magick/Magick.hs view
@@ -1,9 +1,9 @@ module Graphics.Transform.Magick.Magick(module Foreign.C.Types,               module Foreign,               module Foreign.C.String,-              module Control.Monad,               initialize_magick,               get_exception_info,+              destroy_exception_info,               clone_image_info,               read_image,               write_image,@@ -39,6 +39,9 @@               -- constitution               constitute_image,               dispatch_image,+              -- blob+              blob_to_image,+              image_to_blob,               --export_image_pixel_area,               export_pixel_area_options_init,               import_image_pixel_area,@@ -58,6 +61,7 @@               cycle_colormap_image,                describe_image,                destroy_image, +              finalize_image,               destroy_image_info,                get_image_clip_mask,                get_image_depth, @@ -91,7 +95,6 @@ import Foreign import Foreign.C.Types import Foreign.C.String-import Control.Monad  -- The internal interface to the GraphicsMagick library. This -- module should mostly (if not entirely) contain import declarations@@ -106,6 +109,9 @@ foreign import ccall "static magick/api.h GetExceptionInfo"     get_exception_info :: Ptr ExceptionInfo -> IO () +foreign import ccall "static magick/api.h DestroyExceptionInfo"+    destroy_exception_info :: Ptr ExceptionInfo -> IO ()+ foreign import ccall "static magick/api.h CloneImageInfo"     clone_image_info :: Ptr HImageInfo -> IO (Ptr HImageInfo) @@ -148,6 +154,13 @@ foreign import ccall "static magick/api.h ReadInlineImage"     read_inline_image :: Ptr HImageInfo -> CString -> Ptr ExceptionInfo -> IO (Ptr HImage_) +----------------- Blob+foreign import ccall "static magick/api.h BlobToImage"+    blob_to_image :: Ptr HImageInfo -> Ptr CUChar -> CSize -> Ptr ExceptionInfo -> IO (Ptr HImage_)++foreign import ccall "static magick/api.h ImageToBlob"+    image_to_blob :: Ptr HImageInfo -> Ptr HImage_ -> Ptr CSize -> Ptr ExceptionInfo -> IO (Ptr CUChar)+ ----------------- Transformations  foreign import ccall "static magick/api.h FlipImage"@@ -278,6 +291,9 @@  foreign import ccall "static magick/api.h DestroyImage"     destroy_image :: Ptr HImage_ -> IO ()++foreign import ccall "static magick/api.h &DestroyImage"+    finalize_image :: FunPtr(Ptr HImage_ -> IO ())  foreign import ccall "static magick/api.h DestroyImageInfo"     destroy_image_info :: Ptr HImageInfo -> IO ()
Graphics/Transform/Magick/Types.hs view
@@ -20,10 +20,10 @@ -- the filename in both the image *and* the info.  -- TODO: don't export the selectors for this.-data HImage = HImage {image::Ptr HImage_,+data HImage = HImage {image::ForeignPtr HImage_,                       otherInfo::ImageNotLoaded}-data ImageNotLoaded = ImageNotLoaded { imageInfo::Ptr HImageInfo, -                                       exceptionInfo::Ptr ExceptionInfo }+data ImageNotLoaded = ImageNotLoaded { imageInfo::ForeignPtr HImageInfo, +                                       exceptionInfo::ForeignPtr ExceptionInfo }  -- A rectangle is represented as a width, height, horizontal offset, and -- vertical offset@@ -73,23 +73,18 @@   MatteChannel    deriving Enum -getImage :: HImage -> Ptr HImage_-getImageInfo :: HImage -> Ptr HImageInfo-getExceptionInfo :: HImage -> Ptr ExceptionInfo-setImage :: HImage -> Ptr HImage_ -> HImage+getImage :: HImage -> ForeignPtr HImage_+getImageInfo :: HImage -> ForeignPtr HImageInfo+getExceptionInfo :: HImage -> ForeignPtr ExceptionInfo  getImage = image getImageInfo = imageInfo.otherInfo getExceptionInfo = exceptionInfo.otherInfo -setImage hIm imPtr = hIm{ image = imPtr }--mkUnloadedImage :: Ptr HImageInfo -> Ptr ExceptionInfo -> ImageNotLoaded+mkUnloadedImage :: ForeignPtr HImageInfo -> ForeignPtr ExceptionInfo -> ImageNotLoaded mkUnloadedImage iInfo exInfo =     ImageNotLoaded{ imageInfo = iInfo, exceptionInfo = exInfo } -mkImage :: Ptr HImage_ -> ImageNotLoaded -> HImage-mkImage p info = HImage { image=p, otherInfo=info }  data FilterTypes =    UndefinedFilter
README view
@@ -25,9 +25,10 @@ be better yet.  Please submit bug reports, questions, feedback, complaints, praise,-and especially patches (including documentation patches) to me at:+and especially patches (including documentation patches) to the +maintainer at: -   chevalier@alum.wellesley.edu+     vincent_AT_xenbox.fr  I did a lot of this work during the second Haskell Hackathon (Hac II '07) in Freiburg in September 2007. I'd like to thank all the@@ -42,5 +43,5 @@  === Contributors === -Thanks to "nonowarn" for contributing patches.+Thanks to "nonowarn", "Steffen Siering" for contributing patches. 
hsmagick.cabal view
@@ -1,27 +1,27 @@ name:                hsmagick-version:             0.4+version:             0.5 synopsis:            FFI bindings for the GraphicsMagick library description:         FFI bindings for the GraphicsMagick library category:            Graphics license:             BSD3 license-file:        LICENSE author:              Tim Chevalier-maintainer:          chevalier@alum.wellesley.edu+maintainer:          Vincent Gerard, vincent@xenbox.fr copyright:           (c) Tim Chevalier, 2008 stability:           alpha-homepage:            http://community.haskell.org/~tim+homepage:            https://github.com/vincentg/hsmagick Cabal-Version:       >= 1.2.3 -tested-with:         GHC==6.10.4, GHC==6.12.2+tested-with:         GHC==6.10.4, GHC==6.12.2, GHC==7.0.2 build-type:          Simple data-files:          README  Library {-build-depends:       base < 5, directory, filepath, pretty, process+build-depends:       base < 5, directory, filepath, pretty, process, bytestring exposed-modules:     Graphics.Transform.Magick.Images, Graphics.Transform.Magick.Types, Graphics.Transform.Magick.Test other-modules:       Graphics.Transform.Magick.FFIHelpers, Graphics.Transform.Magick.Util, Graphics.Transform.Magick.Errors, Graphics.Transform.Magick.Magick ghc-options:         -Wall-extra-libraries:     tiff jasper jpeg png wmflite bz2 z m pthread+extra-libraries:     tiff jasper jpeg png wmflite bz2 z m pkgconfig-depends:   GraphicsMagick >= 1.3.3                    , lcms                    , freetype2