imagemagick (empty) → 0.0.1
raw patch · 62 files changed
+5831/−0 lines, 62 filesdep +HUnitdep +QuickCheckdep +basesetup-changed
Dependencies added: HUnit, QuickCheck, base, bytestring, directory, imagemagick, lifted-base, resourcet, system-filepath, test-framework, test-framework-hunit, test-framework-quickcheck2, text, transformers, vector
Files
- Graphics/ImageMagick/MagickCore.hs +8/−0
- Graphics/ImageMagick/MagickCore/Exception.hs +30/−0
- Graphics/ImageMagick/MagickCore/FFI/Gem.hsc +24/−0
- Graphics/ImageMagick/MagickCore/FFI/Log.hsc +17/−0
- Graphics/ImageMagick/MagickCore/FFI/MagickCore.hsc +6/−0
- Graphics/ImageMagick/MagickCore/FFI/Mime.hsc +16/−0
- Graphics/ImageMagick/MagickCore/FFI/Option.hsc +18/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/AlphaChannelType.hsc +25/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/CacheView.hsc +32/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/ChannelType.hsc +33/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/ColorspaceType.hsc +37/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Composite.hsc +81/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Compress.hsc +36/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Constitute.hsc +22/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Distort.hsc +45/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Exception.hsc +97/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/FilterTypes.hsc +42/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Fx.hsc +23/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Geometry.hsc +28/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Image.hsc +24/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Layer.hsc +32/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Log.hsc +37/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/MagickFunction.hsc +20/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/PaintMethod.hsc +20/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/PixelPacket.hsc +27/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Statistic.hsc +48/−0
- Graphics/ImageMagick/MagickCore/Types/FFI/Types.hsc +33/−0
- Graphics/ImageMagick/MagickCore/Types/MBits.hs +13/−0
- Graphics/ImageMagick/MagickWand.hs +11/−0
- Graphics/ImageMagick/MagickWand/FFI/DrawingWand.hsc +272/−0
- Graphics/ImageMagick/MagickWand/FFI/ImageDrawing.hsc +2/−0
- Graphics/ImageMagick/MagickWand/FFI/MagickWand.hsc +472/−0
- Graphics/ImageMagick/MagickWand/FFI/PixelIterator.hsc +131/−0
- Graphics/ImageMagick/MagickWand/FFI/PixelWand.hsc +276/−0
- Graphics/ImageMagick/MagickWand/FFI/Types.hsc +89/−0
- Graphics/ImageMagick/MagickWand/FFI/WandImage.hsc +626/−0
- Graphics/ImageMagick/MagickWand/FFI/WandProperties.hsc +136/−0
- LICENSE +103/−0
- Setup.hs +2/−0
- examples/3dlogo.hs +217/−0
- examples/affine.hs +232/−0
- examples/bunny.hs +63/−0
- examples/clipmask.hs +41/−0
- examples/cyclops.hs +35/−0
- examples/draw_shapes.hs +140/−0
- examples/extent.hs +29/−0
- examples/floodfill.hs +25/−0
- examples/gel.hs +145/−0
- examples/grayscale.hs +32/−0
- examples/landscape_3d.hs +94/−0
- examples/make_tile.hs +69/−0
- examples/modulate.hs +89/−0
- examples/pixel_mod.hs +50/−0
- examples/reflect.hs +46/−0
- examples/resize.hs +37/−0
- examples/round_mask.hs +38/−0
- examples/text_effects.hs +315/−0
- examples/tilt_shift.hs +38/−0
- examples/trans_paint.hs +30/−0
- examples/wandtest.hs +172/−0
- imagemagick.cabal +495/−0
- test/ImageTest.hs +405/−0
+ Graphics/ImageMagick/MagickCore.hs view
@@ -0,0 +1,8 @@+module Graphics.ImageMagick.MagickCore+ ( module X ) where++import Graphics.ImageMagick.MagickCore.Exception as X+import Graphics.ImageMagick.MagickCore.Gem as X+import Graphics.ImageMagick.MagickCore.Mime as X+import Graphics.ImageMagick.MagickCore.Option as X+import Graphics.ImageMagick.MagickCore.Types as X
+ Graphics/ImageMagick/MagickCore/Exception.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE DeriveDataTypeable #-}+module Graphics.ImageMagick.MagickCore.Exception+ ( MagickWandException(..)+ -- * support for ImageMagick Exceptions+ , ExceptionCarrier(..)+ , ExceptionSeverity+ , ExceptionType+ ) where++import Control.Exception.Base+import Data.Typeable+import Foreign+import Foreign.C.String+import Graphics.ImageMagick.MagickCore.Types++data MagickWandException = MagickWandException ExceptionSeverity ExceptionType String+ deriving (Typeable)+++instance Show (MagickWandException) where+ show (MagickWandException _ x s) = concat [show x, ": ", s]++instance Exception MagickWandException++-- * Exception Carrier can be different objects+-- that are used in functions++class ExceptionCarrier a where+ getException :: a -> IO MagickWandException+
+ Graphics/ImageMagick/MagickCore/FFI/Gem.hsc view
@@ -0,0 +1,24 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickCore.FFI.Gem+ where++import Foreign+import Foreign.C.Types+import Graphics.ImageMagick.MagickCore.Types.FFI.Types+#include <magick/MagickCore.h>++foreign import ccall "ConvertHSBToRGB" convertHSBToRGB+ :: CDouble -> CDouble -> CDouble -> Ptr Quantum -> Ptr Quantum -> Ptr Quantum -> IO ()+foreign import ccall "ConvertHSLToRGB" convertHSLToRGB+ :: CDouble -> CDouble -> CDouble -> Ptr Quantum -> Ptr Quantum -> Ptr Quantum -> IO ()+foreign import ccall "ConvertHWBToRGB" convertHWBToRGB+ :: CDouble -> CDouble -> CDouble -> Ptr Quantum -> Ptr Quantum -> Ptr Quantum -> IO ()+foreign import ccall "ConvertRGBToHSB" convertRGBToHSB+ :: Quantum -> Quantum -> Quantum -> Ptr CDouble -> Ptr CDouble -> Ptr CDouble -> IO ()+foreign import ccall "ConvertRGBToHSL" convertRGBToHSL+ :: Quantum -> Quantum -> Quantum -> Ptr CDouble -> Ptr CDouble -> Ptr CDouble -> IO ()+foreign import ccall "ConvertRGBToHWB" convertRGBToHWB+ :: Quantum -> Quantum -> Quantum -> Ptr CDouble -> Ptr CDouble -> Ptr CDouble -> IO ()+
+ Graphics/ImageMagick/MagickCore/FFI/Log.hsc view
@@ -0,0 +1,17 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickCore.FFI.Log+ where++import Foreign.C.String+import Foreign.C.Types+import Graphics.ImageMagick.MagickCore.Types.FFI.Log+#include <magick/MagickCore.h>+++-- | SetLogEventMask() accepts a list that determines which events to log. All+-- other events are ignored. By default, no debug is enabled. This method+-- returns the previous log event mask.+foreign import ccall "SetLogEventMask" setLogEventMask+ :: CString -> IO LogEventType
+ Graphics/ImageMagick/MagickCore/FFI/MagickCore.hsc view
@@ -0,0 +1,6 @@+module Graphics.ImageMagick.MagickCore.FFI.MagickCore+ where++import Graphics.ImageMagick.MagickCore.Types++
+ Graphics/ImageMagick/MagickCore/FFI/Mime.hsc view
@@ -0,0 +1,16 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickCore.FFI.Mime+ where++import Foreign.C.String+#include <magick/MagickCore.h>+++-- | MagickToMime() returns the officially registered (or de facto) MIME+-- media-type corresponding to a magick string. If there is no registered+-- media-type, then the string "image/x-magick" (all lower case) is returned.+-- The returned string must be deallocated by the user.+foreign import ccall "MagickToMime" magickToMime+ :: CString -> IO CString
+ Graphics/ImageMagick/MagickCore/FFI/Option.hsc view
@@ -0,0 +1,18 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickCore.FFI.Option+ where++import Foreign.C.String+import Foreign.C.Types++import Graphics.ImageMagick.MagickCore.Types.FFI.ChannelType++#include <magick/MagickCore.h>++-- | ParseChannelOption() parses channel type string representation++foreign import ccall "ParseChannelOption" parseChannelOption+ :: CString -> IO ChannelType+
+ Graphics/ImageMagick/MagickCore/Types/FFI/AlphaChannelType.hsc view
@@ -0,0 +1,25 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickCore.Types.FFI.AlphaChannelType+ where++import Foreign.C.Types+#include <magick/MagickCore.h>+newtype AlphaChannelType = AlphaChannelType { unAlphaChannelType :: CInt }+ deriving (Eq, Show)++#{enum AlphaChannelType, AlphaChannelType+ , undefinedAlphaChannel = UndefinedAlphaChannel+ , activateAlphaChannel = ActivateAlphaChannel+ , backgroundAlphaChannel = BackgroundAlphaChannel+ , copyAlphaChannel = CopyAlphaChannel+ , deactivateAlphaChannel = DeactivateAlphaChannel+ , extractAlphaChannel = ExtractAlphaChannel+ , opaqueAlphaChannel = OpaqueAlphaChannel+ , resetAlphaChannel = ResetAlphaChannel /* deprecated */+ , setAlphaChannel = SetAlphaChannel+ , shapeAlphaChannel = ShapeAlphaChannel+ , transparentAlphaChannel = TransparentAlphaChannel+ , lattenAlphaChannel = FlattenAlphaChannel+ , removeAlphaChannel = RemoveAlphaChannel+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/CacheView.hsc view
@@ -0,0 +1,32 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.CacheView+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype VirtualPixelMethod = VirtualPixelMethod { unVirtualPixelMethod :: CInt }+ deriving (Eq, Show)++#{enum VirtualPixelMethod, VirtualPixelMethod,+ undefinedVirtualPixelMethod = UndefinedVirtualPixelMethod,+ backgroundVirtualPixelMethod = BackgroundVirtualPixelMethod,+ constantVirtualPixelMethod = ConstantVirtualPixelMethod,+ ditherVirtualPixelMethod = DitherVirtualPixelMethod,+ edgeVirtualPixelMethod = EdgeVirtualPixelMethod,+ mirrorVirtualPixelMethod = MirrorVirtualPixelMethod,+ randomVirtualPixelMethod = RandomVirtualPixelMethod,+ tileVirtualPixelMethod = TileVirtualPixelMethod,+ transparentVirtualPixelMethod = TransparentVirtualPixelMethod,+ maskVirtualPixelMethod = MaskVirtualPixelMethod,+ blackVirtualPixelMethod = BlackVirtualPixelMethod,+ grayVirtualPixelMethod = GrayVirtualPixelMethod,+ whiteVirtualPixelMethod = WhiteVirtualPixelMethod,+ horizontalTileVirtualPixelMethod = HorizontalTileVirtualPixelMethod,+ verticalTileVirtualPixelMethod = VerticalTileVirtualPixelMethod,+ horizontalTileEdgeVirtualPixelMethod = HorizontalTileEdgeVirtualPixelMethod,+ verticalTileEdgeVirtualPixelMethod = VerticalTileEdgeVirtualPixelMethod,+ checkerTileVirtualPixelMethod = CheckerTileVirtualPixelMethod+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/ChannelType.hsc view
@@ -0,0 +1,33 @@+{-# LANGUAGE CPP, ForeignFunctionInterface, NoMonomorphismRestriction #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.ChannelType+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype ChannelType = ChannelType { unChannelType :: CInt }+ deriving (Eq, Show)++#{enum ChannelType, ChannelType+ , undefinedCHannel = UndefinedChannel+ , redChannel = RedChannel+ , grayChannel = GrayChannel+ , cyanChannel = CyanChannel+ , greenChannel = GreenChannel+ , magentaChannel = MagentaChannel+ , blueChannel = BlueChannel+ , yellowChannel = YellowChannel+ , alphaChannel = AlphaChannel+ , opacityChannel = OpacityChannel+ , matteChannel = MatteChannel + , blackChannel = BlackChannel+ , indexChannel = IndexChannel+ , compositeChannels = CompositeChannels+ , allChannels = AllChannels+ , trueAlphaChannel = TrueAlphaChannel+ , rgbChannels = RGBChannels+ , grayChannels = GrayChannels+ , syncChannels = SyncChannels+ , defaultChannels = DefaultChannels+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/ColorspaceType.hsc view
@@ -0,0 +1,37 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickCore.Types.FFI.ColorspaceType+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype ColorspaceType = ColorspaceType { unColorspaceType :: CInt }+ deriving (Eq, Show)+++#{enum ColorspaceType, ColorspaceType,+ undefinedColorspace = UndefinedColorspace,+ rgbColorspace = RGBColorspace,+ grayColorspace = GRAYColorspace,+ transparentColorspace = TransparentColorspace,+ ohtaColorspace = OHTAColorspace,+ labColorspace = LabColorspace,+ xyzColorspace = XYZColorspace,+ ycbCrColorspace = YCbCrColorspace,+ yccColorspace = YCCColorspace,+ yiqColorspace = YIQColorspace,+ ypbprColorspace = YPbPrColorspace,+ yuvColorspace = YUVColorspace,+ cmykColorspace = CMYKColorspace,+ srgbColorspace = sRGBColorspace,+ hsbColorspace = HSBColorspace,+ hslColorspace = HSLColorspace,+ hwbColorspace = HWBColorspace,+ rec601LumaColorspace = Rec601LumaColorspace,+ rec601YCbCrColorspace = Rec601YCbCrColorspace,+ rec709LumaColorspace = Rec709LumaColorspace,+ rec709YCbCrColorspace = Rec709YCbCrColorspace,+ logColorspace = LogColorspace,+ cmyColorspace = CMYColorspace+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/Composite.hsc view
@@ -0,0 +1,81 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickCore.Types.FFI.Composite+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype CompositeOperator = CompositeOperator { unCompositeOperator :: CInt }++#{enum CompositeOperator, CompositeOperator,+ undefinedCompositeOp = UndefinedCompositeOp,+ noCompositeOp = NoCompositeOp,+ modulusAddCompositeOp = ModulusAddCompositeOp,+ atopCompositeOp = AtopCompositeOp,+ blendCompositeOp = BlendCompositeOp,+ bumpmapCompositeOp = BumpmapCompositeOp,+ changeMaskCompositeOp = ChangeMaskCompositeOp,+ clearCompositeOp = ClearCompositeOp,+ colorBurnCompositeOp = ColorBurnCompositeOp,+ colorDodgeCompositeOp = ColorDodgeCompositeOp,+ colorizeCompositeOp = ColorizeCompositeOp,+ copyBlackCompositeOp = CopyBlackCompositeOp,+ copyBlueCompositeOp = CopyBlueCompositeOp,+ copyCompositeOp = CopyCompositeOp,+ copyCyanCompositeOp = CopyCyanCompositeOp,+ copyGreenCompositeOp = CopyGreenCompositeOp,+ copyMagentaCompositeOp = CopyMagentaCompositeOp,+ copyOpacityCompositeOp = CopyOpacityCompositeOp,+ copyRedCompositeOp = CopyRedCompositeOp,+ copyYellowCompositeOp = CopyYellowCompositeOp,+ darkenCompositeOp = DarkenCompositeOp,+ dstAtopCompositeOp = DstAtopCompositeOp,+ dstCompositeOp = DstCompositeOp,+ dstInCompositeOp = DstInCompositeOp,+ dstOutCompositeOp = DstOutCompositeOp,+ dstOverCompositeOp = DstOverCompositeOp,+ differenceCompositeOp = DifferenceCompositeOp,+ displaceCompositeOp = DisplaceCompositeOp,+ dissolveCompositeOp = DissolveCompositeOp,+ exclusionCompositeOp = ExclusionCompositeOp,+ hardLightCompositeOp = HardLightCompositeOp,+ hueCompositeOp = HueCompositeOp,+ inCompositeOp = InCompositeOp,+ lightenCompositeOp = LightenCompositeOp,+ linearLightCompositeOp = LinearLightCompositeOp,+ luminizeCompositeOp = LuminizeCompositeOp,+ minusDstCompositeOp = MinusDstCompositeOp,+ modulateCompositeOp = ModulateCompositeOp,+ multiplyCompositeOp = MultiplyCompositeOp,+ outCompositeOp = OutCompositeOp,+ overCompositeOp = OverCompositeOp,+ overlayCompositeOp = OverlayCompositeOp,+ plusCompositeOp = PlusCompositeOp,+ replaceCompositeOp = ReplaceCompositeOp,+ saturateCompositeOp = SaturateCompositeOp,+ screenCompositeOp = ScreenCompositeOp,+ softLightCompositeOp = SoftLightCompositeOp,+ srcAtopCompositeOp = SrcAtopCompositeOp,+ srcCompositeOp = SrcCompositeOp,+ srcInCompositeOp = SrcInCompositeOp,+ srcOutCompositeOp = SrcOutCompositeOp,+ srcOverCompositeOp = SrcOverCompositeOp,+ modulusSubtractCompositeOp = ModulusSubtractCompositeOp,+ thresholdCompositeOp = ThresholdCompositeOp,+ xorCompositeOp = XorCompositeOp,+ divideDstCompositeOp = DivideDstCompositeOp,+ distortCompositeOp = DistortCompositeOp,+ blurCompositeOp = BlurCompositeOp,+ pegtopLightCompositeOp = PegtopLightCompositeOp,+ vividLightCompositeOp = VividLightCompositeOp,+ pinLightCompositeOp = PinLightCompositeOp,+ linearDodgeCompositeOp = LinearDodgeCompositeOp,+ linearBurnCompositeOp = LinearBurnCompositeOp,+ mathematicsCompositeOp = MathematicsCompositeOp,+ divideSrcCompositeOp = DivideSrcCompositeOp,+ minusSrcCompositeOp = MinusSrcCompositeOp,+ darkenIntensityCompositeOp = DarkenIntensityCompositeOp,+ lightenIntensityCompositeOp = LightenIntensityCompositeOp+} +
+ Graphics/ImageMagick/MagickCore/Types/FFI/Compress.hsc view
@@ -0,0 +1,36 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickCore.Types.FFI.Compress+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype CompressionType = CompressionType { unCompressionType :: CInt }+ deriving (Eq, Show)+++#{enum CompressionType, CompressionType+ , undefinedCompression = UndefinedCompression+ , noCompression = NoCompression+ , bzipCompression = BZipCompression+ , dxt1Compression = DXT1Compression+ , dxt3Compression = DXT3Compression+ , dxt5Compression = DXT5Compression+ , axCompression = FaxCompression+ , group4Compression = Group4Compression+ , jpegCompression = JPEGCompression+ , jpeg2000Compression = JPEG2000Compression /* ISO/IEC std 15444-1 */+ , losslessJPEGCompression = LosslessJPEGCompression+ , lzwCompression = LZWCompression+ , rleCompression = RLECompression+ , zipCompression = ZipCompression+ , zipsCompression = ZipSCompression+ , pizCompression = PizCompression+ , pxr24Compression = Pxr24Compression+ , b44Compression = B44Compression+ , b44aCompression = B44ACompression+ , lzmaCompression = LZMACompression /* Lempel-Ziv-Markov chain algorithm */+ , jbig1Compression = JBIG1Compression /* ISO/IEC std 11544 / ITU-T rec T.82 */+ , jbig2Compression = JBIG2Compression /* ISO/IEC std 14492 / ITU-T rec T.88 */+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/Constitute.hsc view
@@ -0,0 +1,22 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.Constitute+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype StorageType = StorageType { unStorageType :: CInt }+ deriving (Eq, Show)++#{enum StorageType, StorageType+ , undefinedPixel = UndefinedPixel+ , charPixel = CharPixel+ , doublePixel = DoublePixel+ , floatPixel = FloatPixel+ , integerPixel = IntegerPixel+ , longPixel = LongPixel+ , quantumPixel = QuantumPixel+ , shortPixel = ShortPixel+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/Distort.hsc view
@@ -0,0 +1,45 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickCore.Types.FFI.Distort+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype DistortImageMethod = DistortImageMethod { unDistortImageMethod :: CInt }++#{enum DistortImageMethod, DistortImageMethod+ , undefinedDistortion = UndefinedDistortion+ , affineDistortion = AffineDistortion+ , affineProjectionDistortion = AffineProjectionDistortion+ , scaleRotateTranslateDistortion = ScaleRotateTranslateDistortion+ , perspectiveDistortion = PerspectiveDistortion+ , perspectiveProjectionDistortion = PerspectiveProjectionDistortion+ , bilinearForwardDistortion = BilinearForwardDistortion+ , bilinearReverseDistortion = BilinearReverseDistortion+ , polynomialDistortion = PolynomialDistortion+ , arcDistortion = ArcDistortion+ , polarDistortion = PolarDistortion+ , dePolarDistortion = DePolarDistortion+ , cylinder2PlaneDistortion = Cylinder2PlaneDistortion+ , plane2CylinderDistortion = Plane2CylinderDistortion+ , barrelDistortion = BarrelDistortion+ , barrelInverseDistortion = BarrelInverseDistortion+ , shepardsDistortion = ShepardsDistortion+ , resizeDistortion = ResizeDistortion+ , sentinelDistortion = SentinelDistortion+}++bilinearDistortion = bilinearForwardDistortion++newtype SparseColorMethod = SparseColorMethod { unSparseColorMethod :: CInt }++#{enum SparseColorMethod, SparseColorMethod,+ undefinedColorInterpolate = UndefinedDistortion,+ barycentricColorInterpolate = AffineDistortion,+ bilinearColorInterpolate = BilinearReverseDistortion,+ polynomialColorInterpolate = PolynomialDistortion,+ shepardsColorInterpolate = ShepardsDistortion,+ voronoiColorInterpolate = SentinelDistortion,+ inverseColorInterpolate =InverseColorInterpolate+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/Exception.hsc view
@@ -0,0 +1,97 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.Exception+ where++import Foreign.Storable+import Foreign.C.Types+#include <magick/MagickCore.h>++newtype ExceptionType = ExceptionType { unExceptionType :: CInt }+ deriving (Eq,Show,Storable)++#{enum ExceptionType, ExceptionType+ , undefinedException = UndefinedException+ , warningException = WarningException + , resourceLimitWarning = ResourceLimitWarning + , typeWarning = TypeWarning + , optionWarning = OptionWarning + , delegateWarning = DelegateWarning + , missingDelegateWarning = MissingDelegateWarning + , corruptImageWarning = CorruptImageWarning + , fileOpenWarning = FileOpenWarning + , blobWarning = BlobWarning + , streamWarning = StreamWarning + , cacheWarning = CacheWarning + , coderWarning = CoderWarning + , filterWarning = FilterWarning + , moduleWarning = ModuleWarning + , drawWarning = DrawWarning + , imageWarning = ImageWarning + , wandWarning = WandWarning + , randomWarning = RandomWarning + , xServerWarning = XServerWarning + , monitorWarning = MonitorWarning + , registryWarning = RegistryWarning + , configureWarning = ConfigureWarning + , policyWarning = PolicyWarning + , errorException = ErrorException + , resourceLimitError = ResourceLimitError + , typeError = TypeError + , optionError = OptionError + , delegateError = DelegateError + , missingDelegateError = MissingDelegateError + , corruptImageError = CorruptImageError + , fileOpenError = FileOpenError + , blobError = BlobError + , streamError = StreamError + , cacheError = CacheError + , coderError = CoderError + , filterError = FilterError + , moduleError = ModuleError + , drawError = DrawError + , imageError = ImageError + , wandError = WandError + , randomError = RandomError + , xServerError = XServerError + , monitorError = MonitorError + , registryError = RegistryError + , configureError = ConfigureError + , policyError = PolicyError + , fatalErrorException = FatalErrorException + , resourceLimitFatalError = ResourceLimitFatalError + , typeFatalError = TypeFatalError + , optionFatalError = OptionFatalError + , delegateFatalError = DelegateFatalError + , missingDelegateFatalError = MissingDelegateFatalError + , corruptImageFatalError = CorruptImageFatalError + , fileOpenFatalError = FileOpenFatalError + , blobFatalError = BlobFatalError + , streamFatalError = StreamFatalError + , cacheFatalError = CacheFatalError + , coderFatalError = CoderFatalError + , filterFatalError = FilterFatalError + , moduleFatalError = ModuleFatalError + , drawFatalError = DrawFatalError + , imageFatalError = ImageFatalError + , wandFatalError = WandFatalError + , randomFatalError = RandomFatalError + , xServerFatalError = XServerFatalError + , monitorFatalError = MonitorFatalError + , registryFatalError = RegistryFatalError + , configureFatalError = ConfigureFatalError + , policyFatalError = PolicyFatalError +}++data ExceptionSeverity = Undefined | Warning | Error | FatalError+ deriving (Eq, Show)++toSeverity :: ExceptionType -> ExceptionSeverity+toSeverity x = go ((unExceptionType x) `div` 100) + where + go 3 = Warning+ go 4 = Error+ go 7 = FatalError+ go _ = Undefined
+ Graphics/ImageMagick/MagickCore/Types/FFI/FilterTypes.hsc view
@@ -0,0 +1,42 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.FilterTypes+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype FilterTypes = FilterTypes { unPCREOption :: CInt }+ deriving (Eq,Show)++#{enum FilterTypes, FilterTypes+ , undefinedFilter = UndefinedFilter+ , pointFilter = PointFilter+ , boxFilter = BoxFilter+ , triangleFilter = TriangleFilter+ , hermiteFilter = HermiteFilter+ , hanningFilter = HanningFilter+ , hammingFilter = HammingFilter+ , blackmanFilter = BlackmanFilter+ , gaussianFilter = GaussianFilter+ , qaudraticFilter = QuadraticFilter+ , cubicFilter = CubicFilter+ , catromFilter = CatromFilter+ , mirchellFilter = MitchellFilter+ , jincFilter = JincFilter+ , sinkFilter = SincFilter+ , sinkFastFilter = SincFastFilter+ , kaiserFilter = KaiserFilter+ , welshFilter = WelshFilter+ , parzenFilter = ParzenFilter+ , bohmanFilter = BohmanFilter+ , bartlettFilter = BartlettFilter+ , lagrangeFilter = LagrangeFilter+ , lanczosFilter = LanczosFilter+ , lanczosSharpFilter = LanczosSharpFilter+ , lanczos2Filter = Lanczos2Filter+ , lanczos2SharpFilter = Lanczos2SharpFilter+ , robidouxFilter = RobidouxFilter+}+
+ Graphics/ImageMagick/MagickCore/Types/FFI/Fx.hsc view
@@ -0,0 +1,23 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.Fx+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype NoiseType = NoiseType { unNoiseType :: CInt }+ deriving (Eq, Show)++#{enum NoiseType, NoiseType,+ undefinedNoise = UndefinedNoise,+ uniformNoise = UniformNoise,+ gaussianNoise = GaussianNoise,+ multiplicativeGaussianNoise = MultiplicativeGaussianNoise,+ impulseNoise = ImpulseNoise,+ laplacianNoise = LaplacianNoise,+ poissonNoise = PoissonNoise,+ randomNoise = RandomNoise+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/Geometry.hsc view
@@ -0,0 +1,28 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.Geometry+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype GravityType = GravityType { unGravityType :: CInt }+ deriving (Eq, Show)++#{enum GravityType, GravityType+ , forgetGravity = ForgetGravity+ , northWestGravity = NorthWestGravity+ , northGravity = NorthGravity+ , northEastGravity = NorthEastGravity+ , westGravity = WestGravity + , centerGravity = CenterGravity+ , eastGravity = EastGravity+ , southWestGravity = SouthWestGravity+ , southGravity = SouthGravity+ , southEastGravity = SouthEastGravity+ , staticGravity = StaticGravity+}++undefinedGravity = forgetGravity
+ Graphics/ImageMagick/MagickCore/Types/FFI/Image.hsc view
@@ -0,0 +1,24 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickCore.Types.FFI.Image+ where++import Foreign.C.Types+#include <magick/MagickCore.h>+newtype ImageType = ImageType { unImageType :: CInt }+ deriving (Eq, Show)++#{enum ImageType, ImageType+ , undefinedType = UndefinedType+ , bilevelType = BilevelType+ , grayscaleType = GrayscaleType+ , grayscaleMatteType = GrayscaleMatteType+ , paletteType = PaletteType+ , paletteMatteType = PaletteMatteType+ , trueColorType = TrueColorType+ , trueColorMatteType = TrueColorMatteType+ , colorSeparationType = ColorSeparationType+ , colorSeparationMatteType = ColorSeparationMatteType+ , optimizeType = OptimizeType+ , paletteBilevelMatteType = PaletteBilevelMatteType+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/Layer.hsc view
@@ -0,0 +1,32 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.Layer+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype ImageLayerMethod = ImageLayerMethod { unImageLayerMethod :: CInt }+ deriving (Eq, Show)++#{enum ImageLayerMethod, ImageLayerMethod+ , undefinedLayer = UndefinedLayer+ , coalesceLayer = CoalesceLayer+ , compareAnyLayer = CompareAnyLayer+ , compareClearLayer = CompareClearLayer+ , compareOverlayLayer = CompareOverlayLayer+ , disposeLayer = DisposeLayer+ , optimizeLayer = OptimizeLayer+ , optimizeImageLayer = OptimizeImageLayer+ , optimizePlusLayer = OptimizePlusLayer+ , optimizeTransLayer = OptimizeTransLayer+ , removeDupsLayer = RemoveDupsLayer+ , removeZeroLayer = RemoveZeroLayer+ , compositeLayer = CompositeLayer+ , mergeLayer = MergeLayer+ , flattenLayer = FlattenLayer+ , mosaicLayer = MosaicLayer+ , trimBoundsLayer = TrimBoundsLayer+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/Log.hsc view
@@ -0,0 +1,37 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.Log+ where++import Foreign.C.Types+#include <magick/MagickCore.h>+++newtype LogEventType = LogEventType { unLogEventType :: CInt }+ deriving (Eq, Show)++#{enum LogEventType, LogEventType+ , undefinedEvents = UndefinedEvents+ , oEvents = NoEvents+ , raceEvent = TraceEvent+ , nnotateEvent = AnnotateEvent+ , lobEvent = BlobEvent+ , acheEvent = CacheEvent+ , oderEvent = CoderEvent+ , onfigureEvent = ConfigureEvent+ , eprecateEvent = DeprecateEvent+ , rawEvent = DrawEvent+ , xceptionEvent = ExceptionEvent+ , mageEvent = ImageEvent+ , ocaleEvent = LocaleEvent+ , oduleEvent = ModuleEvent+ , olicyEvent = PolicyEvent+ , esourceEvent = ResourceEvent+ , ransformEvent = TransformEvent+ , serEvent = UserEvent+ , andEvent = WandEvent+ , x11Event = X11Event+ , ccelerateEvent = AccelerateEvent+ , allEvents = AllEvents+}
+ Graphics/ImageMagick/MagickCore/Types/FFI/MagickFunction.hsc view
@@ -0,0 +1,20 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.MagickFunction+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype MagickFunction = MagickFunction { unMagickFunction :: CInt }+ deriving (Eq, Show)++#{enum MagickFunction, MagickFunction,+ undefinedFunction = UndefinedFunction,+ polynomialFunction = PolynomialFunction,+ sinusoidFunction = SinusoidFunction,+ arcsinFunction = ArcsinFunction,+ arctanFunction = ArctanFunction+}+
+ Graphics/ImageMagick/MagickCore/Types/FFI/PaintMethod.hsc view
@@ -0,0 +1,20 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickCore.Types.FFI.PaintMethod+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype PaintMethod = PaintMethod { unPaintMethod :: CInt }+++#{enum PaintMethod, PaintMethod,+ undefinedMethod = UndefinedMethod,+ pointMethod = PointMethod,+ replaceMethod = ReplaceMethod,+ floodfillMethod = FloodfillMethod,+ fillToBorderMethod = FillToBorderMethod,+ resetMethod = ResetMethod+}+
+ Graphics/ImageMagick/MagickCore/Types/FFI/PixelPacket.hsc view
@@ -0,0 +1,27 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE NoMonomorphismRestriction #-} +module Graphics.ImageMagick.MagickCore.Types.FFI.PixelPacket+ where++import Data.Int+import Data.Word+import Foreign+import Foreign.C.Types+#include <magick/MagickCore.h>++data PixelPacket ++instance Storable PixelPacket where+ sizeOf = const #size PixelPacket+ alignment _ = 1++pixelPacketGetRed = #peek PixelPacket, red+pixelPacketGetGreen = #peek PixelPacket, green+pixelPacketGetBlue = #peek PixelPacket, blue+pixelPacketGetOpacity = #peek PixelPacket, opacity+pixelPacketSetRed = #poke PixelPacket, red+pixelPacketSetGreen = #poke PixelPacket, green+pixelPacketSetBlue = #poke PixelPacket, blue+pixelPacketSetOpacity = #poke PixelPacket, opacity+
+ Graphics/ImageMagick/MagickCore/Types/FFI/Statistic.hsc view
@@ -0,0 +1,48 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Graphics.ImageMagick.MagickCore.Types.FFI.Statistic+ where++import Foreign.C.Types+#include <magick/MagickCore.h>++newtype MagickEvaluateOperator = MagickEvaluateOperator { unMagickEvaluateOperator :: CInt }+ deriving (Eq, Show)++#{enum MagickEvaluateOperator, MagickEvaluateOperator+ , undefinedEvaluateOperator = UndefinedEvaluateOperator+ , addEvaluateOperator = AddEvaluateOperator+ , andEvaluateOperator = AndEvaluateOperator+ , divideEvaluateOperator = DivideEvaluateOperator+ , leftShiftEvaluateOperator = LeftShiftEvaluateOperator+ , maxEvaluateOperator = MaxEvaluateOperator+ , minEvaluateOperator = MinEvaluateOperator+ , multiplyEvaluateOperator = MultiplyEvaluateOperator+ , orEvaluateOperator = OrEvaluateOperator+ , rightShiftEvaluateOperator = RightShiftEvaluateOperator+ , setEvaluateOperator = SetEvaluateOperator+ , subtractEvaluateOperator = SubtractEvaluateOperator+ , xorEvaluateOperator = XorEvaluateOperator+ , powEvaluateOperator = PowEvaluateOperator+ , logEvaluateOperator = LogEvaluateOperator+ , thresholdEvaluateOperator = ThresholdEvaluateOperator+ , thresholdBlackEvaluateOperator = ThresholdBlackEvaluateOperator+ , thresholdWhiteEvaluateOperator = ThresholdWhiteEvaluateOperator+ , gaussianNoiseEvaluateOperator = GaussianNoiseEvaluateOperator+ , impulseNoiseEvaluateOperator = ImpulseNoiseEvaluateOperator+ , laplacianNoiseEvaluateOperator = LaplacianNoiseEvaluateOperator+ , multiplicativeNoiseEvaluateOperator = MultiplicativeNoiseEvaluateOperator+ , poissonNoiseEvaluateOperator = PoissonNoiseEvaluateOperator+ , uniformNoiseEvaluateOperator = UniformNoiseEvaluateOperator+ , cosineEvaluateOperator = CosineEvaluateOperator+ , sineEvaluateOperator = SineEvaluateOperator+ , addModulusEvaluateOperator = AddModulusEvaluateOperator+ , meanEvaluateOperator = MeanEvaluateOperator+ , absEvaluateOperator = AbsEvaluateOperator+ , exponentialEvaluateOperator = ExponentialEvaluateOperator+ , medianEvaluateOperator = MedianEvaluateOperator+ , sumEvaluateOperator = SumEvaluateOperator+}+
+ Graphics/ImageMagick/MagickCore/Types/FFI/Types.hsc view
@@ -0,0 +1,33 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE RankNTypes #-}+module Graphics.ImageMagick.MagickCore.Types.FFI.Types+ where++import Data.Int+import Data.Word+import Foreign.C.String+import Foreign.C.Types+#include <magick/MagickCore.h>++type MagickRealType = #type MagickRealType+type MagickStatusType = #type MagickStatusType+type MagickOffsetType = #type MagickOffsetType+type MagickSizeType = #type MagickSizeType+type SignedQuantum = #type SignedQuantum+type QuantumAny = #type QuantumAny+type Quantum = #type Quantum+type IndexPacket = #type IndexPacket++magickEpsilon :: forall a. Fractional a => a+magickEpsilon = 1e-10 -- #const MagickEpsilon+magickHuge :: forall a. Num a => a+magickHuge = #const MagickHuge+maxColormapSize :: forall a. Num a => a+maxColormapSize = #const MaxColormapSize+maxMap :: forall a. Num a => a+maxMap = #const MaxMap+quantumFormat :: forall a. Num a => a+quantumFormat = #const QuantumFormat+quantumRange :: forall a. Num a => a+quantumRange = #const QuantumRange
+ Graphics/ImageMagick/MagickCore/Types/MBits.hs view
@@ -0,0 +1,13 @@+module Graphics.ImageMagick.MagickCore.Types.MBits+ where++import Data.Bits+import Graphics.ImageMagick.MagickCore.Types.FFI.ChannelType++class MBits a where+ (^|^) :: a -> a -> a+ (^&^) :: a -> a -> a++instance MBits ChannelType where+ a ^|^ b = ChannelType (unChannelType a .|. unChannelType b)+ a ^&^ b = ChannelType (unChannelType a .&. unChannelType b)
+ Graphics/ImageMagick/MagickWand.hs view
@@ -0,0 +1,11 @@+module Graphics.ImageMagick.MagickWand+ ( module G ) where++import Graphics.ImageMagick.MagickCore as G+import Graphics.ImageMagick.MagickWand.DrawingWand as G+import Graphics.ImageMagick.MagickWand.MagickWand as G+import Graphics.ImageMagick.MagickWand.PixelIterator as G+import Graphics.ImageMagick.MagickWand.PixelPacket as G+import Graphics.ImageMagick.MagickWand.PixelWand as G+import Graphics.ImageMagick.MagickWand.Types as G+import Graphics.ImageMagick.MagickWand.WandImage as G
+ Graphics/ImageMagick/MagickWand/FFI/DrawingWand.hsc view
@@ -0,0 +1,272 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickWand.FFI.DrawingWand+ where++import Foreign+import Foreign.C.String+import Foreign.C.Types++import Graphics.ImageMagick.MagickCore.Types+import Graphics.ImageMagick.MagickWand.FFI.Types++#include <wand/MagickWand.h>++-- | NewDrawingWand() returns a drawing wand required for all other methods in the API.+foreign import ccall "NewDrawingWand" newDrawingWand+ :: IO (Ptr DrawingWand)++-- | DestroyDrawingWand() frees all resources associated with the drawing wand.+-- Once the drawing wand has been freed, it should not be used and further unless it re-allocated.+foreign import ccall "DestroyDrawingWand" destroyDrawingWand+ :: Ptr DrawingWand -> IO (Ptr DrawingWand)++-- | PixelGetException() returns the severity, reason, and description of any+-- error that occurs when using other methods in this API.+foreign import ccall "DrawGetException" drawGetException+ :: Ptr DrawingWand -> Ptr ExceptionType -> IO CString++-- | DrawGetFillColor() returns the fill color used for drawing filled objects.+foreign import ccall "DrawGetFillColor" drawGetFillColor+ :: Ptr DrawingWand -> Ptr PixelWand -> IO ()++-- | DrawSetFillColor() sets the fill color to be used for drawing filled objects.+foreign import ccall "DrawSetFillColor" drawSetFillColor+ :: Ptr DrawingWand -> Ptr PixelWand -> IO ()++-- | DrawSetFillPatternURL() sets the URL to use as a fill pattern+-- for filling objects. Only local URLs ("#identifier") are supported+-- at this time. These local URLs are normally created by defining a named+-- fill pattern with DrawPushPattern/DrawPopPattern.+foreign import ccall "DrawSetFillPatternURL" drawSetFillPatternURL+ :: Ptr DrawingWand -> CString -> IO MagickBooleanType++-- | DrawSetFillRule() sets the fill rule to use while drawing polygons.+foreign import ccall "DrawSetFillRule" drawSetFillRule+ :: Ptr DrawingWand -> FillRule -> IO ()++-- | DrawSetFont() sets the fully-sepecified font to use when annotating with text.+foreign import ccall "DrawSetFont" drawSetFont+ :: Ptr DrawingWand -> CString -> IO ()++-- | DrawSetFontSize() sets the font pointsize to use when annotating with text.+foreign import ccall "DrawSetFontSize" drawSetFontSize+ :: Ptr DrawingWand -> CDouble -> IO ()++-- | DrawSetGravity() sets the text placement gravity to use when annotating with text.+foreign import ccall "DrawSetGravity" drawSetGravity+ :: Ptr DrawingWand -> GravityType -> IO ()++-- | DrawSetStrokeAntialias() controls whether stroked outlines are antialiased.+-- Stroked outlines are antialiased by default. When antialiasing is disabled+-- stroked pixels are thresholded to determine if the stroke color or+-- underlying canvas color should be used.+foreign import ccall "DrawSetStrokeAntialias" drawSetStrokeAntialias+ :: Ptr DrawingWand+ -> MagickBooleanType -- ^ stroke_antialias+ -> IO ()++-- | DrawSetStrokeColor() sets the color used for stroking object outlines.+foreign import ccall "DrawSetStrokeColor" drawSetStrokeColor+ :: Ptr DrawingWand+ -> Ptr PixelWand -- ^ stroke_wand+ -> IO ()++-- | DrawSetStrokeDashArray() specifies the pattern of dashes and gaps used to+-- stroke paths. The stroke dash array represents an array of numbers that+-- specify the lengths of alternating dashes and gaps in pixels. If an odd+-- number of values is provided, then the list of values is repeated to yield+-- an even number of values. To remove an existing dash array, pass a zero+-- number_elements argument and null dash_array. A typical stroke dash array+-- might contain the members 5 3 2.+foreign import ccall "DrawSetStrokeDashArray" drawSetStrokeDashArray+ :: Ptr DrawingWand+ -> CSize -- ^ number of elements in dash array+ -> Ptr CDouble -- ^ dash array values+ -> IO ()++-- | DrawSetStrokeLineCap() specifies the shape to be used at the end+-- of open subpaths when they are stroked. Values of LineCap are UndefinedCap,+-- ButtCap, RoundCap, and SquareCap.+foreign import ccall "DrawSetStrokeLineCap" drawSetStrokeLineCap+ :: Ptr DrawingWand+ -> LineCap -- ^ linecap+ -> IO ()++-- | DrawSetStrokeLineJoin() specifies the shape to be used at the corners+-- of paths (or other vector shapes) when they are stroked.+-- Values of LineJoin are UndefinedJoin, MiterJoin, RoundJoin, and BevelJoin.+foreign import ccall "DrawSetStrokeLineJoin" drawSetStrokeLineJoin+ :: Ptr DrawingWand+ -> LineJoin -- ^ linejoin+ -> IO ()++-- | DrawSetStrokeOpacity() specifies the opacity of stroked object outlines.+foreign import ccall "DrawSetStrokeOpacity" drawSetStrokeOpacity+ :: Ptr DrawingWand+ -> CDouble -- ^ stroke_opacity+ -> IO ()++-- | DrawSetStrokeOpacity() specifies the opacity of stroked object outlines.+foreign import ccall "DrawSetTextAntialias" drawSetTextAntialias+ :: Ptr DrawingWand+ -> MagickBooleanType -- ^ antialias boolean. Set to false (0) to disable antialiasing.+ -> IO ()++-- | DrawSetStrokeWidth() sets the width of the stroke used to draw object outlines.+foreign import ccall "DrawSetStrokeWidth" drawSetStrokeWidth+ :: Ptr DrawingWand+ -> CDouble -- ^ stroke_width+ -> IO ()++-- | DrawAnnotation() draws text on the image.+foreign import ccall "DrawAnnotation" drawAnnotation+ :: Ptr DrawingWand+ -> CDouble -- ^ x ordinate to left of text+ -> CDouble -- ^ y ordinate to text baseline+ -> CString -- ^ text to draw+ -> IO ()++-- | DrawCircle() draws a circle on the image.+foreign import ccall "DrawCircle" drawCircle+ :: Ptr DrawingWand+ -> CDouble -- ^ origin x ordinate+ -> CDouble -- ^ origin y ordinate+ -> CDouble -- ^ perimeter x ordinate+ -> CDouble -- ^ perimeter y ordinate+ -> IO ()++-- | DrawComposite() composites an image onto the current image, using+-- the specified composition operator, specified position, and at the specified size.+foreign import ccall "DrawComposite" drawComposite+ :: Ptr DrawingWand+ -> CompositeOperator -- ^ composition operator+ -> CDouble -- ^ x ordinate of top left corner+ -> CDouble -- ^ y ordinate of top left corner+ -> CDouble -- ^ width to resize image to prior to compositing, specify zero to use existing width+ -> CDouble -- ^ height to resize image to prior to compositing, specify zero to use existing height+ -> Ptr MagickWand -- ^ image to composite is obtained from this wand+ -> IO MagickBooleanType+++-- | DrawEllipse() draws an ellipse on the image.+foreign import ccall "DrawEllipse" drawEllipse+ :: Ptr DrawingWand+ -> CDouble -- ^ origin x ordinate+ -> CDouble -- ^ origin y ordinate+ -> CDouble -- ^ radius in x+ -> CDouble -- ^ radius in y+ -> CDouble -- ^ starting rotation in degrees+ -> CDouble -- ^ ending rotation in degrees+ -> IO ()++-- | DrawLine() draws a line on the image using the current stroke color,+-- stroke opacity, and stroke width.+foreign import ccall "DrawLine" drawLine+ :: Ptr DrawingWand+ -> CDouble -- ^ starting x ordinate+ -> CDouble -- ^ starting y ordinate+ -> CDouble -- ^ ending x ordinate+ -> CDouble -- ^ ending y ordinate+ -> IO ()++-- | DrawPolygon() draws a polygon using the current stroke, stroke width,+-- and fill color or texture, using the specified array of coordinates.+foreign import ccall "DrawPolygon" drawPolygon+ :: Ptr DrawingWand+ -> CSize -- ^ number of coordinates+ -> Ptr PointInfo -- ^ coordinate array+ -> IO ()++-- | DrawRectangle() draws a rectangle given two coordinates+-- and using the current stroke, stroke width, and fill settings.+foreign import ccall "DrawRectangle" drawRectangle+ :: Ptr DrawingWand+ -> CDouble -- ^ x ordinate of first coordinate+ -> CDouble -- ^ y ordinate of first coordinate+ -> CDouble -- ^ x ordinate of second coordinate+ -> CDouble -- ^ y ordinate of second coordinate+ -> IO ()++-- | DrawRoundRectangle() draws a rounted rectangle given two coordinates,+-- x & y corner radiuses and using the current stroke, stroke width, and fill settings.+foreign import ccall "DrawRoundRectangle" drawRoundRectangle+ :: Ptr DrawingWand+ -> CDouble -- ^ x ordinate of first coordinate+ -> CDouble -- ^ y ordinate of first coordinate+ -> CDouble -- ^ x ordinate of second coordinate+ -> CDouble -- ^ y ordinate of second coordinate+ -> CDouble -- ^ radius of corner in horizontal direction+ -> CDouble -- ^ radius of corner in vertical direction+ -> IO ()++-- | PushDrawingWand() clones the current drawing wand to create a new drawing wand.+-- The original drawing wand(s) may be returned to by invoking PopDrawingWand().+-- The drawing wands are stored on a drawing wand stack. For every Pop there must+-- have already been an equivalent Push.+foreign import ccall "PushDrawingWand" pushDrawingWand+ :: Ptr DrawingWand+ -> IO MagickBooleanType++-- | PopDrawingWand() destroys the current drawing wand and returns to the+-- previously pushed drawing wand. Multiple drawing wands may exist.+-- It is an error to attempt to pop more drawing wands than have been pushed,+-- and it is proper form to pop all drawing wands which have been pushed.+foreign import ccall "PopDrawingWand" popDrawingWand+ :: Ptr DrawingWand+ -> IO MagickBooleanType++-- | DrawRotate() applies the specified rotation to the current coordinate space.+foreign import ccall "DrawRotate" drawRotate+ :: Ptr DrawingWand+ -> CDouble -- ^ degrees of rotation+ -> IO ()++-- | DrawTranslate() applies a translation to the current coordinate system+-- which moves the coordinate system origin to the specified coordinate.+foreign import ccall "DrawTranslate" drawTranslate+ :: Ptr DrawingWand+ -> CDouble -- ^ new x ordinate for coordinate system origin+ -> CDouble -- ^ new y ordinate for coordinate system origin+ -> IO ()++-- | DrawPushPattern() indicates that subsequent commands up to+-- a DrawPopPattern() command comprise the definition of a named pattern.+-- The pattern space is assigned top left corner coordinates, a width and height,+-- and becomes its own drawing space. Anything which can be drawn may be used+-- in a pattern definition. Named patterns may be used as stroke or brush definitions.+foreign import ccall "DrawPushPattern" drawPushPattern+ :: Ptr DrawingWand+ -> CString -- ^ pattern identification for later reference+ -> CDouble -- x ordinate of top left corner+ -> CDouble -- y ordinate of top left corner+ -> CDouble -- width of pattern space+ -> CDouble -- height of pattern space+ -> IO MagickBooleanType++-- | DrawPopPattern() terminates a pattern definition.+foreign import ccall "DrawPopPattern" drawPopPattern+ :: Ptr DrawingWand+ -> IO MagickBooleanType+++-- | DrawColor() draws color on image using the current fill color, starting at+-- specified position, and using specified paint method. The available paint methods are:+--+-- PointMethod: Recolors the target pixel+-- ReplaceMethod: Recolor any pixel that matches the target pixel.+-- FloodfillMethod: Recolors target pixels and matching neighbors.+-- ResetMethod: Recolor all pixels.+foreign import ccall "DrawColor" drawColor+ :: Ptr DrawingWand+ -> CDouble+ -> CDouble+ -> PaintMethod+ -> IO ()++-- | DrawPoint() draws a point using the current fill color.+foreign import ccall "DrawPoint" drawPoint+ :: Ptr DrawingWand+ -> CDouble -- ^ target x coordinate+ -> CDouble -- ^ target y coordinate+ -> IO ()
+ Graphics/ImageMagick/MagickWand/FFI/ImageDrawing.hsc view
@@ -0,0 +1,2 @@+module Graphics.ImageMagick.MagickWand.FFI.ImageDrawing+ where
+ Graphics/ImageMagick/MagickWand/FFI/MagickWand.hsc view
@@ -0,0 +1,472 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickWand.FFI.MagickWand+ where++import Foreign+import Foreign.C.String+import Foreign.C.Types++import Graphics.ImageMagick.MagickCore.Types+import Graphics.ImageMagick.MagickWand.FFI.Types++#include <wand/MagickWand.h>+++-- | MagickWandGenesis() initializes the MagickWand environment.+foreign import ccall "MagickWandGenesis" magickWandGenesis+ :: IO ()++-- | MagickWandTerminus() terminates the MagickWand environment.+foreign import ccall "MagickWandTerminus" magickWandTerminus+ :: IO ()++-- * Constructing magic wand++-- | NewMagickWand() returns a wand required for all other methods in the API.+-- A fatal exception is thrown if there is not enough memory to allocate the wand.+-- Use DestroyMagickWand() to dispose of the wand when it is no longer needed.+foreign import ccall "NewMagickWand" newMagickWand+ :: IO (Ptr MagickWand)+++-- | NewMagickWandFromImage() returns a wand with an image.+foreign import ccall "NewMagickWandFromImage" newMagickWandFromImage+ :: Ptr Image -- ^ Image+ -> IO (Ptr MagickWand)++-- | CloneMagickWand() makes an exact copy of the specified wand.+foreign import ccall "CloneMagickWand" cloneMagickWand+ :: Ptr MagickWand -> IO (Ptr MagickWand)++-- * Clearing and destroying++-- | ClearMagickWand() clears resources associated with the wand,+-- leaving the wand blank, and ready to be used for a new set of images.+foreign import ccall "ClearMagickWand" clearMagickWand+ :: Ptr MagickWand -> IO ()++-- | DestroyMagickWand() deallocates memory associated with an MagickWand.+foreign import ccall "DestroyMagickWand" destroyMagickWand+ :: Ptr MagickWand -> IO (Ptr MagickWand)++foreign import ccall "&DestroyMagickWand" pDestroyMagickWand+ :: FunPtr (Ptr MagickWand -> IO ())+-- * Utilities++-- | IsMagickWand() returns MagickTrue if the wand is verified as a magick wand.+foreign import ccall " IsMagickWand" isMagicWand+ :: Ptr MagickWand -> IO MagickBooleanType++-- * Exceptions++-- | MagickClearException() clears any exceptions associated with the wand.+--+foreign import ccall "MagickClearException" magickClearException+ :: Ptr MagickWand -> IO MagickBooleanType++-- | MagickGetException() returns the severity, reason, and description of+-- any error that occurs when using other methods in this API.+foreign import ccall "MagickGetException" magickGetException+ :: Ptr MagickWand -> Ptr ExceptionType -> IO CString++-- | MagickGetExceptionType() returns the exception type associated with the wand.+-- If no exception has occurred, UndefinedExceptionType is returned.+foreign import ccall "MagickGetExceptionType" magickGetExceptionType+ :: Ptr MagickWand -> IO ExceptionType+++-- | MagickGetIteratorIndex() returns the position of the iterator in the image list.+foreign import ccall "MagickGetIteratorIndex" magickGetIteratorIndex :: Ptr MagickWand -> IO CSize+++{-++MagickQueryConfigureOption() returns the value associated with the specified configure option.+ char *MagickQueryConfigureOption(const char *option)++MagickQueryConfigureOptions() returns any configure options that match the specified pattern (e.g. "*" for all). Options include NAME, VERSION, LIB_VERSION, etc.++The format of the MagickQueryConfigureOptions function is:++ char **MagickQueryConfigureOptions(const char *pattern,+ size_t *number_options)++A description of each parameter follows:+pattern++Specifies a pointer to a text string containing a pattern.+number_options++Returns the number of configure options in the list.++++MagickQueryFontMetrics() returns a 13 element array representing the following font metrics:++ Element Description+ -------------------------------------------------+ 0 character width+ 1 character height+ 2 ascender+ 3 descender+ 4 text width+ 5 text height+ 6 maximum horizontal advance+ 7 bounding box: x1+ 8 bounding box: y1+ 9 bounding box: x2+ 10 bounding box: y2+ 11 origin: x+ 12 origin: y++The format of the MagickQueryFontMetrics method is:++ double *MagickQueryFontMetrics(MagickWand *wand,+ const DrawingWand *drawing_wand,const char *text)++A description of each parameter follows:+wand++the Magick wand.+drawing_wand++the drawing wand.+text++the text.+++MagickQueryMultilineFontMetrics() returns a 13 element array representing the following font metrics:++ Element Description+ -------------------------------------------------+ 0 character width+ 1 character height+ 2 ascender+ 3 descender+ 4 text width+ 5 text height+ 6 maximum horizontal advance+ 7 bounding box: x1+ 8 bounding box: y1+ 9 bounding box: x2+ 10 bounding box: y2+ 11 origin: x+ 12 origin: y++This method is like MagickQueryFontMetrics() but it returns the maximum text width and height for multiple lines of text.++The format of the MagickQueryFontMetrics method is:++ double *MagickQueryMultilineFontMetrics(MagickWand *wand,+ const DrawingWand *drawing_wand,const char *text)++A description of each parameter follows:+wand++the Magick wand.+drawing_wand++the drawing wand.+text++the text.++++MagickQueryFonts() returns any font that match the specified pattern (e.g. "*" for all).++The format of the MagickQueryFonts function is:++ char **MagickQueryFonts(const char *pattern,size_t *number_fonts)++A description of each parameter follows:+pattern++Specifies a pointer to a text string containing a pattern.+number_fonts++Returns the number of fonts in the list.++++MagickQueryFonts() returns any image formats that match the specified pattern (e.g. "*" for all).++The format of the MagickQueryFonts function is:++ char **MagickQueryFonts(const char *pattern,+ size_t *number_formats)++A description of each parameter follows:+pattern++Specifies a pointer to a text string containing a pattern.+number_formats++This integer returns the number of image formats in the list.+++++++++MagickSetFirstIterator() sets the wand iterator to the first image.++After using any images added to the wand using MagickAddImage() or MagickReadImage() will be prepended before any image in the wand.++Also the current image has been set to the first image (if any) in the Magick Wand. Using MagickNextImage() will then set teh current image to the second image in the list (if present).++This operation is similar to MagickResetIterator() but differs in how MagickAddImage(), MagickReadImage(), and MagickNextImage() behaves afterward.++The format of the MagickSetFirstIterator method is:++ void MagickSetFirstIterator(MagickWand *wand)++A description of each parameter follows:+wand++the magick wand.+++MagickSetIteratorIndex() set the iterator to the given position in the image list specified with the index parameter. A zero index will set the first image as current, and so on. Negative indexes can be used to specify an image relative to the end of the images in the wand, with -1 being the last image in the wand.++If the index is invalid (range too large for number of images in wand) the function will return MagickFalse, but no 'exception' will be raised, as it is not actually an error. In that case the current image will not change.++After using any images added to the wand using MagickAddImage() or MagickReadImage() will be added after the image indexed, regardless of if a zero (first image in list) or negative index (from end) is used.++Jumping to index 0 is similar to MagickResetIterator() but differs in how MagickNextImage() behaves afterward.++The format of the MagickSetIteratorIndex method is:++ MagickBooleanType MagickSetIteratorIndex(MagickWand *wand,+ const ssize_t index)++A description of each parameter follows:+wand++the magick wand.+index++the scene number.++++MagickSetLastIterator() sets the wand iterator to the last image.++The last image is actually the current image, and the next use of MagickPreviousImage() will not change this allowing this function to be used to iterate over the images in the reverse direction. In this sense it is more like MagickResetIterator() than MagickSetFirstIterator().++Typically this function is used before MagickAddImage(), MagickReadImage() functions to ensure new images are appended to the very end of wand's image list.++The format of the MagickSetLastIterator method is:++ void MagickSetLastIterator(MagickWand *wand)++A description of each parameter follows:+wand++the magick wand.++-}++-- * Image functions++-- | MagickNextImage() sets the next image in the wand as the current image.+-- It is typically used after MagickResetIterator(), after which its first use will+-- set the first image as the current image (unless the wand is empty).+--+-- It will return MagickFalse when no more images are left to be returned which+-- happens when the wand is empty, or the current image is the last image.+--+-- When the above condition (end of image list) is reached, the iterator is+-- automatically set so that you can start using MagickPreviousImage() to again+-- iterate over the images in the reverse direction, starting with the last image+-- (again). You can jump to this condition immeditally using MagickSetLastIterator().+foreign import ccall "MagickNextImage" magickNextImage+ :: Ptr MagickWand -> IO MagickBooleanType+++-- | MagickPreviousImage() sets the previous image in the wand as the current image.+--+-- It is typically used after MagickSetLastIterator(), after which its first use+-- will set the last image as the current image (unless the wand is empty).+--+-- It will return MagickFalse when no more images are left to be returned which+-- happens when the wand is empty, or the current image is the first image.+-- At that point the iterator is than reset to again process images in the forward+-- direction, again starting with the first image in list. Images added at this+-- point are prepended.+--+-- Also at that point any images added to the wand using MagickAddImages() or+-- MagickReadImages() will be prepended before the first image. In this sense the+-- condition is not quite exactly the same as MagickResetIterator().+foreign import ccall "MagickPreviousImage" magickPreviousImage+ :: Ptr MagickWand -> IO MagickBooleanType++{-+ ResizeFilter Bessel Blackman Box+ Catrom CubicGaussian+ Hanning Hermite Lanczos+ Mitchell PointQuandratic+ Sinc Triangle+-}++-- | MagickResizeImage() scales an image to the desired dimensions with one of these filters:+--+-- Most of the filters are FIR (finite impulse response), however, Bessel, Gaussian, and Sinc are+-- IIR (infinite impulse response). Bessel and Sinc are windowed (brought down to zero) with the Blackman filter.++foreign import ccall "MagickResizeImage" magickResizeImage+ :: Ptr MagickWand+ -> CSize -- ^ the number of columns in the scaled image+ -> CSize -- ^ the number of rows in the scaled image+ -> FilterTypes -- ^ filter+ -> CDouble -- ^ blur factor where 1 > blurry, < 1 sharp+ -> IO MagickBooleanType+++-- | MagickWriteImages() writes an image or image sequence.+foreign import ccall "MagickWriteImages" magickWriteImages+ :: Ptr MagickWand+ -> CString -- ^ filename+ -> MagickBooleanType -- ^ join images into a single multi-image file.+ -> IO MagickBooleanType+++-- | MagickSetSize() sets the size of the magick wand. Set it before you read a raw image format such as RGB, GRAY, or CMYK.+foreign import ccall "MagickSetSize" magickSetSize+ :: Ptr MagickWand+ -> CSize -- ^ columns+ -> CSize -- ^ rows+ -> IO MagickBooleanType+++-- | MagickGetSize() returns the size associated with the magick wand.+foreign import ccall "MagickGetSize" magickGetSize+ :: Ptr MagickWand+ -> Ptr CSize -- ^ the width in pixels+ -> Ptr CSize -- ^ the height in pixels+ -> IO MagickBooleanType+++-- | MagickGaussianBlurImage() blurs an image. We convolve the image with a Gaussian operator+-- of the given radius and standard deviation (sigma). For reasonable results, the radius should+-- be larger than sigma. Use a radius of 0 and MagickGaussianBlurImage() selects a suitable radius for you.+foreign import ccall "MagickGaussianBlurImage" magickGaussianBlurImage+ :: Ptr MagickWand+ -> CDouble -- ^ radius+ -> CDouble -- ^ sigma+ -> IO MagickBooleanType+++foreign import ccall "MagickGaussianBlurImage" magickGaussianBlurImageChannel+ :: Ptr MagickWand+ -> ChannelType+ -> CDouble -- ^ radius+ -> CDouble -- ^ sigma+ -> IO MagickBooleanType+++-- | MagickSetImageArtifact() associates a artifact with an image.+-- The format of the MagickSetImageArtifact method is:+foreign import ccall "MagickSetImageArtifact" magickSetImageArtifact+ :: Ptr MagickWand+ -> CString+ -> CString+ -> IO MagickBooleanType++-- | MagickDeleteImageArtifact() deletes a wand artifact.+foreign import ccall "MagickDeleteImageArtifact" magickDeleteImageArtifact+ :: Ptr MagickWand+ -> CString+ -> IO MagickBooleanType++-- | MagickSetIteratorIndex() set the iterator to the given position+-- in the image list specified with the index parameter. A zero index+-- will set the first image as current, and so on. Negative indexes+-- can be used to specify an image relative to the end of the images+-- in the wand, with -1 being the last image in the wand.+--+-- If the index is invalid (range too large for number of images in+-- wand) the function will return MagickFalse, but no 'exception' will+-- be raised, as it is not actually an error. In that case the current+-- image will not change.+--+-- After using any images added to the wand using `magickAddImage` or+-- `magickReadImage` will be added after the image indexed, regardless+-- of if a zero (first image in list) or negative index (from end)+-- is used.+--+-- Jumping to index 0 is similar to `magickResetIterator` but differs+-- in how `magickNextImage` behaves afterward.+foreign import ccall "MagickSetIteratorIndex" magickSetIteratorIndex+ :: Ptr MagickWand+ -> CSize -- ^ the scene number+ -> IO MagickBooleanType++-- | MagickResetIterator() resets the wand iterator.+--+-- It is typically used either before iterating though images, or+-- before calling specific functions such as `magickAppendImages`+-- to append all images together.+--+-- Afterward you can use `magickNextImage` to iterate over all the+-- images in a wand container, starting with the first image.+--+-- Using this before `magickAddImages` or `magickReadImages` will+-- cause new images to be inserted between the first and second image.+foreign import ccall "MagickResetIterator" magickResetIterator+ :: Ptr MagickWand+ -> IO ()++-- | MagickSetLastIterator() sets the wand iterator to the last image.+-- The last image is actually the current image, and the next use of+-- MagickPreviousImage() will not change this allowing this function+-- to be used to iterate over the images in the reverse direction.+-- In this sense it is more like MagickResetIterator() than+-- MagickSetFirstIterator().+-- Typically this function is used before MagickAddImage(),+-- MagickReadImage() functions to ensure new images are appended to+-- the very end of wand's image list.+foreign import ccall "MagickSetFirstIterator" magickSetFirstIterator+ :: Ptr MagickWand+ -> IO ()++-- | MagickSetFirstIterator() sets the wand iterator to the first image.+-- After using any images added to the wand using MagickAddImage() or+-- MagickReadImage() will be prepended before any image in the wand.+-- Also the current image has been set to the first image (if any) in+-- the Magick Wand. Using MagickNextImage() will then set teh current+-- image to the second image in the list (if present).+-- This operation is similar to MagickResetIterator() but differs in+-- how MagickAddImage(), MagickReadImage(), and MagickNextImage()+-- behaves afterward.+foreign import ccall "MagickSetLastIterator" magickSetLastIterator+ :: Ptr MagickWand+ -> IO ()++-- | MagickRelinquishMemory() relinquishes memory resources returned+-- by such methods as MagickIdentifyImage(), MagickGetException(), etc.+foreign import ccall "MagickRelinquishMemory" magickRelinquishMemory+ :: Ptr () -> IO ()++foreign import ccall "MagickGetColorspace" magickGetColorspace+ :: Ptr MagickWand -> IO ColorspaceType++foreign import ccall "MagickGetColorspace" magickSetColorspace+ :: Ptr MagickWand -> ColorspaceType -> IO MagickBooleanType++foreign import ccall "MagickGetCompressionQuality" magickGetCompressionQuality+ :: Ptr MagickWand -> IO CSize++foreign import ccall "MagickSetCompressionQuality" magickSetCompressionQuality+ :: Ptr MagickWand -> CSize -> IO MagickBooleanType++foreign import ccall "MagickGetCompression" magickGetCompression+ :: Ptr MagickWand -> IO CompressionType++foreign import ccall "MagickSetCompression" magickSetCompression+ :: Ptr MagickWand -> CompressionType -> IO MagickBooleanType
+ Graphics/ImageMagick/MagickWand/FFI/PixelIterator.hsc view
@@ -0,0 +1,131 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickWand.FFI.PixelIterator+ where++import Foreign+import Foreign.C.String+import Foreign.C.Types++import Graphics.ImageMagick.MagickCore.Types+import Graphics.ImageMagick.MagickWand.FFI.Types++#include <wand/MagickWand.h>++-- | ClearPixelIterator() clear resources associated with a PixelIterator.+foreign import ccall "ClearPixelIterator" clearPixelIterator+ :: Ptr PixelIterator -> IO ()++-- | ClonePixelIterator() makes an exact copy of the specified iterator.+foreign import ccall "ClonePixelIterator" clonePixelIterator+ :: Ptr PixelIterator -> IO (Ptr PixelIterator)++-- | DestroyPixelIterator() deallocates resources associated with a PixelIterator.+foreign import ccall "DestroyPixelIterator" destroyPixelIterator+ :: Ptr PixelIterator -> IO (Ptr PixelIterator)++-- | IsPixelIterator() returns MagickTrue if the iterator is verified as a pixel iterator.+foreign import ccall "IsPixelIterator" isPixelIterator+ :: Ptr PixelIterator -> IO MagickBooleanType++foreign import ccall "NewPixelIterator" newPixelIterator+ :: Ptr MagickWand -> IO (Ptr PixelIterator)++-- | NewPixelRegionIterator() returns a new pixel iterator.+foreign import ccall "NewPixelRegionIterator" newPixelRegionIterator+ :: Ptr MagickWand -> CSize -> CSize -> CSize -> CSize -> IO (Ptr PixelIterator)+++-- | PixelClearIteratorException() clear any exceptions associated with the iterator.+foreign import ccall "PixelClearIteratorException" pixelClearIteratorException+ :: Ptr PixelIterator -> IO MagickBooleanType++-- | PixelGetIteratorException() returns the severity, reason, and description of any+-- error that occurs when using other methods in this API.+foreign import ccall "PixelGetIteratorException" pixelGetIteratorException+ :: Ptr PixelIterator -> Ptr ExceptionType -> IO CString++-- | PixelGetIteratorExceptionType() the exception type associated with the iterator.+-- If no exception has occurred, UndefinedExceptionType is returned.+foreign import ccall "PixelGetIteratorExceptionType" pixelGetIteratorExceptionType+ :: Ptr PixelIterator -> IO ExceptionType++{- | PixelGetCurrentIteratorRow() returns the current row as an array of pixel wands from the pixel iterator.+-}+foreign import ccall "PixelGetCurrentIteratorRow" pixelGetCurrentIteratorRow+ :: Ptr PixelIterator -> CSize -> Ptr (Ptr PixelWand)++-- | PixelGetIteratorRow() returns the current pixel iterator row.+foreign import ccall "PixelGetIteratorRow" pixelGetIteratorRow+ :: Ptr PixelIterator -> IO ()++-- | PixelGetNextIteratorRow() returns the next row as an array of pixel wands from the pixel iterator.+foreign import ccall "PixelGetNextIteratorRow" pixelGetNextIteratorRow+ :: Ptr PixelIterator -- ^ iterator+ -> Ptr CSize -- ^ number of pixel wands+ -> IO (Ptr (Ptr PixelWand))++{-+ PixelGetPreviousIteratorRow++ PixelGetPreviousIteratorRow() returns the previous row as an array of pixel wands from the pixel iterator.++ The format of the PixelGetPreviousIteratorRow method is:++ PixelWand **PixelGetPreviousIteratorRow(PixelIterator *iterator,+ size_t *number_wands)++ A description of each parameter follows:+ iterator++ the pixel iterator.+ number_wands++ the number of pixel wands.+ PixelSetFirstIteratorRow++ PixelSetFirstIteratorRow() sets the pixel iterator to the first pixel row.++ The format of the PixelSetFirstIteratorRow method is:++ void PixelSetFirstIteratorRow(PixelIterator *iterator)++ A description of each parameter follows:+ iterator++ the magick iterator.+ PixelSetIteratorRow++ PixelSetIteratorRow() set the pixel iterator row.++ The format of the PixelSetIteratorRow method is:++ MagickBooleanType PixelSetIteratorRow(PixelIterator *iterator,+ const ssize_t row)++ A description of each parameter follows:+ iterator++ the pixel iterator.+ PixelSetLastIteratorRow++ PixelSetLastIteratorRow() sets the pixel iterator to the last pixel row.++ The format of the PixelSetLastIteratorRow method is:++ void PixelSetLastIteratorRow(PixelIterator *iterator)++ A description of each parameter follows:+ iterator++ the magick iterator.+-}++foreign import ccall "PixelSyncIterator" pixelSyncIterator+ :: Ptr PixelIterator -> IO MagickBooleanType++-- | PixelResetIterator() resets the pixel iterator. Use it in conjunction+-- with PixelGetNextIteratorRow() to iterate over all the pixels in a pixel container.+foreign import ccall "PixelResetIterator" pixelResetIterator+ :: Ptr PixelIterator -> IO ()
+ Graphics/ImageMagick/MagickWand/FFI/PixelWand.hsc view
@@ -0,0 +1,276 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}++module Graphics.ImageMagick.MagickWand.FFI.PixelWand+ where++import Foreign+import Foreign.C.String+import Foreign.C.Types++import Graphics.ImageMagick.MagickCore.Types+import Graphics.ImageMagick.MagickWand.FFI.Types++#include <wand/MagickWand.h>++-- | DestroyPixelWand() deallocates resources associated with a PixelWand.++foreign import ccall "DestroyPixelWand" destroyPixelWand+ :: Ptr PixelWand -> IO (Ptr PixelWand)++foreign import ccall "DestroyPixelWands" destroyPixelWands+ :: Ptr PixelWand -> CSize -> IO ()++foreign import ccall "IsPixelWand" isPixelWand+ :: Ptr PixelWand -> IO MagickBooleanType++-- | PixelGetMagickColor() gets the magick color of the pixel wand.+foreign import ccall "PixelGetMagickColor" pixelGetMagickColor+ :: Ptr PixelWand -> Ptr MagickPixelPacket -> IO ()++-- | PixelSetMagickColor() sets the color of the pixel wand.+foreign import ccall "PixelSetMagickColor" pixelSetMagickColor+ :: Ptr PixelWand -> Ptr MagickPixelPacket -> IO ()++foreign import ccall "ClearPixelWand" clearPixelWand+ :: Ptr PixelWand -> IO ()++foreign import ccall "ClonePixelWand" clonePixelWand+ :: Ptr PixelWand -> IO (Ptr PixelWand)++-- | NewPixelWand() returns a new pixel wand.+foreign import ccall "NewPixelWand" newPixelWand+ :: IO (Ptr PixelWand)++-- | NewPixelWands() returns an array of pixel wands.+foreign import ccall "NewPixelWands" newPixelWands+ :: CSize -> IO (Ptr (Ptr PixelWand))++-- | PixelSetColor() sets the color of the pixel wand with a string (e.g. "blue", "#0000ff", "rgb(0,0,255)", "cmyk(100,100,100,10)", etc.).+foreign import ccall "PixelSetColor" pixelSetColor+ :: Ptr PixelWand -> CString -> IO MagickBooleanType++-- | PixelClearException() clear any exceptions associated with the iterator.+foreign import ccall "PixelClearException" pixelClearException+ :: Ptr PixelWand -> IO MagickBooleanType++-- | PixelGetException() returns the severity, reason, and description of any+-- error that occurs when using other methods in this API.+foreign import ccall "PixelGetException" pixelGetException+ :: Ptr PixelWand -> Ptr ExceptionType -> IO CString++-- | PixelGetExceptionType() the exception type associated with the wand.+-- If no exception has occurred, UndefinedExceptionType is returned.+foreign import ccall "PixelGetExceptionType" pixelGetExceptionType+ :: Ptr PixelWand -> IO ExceptionType++-- | PixelGetColorAsString() returnsd the color of the pixel wand as a string.+foreign import ccall "PixelGetColorAsString" pixelGetColorAsString+ :: Ptr PixelWand -> IO CString++-- | PixelGetColorAsNormalizedString() returns the normalized color of the pixel wand as a string.+foreign import ccall "PixelGetColorAsNormalizedString" pixelGetColorAsNormalizedString+ :: Ptr PixelWand -> IO CString++-- | PixelGetRed) returns the normalized red color of the pixel wand.+foreign import ccall "PixelSetRed" pixelSetRed+ :: Ptr PixelWand -> CDouble -> IO ()++-- | PixelSetRedQuantum() sets the red color of the pixel wand.+foreign import ccall "PixelSetRedQuantum" pixelSetRedQuantum+ :: Ptr PixelWand -> Quantum -> IO ()++-- | PixelGetRed) returns the normalized red color of the pixel wand.+foreign import ccall "PixelGetRed" pixelGetRed+ :: Ptr PixelWand -> IO CDouble++-- | PixelGetRedQuantum() returns the red color of the pixel wand.+foreign import ccall "PixelGetRedQuantum" pixelGetRedQuantum+ :: Ptr PixelWand -> IO Quantum++-- | PixelGetGreen) returns the normalized green color of the pixel wand.+foreign import ccall "PixelGetGreen" pixelGetGreen+ :: Ptr PixelWand -> IO CDouble++-- | PixelGetGreenQuantum() returns the green color of the pixel wand.+foreign import ccall "PixelGetGreenQuantum" pixelGetGreenQuantum+ :: Ptr PixelWand -> IO Quantum++-- | PixelSetGreen() sets the green color of the pixel wand.+foreign import ccall "PixelSetGreen" pixelSetGreen+ :: Ptr PixelWand -> CDouble -> IO ()++-- | PixelSetGreenQuantum() sets the green color of the pixel wand.+foreign import ccall "PixelSetGreenQuantum" pixelSetGreenQuantum+ :: Ptr PixelWand -> Quantum -> IO ()++-- | PixelGetBlue() returns the normalized blue color of the pixel wand.+foreign import ccall "PixelGetBlue" pixelGetBlue+ :: Ptr PixelWand -> IO CDouble++foreign import ccall "PixelSetBlue" pixelSetBlue+ :: Ptr PixelWand -> CDouble -> IO ()++-- | PixelGetBlueQuantum() returns the blue color of the pixel wand.+foreign import ccall "PixelGetBlueQuantum" pixelGetBlueQuantum+ :: Ptr PixelWand -> IO Quantum++-- | PixelSetBlueQuantum() sets the blue color of the pixel wand.+foreign import ccall "PixelSetBlueQuantum" pixelSetBlueQuantum+ :: Ptr PixelWand -> Quantum -> IO ()++-- | IsPixelWandSimilar() returns MagickTrue if the distance between+-- two colors is less than the specified distance.+foreign import ccall "IsPixelWandSimilar" isPixelWandSimilar+ :: Ptr PixelWand -> Ptr PixelWand+ -> CDouble -- ^ any two colors that are less than or equal to this distance squared are consider similar+ -> IO MagickBooleanType++-- | PixelGetCyan) returns the normalized blue color of the pixel wand.+foreign import ccall "PixelGetCyan" pixelGetCyan+ :: Ptr PixelWand -> IO CDouble++foreign import ccall "PixelSetCyan" pixelSetCyan+ :: Ptr PixelWand -> CDouble -> IO ()++-- | PixelGetCyanQuantum() returns the blue color of the pixel wand.+foreign import ccall "PixelGetCyanQuantum" pixelGetCyanQuantum+ :: Ptr PixelWand -> IO Quantum++-- | PixelSetCyanQuantum() sets the blue color of the pixel wand.+foreign import ccall "PixelSetCyanQuantum" pixelSetCyanQuantum+ :: Ptr PixelWand -> Quantum -> IO ()++-- | PixelGetMagenta) returns the normalized blue color of the pixel wand.+foreign import ccall "PixelGetMagenta" pixelGetMagenta+ :: Ptr PixelWand -> IO CDouble++foreign import ccall "PixelSetMagenta" pixelSetMagenta+ :: Ptr PixelWand -> CDouble -> IO ()++-- | PixelGetMagentaQuantum() returns the blue color of the pixel wand.+foreign import ccall "PixelGetMagentaQuantum" pixelGetMagentaQuantum+ :: Ptr PixelWand -> IO Quantum++-- | PixelSetMagentaQuantum() sets the blue color of the pixel wand.+foreign import ccall "PixelSetMagentaQuantum" pixelSetMagentaQuantum+ :: Ptr PixelWand -> Quantum -> IO ()++-- | PixelGetYellow) returns the normalized blue color of the pixel wand.+foreign import ccall "PixelGetYellow" pixelGetYellow+ :: Ptr PixelWand -> IO CDouble++foreign import ccall "PixelSetYellow" pixelSetYellow+ :: Ptr PixelWand -> CDouble -> IO ()++-- | PixelGetYellowQuantum() returns the blue color of the pixel wand.+foreign import ccall "PixelGetYellowQuantum" pixelGetYellowQuantum+ :: Ptr PixelWand -> IO Quantum++-- | PixelSetYellowQuantum() sets the blue color of the pixel wand.+foreign import ccall "PixelSetYellowQuantum" pixelSetYellowQuantum+ :: Ptr PixelWand -> Quantum -> IO ()++-- | PixelGetBlack) returns the normalized blue color of the pixel wand.+foreign import ccall "PixelGetBlack" pixelGetBlack+ :: Ptr PixelWand -> IO CDouble++foreign import ccall "PixelSetBlack" pixelSetBlack+ :: Ptr PixelWand -> CDouble -> IO ()++-- | PixelGetBlackQuantum() returns the blue color of the pixel wand.+foreign import ccall "PixelGetBlackQuantum" pixelGetBlackQuantum+ :: Ptr PixelWand -> IO Quantum++-- | PixelSetBlackQuantum() sets the blue color of the pixel wand.+foreign import ccall "PixelSetBlackQuantum" pixelSetBlackQuantum+ :: Ptr PixelWand -> Quantum -> IO ()++-- | PixelGetAlpha) returns the normalized blue color of the pixel wand.+foreign import ccall "PixelGetAlpha" pixelGetAlpha+ :: Ptr PixelWand -> IO CDouble++-- | PixelGetAlphaQuantum() returns the blue color of the pixel wand.+foreign import ccall "PixelGetAlphaQuantum" pixelGetAlphaQuantum+ :: Ptr PixelWand -> IO Quantum++-- | PixelSetAlphaQuantum() sets the blue color of the pixel wand.+foreign import ccall "PixelSetAlphaQuantum" pixelSetAlphaQuantum+ :: Ptr PixelWand -> Quantum -> IO ()++foreign import ccall "PixelSetAlpha" pixelSetAlpha+ :: Ptr PixelWand -> CDouble -> IO ()++-- | PixelGetOpacity) returns the normalized blue color of the pixel wand.+foreign import ccall "PixelGetOpacity" pixelGetOpacity+ :: Ptr PixelWand -> IO CDouble++-- | PixelGetOpacityQuantum() returns the blue color of the pixel wand.+foreign import ccall "PixelGetOpacityQuantum" pixelGetOpacityQuantum+ :: Ptr PixelWand -> IO Quantum++-- | PixelSetOpacityQuantum() sets the blue color of the pixel wand.+foreign import ccall "PixelSetOpacityQuantum" pixelSetOpacityQuantum+ :: Ptr PixelWand -> Quantum -> IO ()++foreign import ccall "PixelSetOpacity" pixelSetOpacity+ :: Ptr PixelWand -> CDouble -> IO ()++++-- | PixelGetColorCount() returns the color count associated with this color.+foreign import ccall "PixelGetColorCount" pixelGetColorCount+ :: Ptr PixelWand -> IO CSize++-- | PixelSetColorCount() sets the color count of the pixel wand.+foreign import ccall "PixelSetColorCount" pixelSetColorCount+ :: Ptr PixelWand -> CSize -> IO ()++-- PixelGetHSL() returns the normalized HSL color of the pixel wand.+foreign import ccall "PixelGetHSL" pixelGetHSL+ :: Ptr PixelWand -> Ptr CDouble -> Ptr CDouble -> Ptr CDouble -> IO ()++-- | PixelSetHSL() sets the normalized HSL color of the pixel wand.+foreign import ccall "PixelSetHSL" pixelSetHSL+ :: Ptr PixelWand -> CDouble -> CDouble -> CDouble -> IO ()+++-- | PixelSetColorFromWand() sets the color of the pixel wand.+foreign import ccall "PixelSetColorFromWand" pixelSetColorFromWand+ :: Ptr PixelWand -> Ptr PixelWand -> IO ()+++-- | PixelGetIndex() returns the colormap index from the pixel wand.+foreign import ccall "PixelGetIndex" pixelGetIndex+ :: Ptr PixelWand -> IO IndexPacket+++-- | PixelSetIndex() sets the colormap index of the pixel wand.+foreign import ccall "PixelSetColor" pixelSetIndex+ :: Ptr PixelWand -> IndexPacket -> IO ()++-- | PixelGetQuantumColor() gets the color of the pixel wand as a PixelPacket.+foreign import ccall "PixelGetQuantumColor" pixelGetQuantumColor+ :: Ptr PixelWand -> Ptr PixelPacket -> IO ()++-- | PixelGetQuantumColor() gets the color of the pixel wand as a PixelPacket.+foreign import ccall "PixelSetQuantumColor" pixelSetQuantumColor+ :: Ptr PixelWand -> Ptr PixelPacket -> IO ()++-- | PixelGetFuzz() returns the normalized fuzz value of the pixel wand.+foreign import ccall "PixelGetFuzz" pixelGetFuzz+ :: Ptr PixelWand -> IO CDouble++-- | PixelSetFuzz() sets the fuzz value of the pixel wand.+foreign import ccall "PixelSetFuzz" pixelSetFuzz+ :: Ptr PixelWand -> CDouble -> IO ()++{-+ClonePixelWands() makes an exact copy of the specified wands.++The format of the ClonePixelWands method is:++ PixelWand **ClonePixelWands(const PixelWand **wands,+ const size_t number_wands)++-}
+ Graphics/ImageMagick/MagickWand/FFI/Types.hsc view
@@ -0,0 +1,89 @@+{-# LANGUAGE CPP, ForeignFunctionInterface, NoMonomorphismRestriction, RankNTypes #-}++module Graphics.ImageMagick.MagickWand.FFI.Types+ where++#include <wand/MagickWand.h>++import Control.Monad++import Foreign+import Foreign.C.Types+import Graphics.ImageMagick.MagickCore.Types.FFI.Types++data PixelIterator+data MagickWand+data PixelWand+data DrawingWand+data Image+data PointInfo = PointInfo {piX, piY :: CDouble}+ deriving (Eq, Show)++instance Storable PointInfo where+ sizeOf = const #size PointInfo+ alignment _ = 1+ poke p foo = do+ #{poke PointInfo, x} p $ piX foo+ #{poke PointInfo, y} p $ piY foo++ peek p = return PointInfo+ `ap` (#{peek PointInfo, x} p)+ `ap` (#{peek PointInfo, y} p)+++newtype MagickBooleanType = MagickBooleanType { unMagickBooleanType :: CInt}+ deriving (Eq, Show)++#{enum MagickBooleanType, MagickBooleanType + , mFalse = MagickFalse+ , mTrue = MagickTrue+}++newtype ClassType = ClassType { unClassType :: CInt}+ deriving (Eq, Show)++#{enum ClassType, ClassType+ , undefinedClass = UndefinedClass+ , directClass = DirectClass+ , pseudoClass = PseudoClass+}++newtype LineCap = LineCap { unLineCap :: CInt }+#{enum LineCap, LineCap+ , udefinedCap = UndefinedCap+ , buttCap = ButtCap+ , roundCap = RoundCap+ , squareCap = SquareCap+}++newtype LineJoin = LineJoin { unLineJoin :: CInt }+#{enum LineJoin, LineJoin+ , undefinedJoin = UndefinedJoin+ , mitterJoin = MiterJoin+ , roundJoin = RoundJoin+ , bevelJoin = BevelJoin+}++newtype FillRule = FillRule { unFillRule :: CInt }+#{enum FillRule, FillRule+ , undefinedRule = UndefinedRule+ , evenOddRule = EvenOddRule+ , nonZeroRule = NonZeroRule+}++data MagickPixelPacket ++instance Storable MagickPixelPacket where+ sizeOf = const #size MagickPixelPacket+ alignment _ = 1+++getPixelRed = #peek MagickPixelPacket, red+getPixelGreen = #peek MagickPixelPacket, green+getPixelBlue = #peek MagickPixelPacket, blue+getPixelIndex = #peek MagickPixelPacket, index+setPixelRed = #poke MagickPixelPacket, red+setPixelGreen = #poke MagickPixelPacket, green+setPixelBlue = #poke MagickPixelPacket, blue+setPixelIndex = #poke MagickPixelPacket, index+
+ Graphics/ImageMagick/MagickWand/FFI/WandImage.hsc view
@@ -0,0 +1,626 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickWand.FFI.WandImage+ where++import Foreign+import Foreign.C.String+import Foreign.C.Types++import Graphics.ImageMagick.MagickCore.Types+import Graphics.ImageMagick.MagickWand.FFI.Types++#include <wand/MagickWand.h>++-- | MagickGetImageHeight() returns the image height.+foreign import ccall "MagickGetImageHeight" magickGetImageHeight+ :: Ptr MagickWand -> IO CSize++-- | MagickGetImageWidth() returns the image width.+foreign import ccall "MagickGetImageWidth" magickGetImageWidth+ :: Ptr MagickWand -> IO CSize++-- | MagickGetImagePixelColor() returns the color of the specified pixel.+foreign import ccall "MagickGetImagePixelColor" magickGetImagePixelColor+ :: Ptr MagickWand+ -> CSize -- ^ pixel x coordinate+ -> CSize -- ^ pixel y coordinate+ -> Ptr PixelWand -- ^ return the colormap color in this wand+ -> IO MagickBooleanType++-- | MagickGetImageCompressionQuality() gets the image compression quality.+foreign import ccall "MagickGetImageCompressionQuality" magickGetImageCompressionQuality+ :: Ptr MagickWand -> IO CSize++-- | MagickSetImageCompression() sets the image compression.+foreign import ccall "MagickSetImageCompression" magickSetImageCompression+ :: Ptr MagickWand -> CompressionType -> IO MagickBooleanType++-- | MagickSetImageCompressionQuality() sets the image compression quality.+foreign import ccall "MagickSetImageCompressionQuality" magickSetImageCompressionQuality+ :: Ptr MagickWand -> CSize -> IO MagickBooleanType++-- | MagickGetImageBackgroundColor() returns the image background color.+foreign import ccall "MagickGetImageBackgroundColor" magickGetImageBackgroundColor+ :: Ptr MagickWand -> Ptr PixelWand -> IO MagickBooleanType++-- | MagickSetImageBackgroundColor() sets the image background color.+foreign import ccall "MagickSetImageBackgroundColor" magickSetImageBackgroundColor+ :: Ptr MagickWand -> Ptr PixelWand -> IO MagickBooleanType++-- | MagickExtentImage() extends the image as defined by the geometry, gravity,+-- and wand background color. Set the (x,y) offset of the geometry to move the+-- original wand relative to the extended wand.+foreign import ccall "MagickExtentImage" magickExtentImage+ :: Ptr MagickWand -- ^ wand+ -> CSize -- ^ width+ -> CSize -- ^ height+ -> CSize -- ^ x offset+ -> CSize -- ^ y offset+ -> IO MagickBooleanType++-- | MagickFloodfillPaintImage() changes the color value of any pixel+-- that matches target and is an immediate neighbor. If the method FillToBorderMethod+-- is specified, the color value is changed for any neighbor pixel that does+-- not match the bordercolor member of image.+foreign import ccall "MagickFloodfillPaintImage" magickFloodfillPaintImage+ :: Ptr MagickWand -- ^ wand+ -> ChannelType -- ^ channel+ -> Ptr PixelWand -- ^ fill+ -> CDouble -- ^ fuzz+ -> Ptr PixelWand -- ^ bordercolor+ -> CSize -- ^ x offset+ -> CSize -- ^ y offset+ -> MagickBooleanType -- ^ invert+ -> IO MagickBooleanType++-- | MagickNegateImage() negates the colors in the reference image.+-- The Grayscale option means that only grayscale values within the image are negated.+-- You can also reduce the influence of a particular channel with a gamma value of 0.+foreign import ccall "MagickNegateImage" magickNegateImage+ :: Ptr MagickWand+ -> MagickBooleanType -- ^ negate gray+ -> IO MagickBooleanType++foreign import ccall "MagickNegateImageChannel" magickNegateImageChannel+ :: Ptr MagickWand+ -> ChannelType+ -> MagickBooleanType -- ^ negate gray+ -> IO MagickBooleanType++-- | MagickGetImageClipMask() gets the image clip mask at the current image index.+foreign import ccall "MagickGetImageClipMask" magickGetImageClipMask+ :: Ptr MagickWand+ -> IO (Ptr MagickWand)++-- | MagickSetImageClipMask() sets image clip mask.+foreign import ccall "MagickSetImageClipMask" magickSetImageClipMask+ :: Ptr MagickWand+ -> Ptr MagickWand+ -> IO MagickBooleanType++-- | MagickCompositeImage() composite one image onto another at the specified offset.+foreign import ccall "MagickCompositeImage" magickCompositeImage+ :: Ptr MagickWand+ -> Ptr MagickWand -- ^ source+ -> CompositeOperator+ -> CSize -- ^ column offset+ -> CSize -- ^ row offset+ -> IO MagickBooleanType++foreign import ccall "MagickCompositeImage" magickCompositeImageChannel+ :: Ptr MagickWand+ -> Ptr MagickWand -- ^ source+ -> ChannelType+ -> CompositeOperator+ -> CSize -- ^ column offset+ -> CSize -- ^ row offset+ -> IO MagickBooleanType++-- | MagickTransparentPaintImage() changes any pixel that matches color with the color defined by fill.+foreign import ccall "MagickTransparentPaintImage" magickTransparentPaintImage+ :: Ptr MagickWand+ -> Ptr PixelWand -- ^ change this color to specified opacity value withing the image+ -> Double -- ^ the level of transarency: 1.0 fully opaque 0.0 fully transparent+ -> Double -- ^ By default target must match a particular pixel color exactly.+ -- However, in many cases two colors may differ by a small amount.+ -- The fuzz member of image defines how much tolerance is acceptable+ -- to consider two colors as the same. For example, set fuzz to 10 and+ -- the color red at intensities of 100 and 102 respectively are now+ -- interpreted as the same color for the purposes of the floodfill.+ -> MagickBooleanType -- paint any pixel that does not match the target color.+ -> IO MagickBooleanType++-- | MagickBorderImage() surrounds the image with a border of the color+-- defined by the bordercolor pixel wand.+foreign import ccall "MagickBorderImage" magickBorderImage+ :: Ptr MagickWand -- ^ wand+ -> Ptr PixelWand -- ^ bordercolor+ -> CSize -- ^ width+ -> CSize -- ^ height+ -> IO MagickBooleanType++-- | MagickShaveImage() shaves pixels from the image edges. It allocates+-- the memory necessary for the new Image structure and returns a pointer+-- to the new image.+foreign import ccall "MagickShaveImage" magickShaveImage+ :: Ptr MagickWand -- ^ wand+ -> CSize -- ^ columns+ -> CSize -- ^ rows+ -> IO MagickBooleanType++-- | MagickSetImageAlphaChannel() activates, deactivates, resets, or+-- sets the alpha channel.+foreign import ccall "MagickSetImageAlphaChannel" magickSetImageAlphaChannel+ :: Ptr MagickWand -- ^ wand+ -> AlphaChannelType -- ^ alpha_type+ -> IO MagickBooleanType++-- | MagickNewImage() adds a blank image canvas of the specified size and background color to the wand.+foreign import ccall "MagickNewImage" magickNewImage+ :: Ptr MagickWand+ -> CSize -- ^ width+ -> CSize -- ^ height+ -> Ptr PixelWand -- ^ background color+ -> IO MagickBooleanType++-- | MagickDrawImage() renders the drawing wand on the current image.+foreign import ccall "MagickDrawImage" magickDrawImage+ :: Ptr MagickWand -> Ptr DrawingWand -> IO MagickBooleanType++-- | MagickFlopImage() creates a horizontal mirror image by reflecting the pixels around the central y-axis.+foreign import ccall "MagickFlopImage" magickFlopImage+ :: Ptr MagickWand -> IO MagickBooleanType+++-- | MagickAddNoiseImage() adds random noise to the image.+-- The type of noise: Uniform, Gaussian, Multiplicative, Impulse, Laplacian, or Poisson.+foreign import ccall "MagickAddNoiseImage" magickAddNoiseImage+ :: Ptr MagickWand -> NoiseType -> IO MagickBooleanType++-- | MagickAddImage() adds a clone of the images from the second wand and inserts them into the first wand.+-- Use MagickSetLastIterator(), to append new images into an existing wand, current image will be set to+-- last image so later adds with also be appened to end of wand.+--+-- Use MagickSetFirstIterator() to prepend new images into wand, any more images added will also be prepended+-- before other images in the wand. However the order of a list of new images will not change.+--+-- Otherwise the new images will be inserted just after the current image, and any later image will also be+-- added after this current image but before the previously added images. Caution is advised when multiple+-- image adds are inserted into the middle of the wand image list.+foreign import ccall "MagickAddImage" magickAddImage+ :: Ptr MagickWand -> Ptr MagickWand -> IO MagickBooleanType++-- | MagickFlipImage() creates a vertical mirror image by reflecting the pixels around the central x-axis.+foreign import ccall "MagickFlipImage" magickFlipImage+ :: Ptr MagickWand -> IO MagickBooleanType++-- | MagickSetImageVirtualPixelMethod() sets the image virtual pixel method.+-- the image virtual pixel method : UndefinedVirtualPixelMethod, ConstantVirtualPixelMethod,+-- EdgeVirtualPixelMethod, MirrorVirtualPixelMethod, or TileVirtualPixelMethod.+foreign import ccall "MagickSetImageVirtualPixelMethod" magickSetVirtualPixelMethod+ :: Ptr MagickWand -> VirtualPixelMethod -> IO VirtualPixelMethod++-- | MagickAppendImages() append the images in a wand from the current image onwards,+-- creating a new wand with the single image result. This is affected by the gravity+-- and background settings of the first image.+-- Typically you would call either MagickResetIterator() or MagickSetFirstImage() before+-- calling this function to ensure that all the images in the wand's image list will be appended together.+foreign import ccall "MagickAppendImages" magickAppendImages+ :: Ptr MagickWand -> MagickBooleanType -> IO (Ptr MagickWand)++-- | MagickReadImage() reads an image or image sequence. The images are inserted at+-- the current image pointer position. Use MagickSetFirstIterator(), MagickSetLastIterator,+-- or MagickSetImageIndex() to specify the current image pointer position at the beginning+-- of the image list, the end, or anywhere in-between respectively.+foreign import ccall "MagickReadImage" magickReadImage+ :: Ptr MagickWand -> CString -> IO MagickBooleanType++-- | MagickReadImageBlob() reads an image or image sequence from a blob.+foreign import ccall "MagickReadImageBlob" magickReadImageBlob+ :: Ptr MagickWand -> Ptr () -> CSize -> IO MagickBooleanType++-- | MagickWriteImage() writes an image to the specified filename. If the filename+-- parameter is NULL, the image is written to the filename set by MagickReadImage()+-- or MagickSetImageFilename().+foreign import ccall "MagickWriteImage" magickWriteImage+ :: Ptr MagickWand -> CString -> IO (MagickBooleanType)++-- | MagickBlurImage() blurs an image. We convolve the image with a gaussian+-- operator of the given radius and standard deviation (sigma). For reasonable+-- results, the radius should be larger than sigma. Use a radius of 0 and+-- BlurImage() selects a suitable radius for you.+--+-- The format of the MagickBlurImage method is:+foreign import ccall "MagickBlurImage" magickBlurImage+ :: Ptr MagickWand -> CDouble -> CDouble -> IO MagickBooleanType++foreign import ccall "MagickBlurImageChannel" magickBlurImageChannel+ :: Ptr MagickWand -> ChannelType -> CDouble -> CDouble -> IO MagickBooleanType++-- | MagickNormalizeImage() enhances the contrast of a color image by adjusting+-- the pixels color to span the entire range of colors available+--+-- You can also reduce the influence of a particular channel with a gamma+-- value of 0.+foreign import ccall "MagickNormalizeImage" magickNormalizeImage+ :: Ptr MagickWand -> IO MagickBooleanType++foreign import ccall "MagickNormalizeImageChannel" magickNormalizeImageChannel+ :: Ptr MagickWand -> ChannelType -> IO MagickBooleanType++-- | MagickShadowImage() simulates an image shadow.+foreign import ccall "MagickShadowImage" magickShadowImage+ :: Ptr MagickWand+ -> CDouble -- ^ percentage transparency+ -> CDouble -- ^ the standard deviation of the Gaussian, in pixels+ -> CSize -- ^ the shadow x-offset+ -> CSize -- ^ the shadow y-offset+ -> IO MagickBooleanType++-- | MagickTrimImage() remove edges that are the background color from the image.+foreign import ccall "MagickTrimImage" magickTrimImage+ :: Ptr MagickWand -> CDouble -> IO MagickBooleanType++-- | MagickResetImagePage() resets the Wand page canvas and position.+foreign import ccall "MagickResetImagePage" magickResetImagePage+ :: Ptr MagickWand -> CString -> IO MagickBooleanType++-- | MagickDistortImage() distorts an image using various distortion methods,+-- by mapping color lookups of the source image to a new destination image usally+-- of the same size as the source image, unless 'bestfit' is set to true.+-- If 'bestfit' is enabled, and distortion allows it, the destination image+-- is adjusted to ensure the whole source 'image' will just fit within the final+-- destination image, which will be sized and offset accordingly. Also in many cases+-- the virtual offset of the source image will be taken into account in the mapping.+foreign import ccall "MagickDistortImage" magickDistortImage+ :: Ptr MagickWand+ -> DistortImageMethod -- ^ the method of image distortion+ -> CSize -- ^ the number of arguments given for this distortion method+ -> Ptr CDouble -- ^ the arguments for this distortion method+ -> MagickBooleanType -- ^ attempt to resize destination to fit distorted source+ -> IO MagickBooleanType++-- | MagickShadeImage() shines a distant light on an image to create+-- a three-dimensional effect. You control the positioning of the light+-- with azimuth and elevation; azimuth is measured in degrees off the x axis+-- and elevation is measured in pixels above the Z axis.+foreign import ccall "MagickShadeImage" magickShadeImage+ :: Ptr MagickWand+ -> MagickBooleanType -- ^ a value other than zero shades the intensity of each pixel+ -> CDouble -- ^ azimuth of the light source direction+ -> CDouble -- ^ evelation of the light source direction+ -> IO MagickBooleanType++-- | MagickColorizeImage() blends the fill color with each pixel in the image.+foreign import ccall "MagickColorizeImage" magickColorizeImage+ :: Ptr MagickWand+ -> Ptr PixelWand -- ^ the colorize pixel wand+ -> Ptr PixelWand -- ^ the opacity pixel wand+ -> IO MagickBooleanType++-- | MagickFxImage() evaluate expression for each pixel in the image.+foreign import ccall "MagickFxImage" magickFxImage+ :: Ptr MagickWand+ -> CString -- ^ the expression+ -> IO (Ptr MagickWand)++-- | MagickFxImageChannel() evaluate expression for each pixel in the image.+foreign import ccall "MagickFxImageChannel" magickFxImageChannel+ :: Ptr MagickWand+ -> ChannelType -- ^ the image channel(s)+ -> CString -- ^ the expression+ -> IO (Ptr MagickWand)++-- | MagickSigmoidalContrastImage() adjusts the contrast of an image with a+-- non-linear sigmoidal contrast algorithm. Increase the contrast of the image+-- using a sigmoidal transfer function without saturating highlights or shadows.+-- Contrast indicates how much to increase the contrast (0 is none; 3 is typical;+-- 20 is pushing it); mid-point indicates where midtones fall in the resultant+-- image (0 is white; 50 is middle-gray; 100 is black). Set sharpen to `True`+-- to increase the image contrast otherwise the contrast is reduced.+foreign import ccall "MagickSigmoidalContrastImage" magickSigmoidalContrastImage+ :: Ptr MagickWand+ -> MagickBooleanType -- ^ increase or decrease image contrast+ -> CDouble -- ^ strength of the contrast, the larger the number the more 'threshold-like' it becomes+ -> CDouble -- ^ midpoint of the function as a color value 0 to `quantumRange`+ -> IO MagickBooleanType++-- | see `magickSigmoidalContrastImage`+foreign import ccall "MagickSigmoidalContrastImageChannel" magickSigmoidalContrastImageChannel+ :: Ptr MagickWand+ -> ChannelType -- ^ identify which channel to level: `redChannel`, `greenChannel`+ -> MagickBooleanType -- ^ increase or decrease image contrast+ -> CDouble -- ^ strength of the contrast, the larger the number the more 'threshold-like' it becomes+ -> CDouble -- ^ midpoint of the function as a color value 0 to `quantumRange`+ -> IO MagickBooleanType++-- | MagickEvaluateImage() applies an arithmetic, relational, or logical+-- expression to an image. Use these operators to lighten or darken an image,+-- to increase or decrease contrast in an image, or to produce the "negative"+-- of an image.+foreign import ccall "MagickEvaluateImage" magickEvaluateImage+ :: Ptr MagickWand+ -> MagickEvaluateOperator -- ^ a channel operator+ -> CDouble -- ^ value+ -> IO MagickBooleanType++-- | see `magickEvaluateImage`+foreign import ccall "MagickEvaluateImages" magickEvaluateImages+ :: Ptr MagickWand+ -> MagickEvaluateOperator -- ^ a channel operator+ -> IO MagickBooleanType++-- | see `magickEvaluateImage`+foreign import ccall "MagickEvaluateImageChannel" magickEvaluateImageChannel+ :: Ptr MagickWand+ -> ChannelType -- ^ the channel(s)+ -> MagickEvaluateOperator -- ^ a channel operator+ -> CDouble -- ^ value+ -> IO MagickBooleanType++-- | MagickRollImage() offsets an image as defined by x and y.+foreign import ccall "MagickRollImage" magickRollImage+ :: Ptr MagickWand+ -> CDouble -- ^ the x offset+ -> CDouble -- ^ the y offset+ -> IO MagickBooleanType++-- | MagickAnnotateImage() annotates an image with text.+foreign import ccall "MagickAnnotateImage" magickAnnotateImage+ :: Ptr MagickWand+ -> Ptr DrawingWand -- ^ the draw wand+ -> CDouble -- ^ x ordinate to left of text+ -> CDouble -- ^ y ordinate to text baseline+ -> CDouble -- ^ rotate text relative to this angle+ -> CString -- ^ text to draw+ -> IO MagickBooleanType++-- | MagickMergeImageLayers() composes all the image layers from the current+-- given image onward to produce a single image of the merged layers.+-- The inital canvas's size depends on the given ImageLayerMethod, and is+-- initialized using the first images background color. The images are then+-- compositied onto that image in sequence using the given composition that+-- has been assigned to each individual image.+foreign import ccall "MagickMergeImageLayers" magickMergeImageLayers+ :: Ptr MagickWand+ -> ImageLayerMethod -- ^ the method of selecting the size of the initial canvas+ -> IO (Ptr MagickWand)++-- | MagickTintImage() applies a color vector to each pixel in the image. The+-- length of the vector is 0 for black and white and at its maximum for the+-- midtones. The vector weighting function is f(x)=(1-(4.0*((x-0.5)*(x-0.5)))).+foreign import ccall "MagickTintImage" magickTintImage+ :: Ptr MagickWand+ -> Ptr PixelWand -- ^ the tint pixel wand.+ -> Ptr PixelWand -- ^ opacity pixel wand+ -> IO MagickBooleanType+++-- | MagickSetImageMatte() sets the image matte channel.+foreign import ccall "MagickSetImageMatte" magickSetImageMatte+ :: Ptr MagickWand+ -> MagickBooleanType+ -> IO MagickBooleanType++-- | MagickCropImage() extracts a region of the image.+foreign import ccall "MagickCropImage" magickCropImage+ :: Ptr MagickWand+ -> CSize -- ^ the region width+ -> CSize -- ^ the region height+ -> CSize -- ^ the region x-offset+ -> CSize -- ^ the region y-offset+ -> IO MagickBooleanType++-- | MagickShearImage() slides one edge of an image along the X or Y axis,+-- creating a parallelogram. An X direction shear slides an edge along the X axis,+-- while a Y direction shear slides an edge along the Y axis. The amount of+-- the shear is controlled by a shear angle. For X direction shears, x_shear is+-- measured relative to the Y axis, and similarly, for Y direction shears y_shear+-- is measured relative to the X axis. Empty triangles left over from shearing+-- the image are filled with the background color.+foreign import ccall "MagickShearImage" magickShearImage+ :: Ptr MagickWand+ -> Ptr PixelWand -- ^ the background pixel wand+ -> CDouble -- ^ the number of degrees to shear the image+ -> CDouble -- ^ the number of degrees to shear the image+ -> IO MagickBooleanType++-- | MagickScaleImage() scales the size of an image to the given dimensions.+foreign import ccall "MagickScaleImage" magickScaleImage+ :: Ptr MagickWand+ -> CSize -- ^ the number of columns in the scaled image+ -> CSize -- ^ the number of rows in the scaled image+ -> IO MagickBooleanType++-- | MagickSparseColorImage(), given a set of coordinates, interpolates the+-- colors found at those coordinates, across the whole image, using various methods.+--+-- The format of the MagickSparseColorImage method is:+-- ArcSparseColorion will always ignore source image offset, and always 'bestfit'+-- the destination image with the top left corner offset relative to the polar mapping center.+--+-- Bilinear has no simple inverse mapping so will not allow 'bestfit' style of image sparseion.+--+-- Affine, Perspective, and Bilinear, will do least squares fitting of the distrotion when more+-- than the minimum number of control point pairs are provided.+--+-- Perspective, and Bilinear, will fall back to a Affine sparseion when less than 4 control+-- point pairs are provided. While Affine sparseions will let you use any number of control+-- point pairs, that is Zero pairs is a No-Op (viewport only) distrotion, one pair is a+-- translation and two pairs of control points will do a scale-rotate-translate, without any+-- shearing.+foreign import ccall "MagickSparseColorImage" magickSparseColorImage+ :: Ptr MagickWand+ -> ChannelType+ -> SparseColorMethod+ -> CSize+ -> Ptr Double+ -> IO MagickBooleanType++-- | MagickFunctionImage() applys an arithmetic, relational, or logical expression to an image.+-- Use these operators to lighten or darken an image, to increase or decrease contrast in an+-- image, or to produce the "negative" of an image.+foreign import ccall "MagickFunctionImage" magickFunctionImage+ :: Ptr MagickWand+ -> MagickFunction+ -> CSize+ -> Ptr Double+ -> IO MagickBooleanType++foreign import ccall "MagickFunctionImageChannel" magickFunctionImageChannel+ :: Ptr MagickWand+ -> ChannelType+ -> MagickFunction+ -> CSize+ -> Ptr Double+ -> IO MagickBooleanType++-- | MagickCoalesceImages() composites a set of images while respecting+-- any page offsets and disposal methods. GIF, MIFF, and MNG animation+-- sequences typically start with an image background and each subsequent+-- image varies in size and offset. MagickCoalesceImages() returns a new+-- sequence where each image in the sequence is the same size as the+-- first and composited with the next image in the sequence.+foreign import ccall "MagickCoalesceImages" magickCoalesceImages+ :: Ptr MagickWand+ -> IO (Ptr MagickWand)++-- | MagickGetNumberImages() returns the number of images associated+-- with a magick wand.+foreign import ccall "MagickGetNumberImages" magickGetNumberImages+ :: Ptr MagickWand+ -> IO CSize++-- | MagickGetImage() gets the image at the current image index.+foreign import ccall "MagickGetImage" magickGetImage+ :: Ptr MagickWand+ -> IO (Ptr MagickWand)++-- | MagickCompareImageLayers() compares each image with the next in+-- a sequence and returns the maximum bounding region of any pixel+-- differences it discovers.+foreign import ccall "MagickCompareImageLayers" magickCompareImageLayers+ :: Ptr MagickWand+ -> ImageLayerMethod+ -> IO (Ptr MagickWand)++-- | MagickGetImageScene() gets the image scene+foreign import ccall "MagickGetImageScene" magickGetImageScene+ :: Ptr MagickWand -> IO CSize++-- | MagickRemoveImage() removes an image from the image list.+foreign import ccall "MagickRemoveImage" magickRemoveImage+ :: Ptr MagickWand -> IO MagickBooleanType++-- | MagickSetImage() replaces the last image returned by MagickSetImageIndex(),+-- MagickNextImage(), MagickPreviousImage() with the images from the specified+-- wand.+foreign import ccall "MagickSetImage" magickSetImage+ :: Ptr MagickWand -> Ptr MagickWand -> IO MagickBooleanType++-- | MagickImportImagePixels() accepts pixel data and stores it in the image at+-- the location you specify. The method returns MagickFalse on success otherwise+-- MagickTrue if an error is encountered. The pixel data can be either char,+-- short int, int, ssize_t, float, or double in the order specified by map.+--+-- Suppose your want to upload the first scanline of a 640x480 image from+-- character data in red-green-blue order:+-- magickImportImagePixels wand 0 0 640 1 "RGB" charPixel pixels+foreign import ccall "MagickImportImagePixels" magickImportImagePixels+ :: Ptr MagickWand+ -> CSize -- ^ x+ -> CSize -- ^ y+ -> CSize -- ^ width+ -> CSize -- ^ height+ -> CString -- ^ this string reflects the expected ordering of the pixel array.+ -- It can be any combination or order of R = red, G = green, B = blue, A = alpha+ -- (0 is transparent), O = opacity (0 is opaque), C = cyan, Y = yellow, M = magenta,+ -- K = black, I = intensity (for grayscale), P = pad.+ -> StorageType -- define the data type of the pixels. Float and double types are expected+ -- to be normalized [0..1] otherwise [0..QuantumRange]. Choose from these+ -- types: CharPixel, ShortPixel, IntegerPixel, LongPixel, FloatPixel, or DoublePixel.+ -> Ptr () -- ^ This array of values contain the pixel components as defined by map and type.+ -- You must preallocate this array where the expected length varies depending on+ -- the values of width, height, map, and type+ -> IO MagickBooleanType++-- | MagickExportImagePixels() extracts pixel data from an image and returns it+-- to you. The method returns MagickTrue on success otherwise MagickFalse if an+-- error is encountered. The data is returned as char, short int, int, ssize_t,+-- float, or double in the order specified by map.+foreign import ccall "MagickExportImagePixels" magickExportImagePixels+ :: Ptr MagickWand+ -> CSize -- ^ x+ -> CSize -- ^ y+ -> CSize -- ^ width+ -> CSize -- ^ height+ -> CString -- ^ this string reflects the expected ordering of the pixel array.+ -- It can be any combination or order of R = red, G = green, B = blue, A = alpha+ -- (0 is transparent), O = opacity (0 is opaque), C = cyan, Y = yellow, M = magenta,+ -- K = black, I = intensity (for grayscale), P = pad.+ -> StorageType -- define the data type of the pixels. Float and double types are expected+ -- to be normalized [0..1] otherwise [0..QuantumRange]. Choose from these+ -- types: CharPixel, ShortPixel, IntegerPixel, LongPixel, FloatPixel, or DoublePixel.+ -> Ptr () -- ^ This array of values contain the pixel components as defined by map and type.+ -- You must preallocate this array where the expected length varies depending on+ -- the values of width, height, map, and type+ -> IO MagickBooleanType++-- | MagickRotateImage() rotates an image the specified number of degrees.+-- Empty triangles left over from rotating the image are filled with the+-- background color.+foreign import ccall "MagickRotateImage" magickRotateImage+ :: Ptr MagickWand -> Ptr PixelWand -> CDouble -> IO MagickBooleanType++-- | MagickSetImageDepth() sets the image depth.+foreign import ccall "MagickSetImageDepth" magickSetImageDepth+ :: Ptr MagickWand -> CSize -> IO MagickBooleanType++-- | MagickSetImageDelay() sets the image delay.+foreign import ccall "MagickSetImageDelay" magickSetImageDelay+ :: Ptr MagickWand -> CSize -> IO MagickBooleanType++-- | MagickGetImageDelay() gets the image delay.+foreign import ccall "MagickGetImageDelay" magickGetImageDelay+ :: Ptr MagickWand -> IO CSize++-- | MagickGetImageBlob() implements direct to memory image formats.+-- It returns the image as a blob (a formatted "file" in memory) and+-- its length, starting from the current position in the image sequence.+-- Use MagickSetImageFormat() to set the format to write to the blob (GIF, JPEG, PNG, etc.).+-- Utilize MagickResetIterator() to ensure the write is from the beginning of the image sequence.+-- Use MagickRelinquishMemory() to free the blob when you are done with it.+-- The format of the MagickGetImageBlob method is:+foreign import ccall "MagickGetImageBlob" magickGetImageBlob+ :: Ptr MagickWand -> Ptr CSize -> IO (Ptr CChar)++-- | MagickGetImageDepth() gets the image depth.+foreign import ccall "MagickGetImageDepth" magickGetImageDepth+ :: Ptr MagickWand -> IO CSize++-- | MagickGetImageFormat() returns the format of a particular image in a sequence.+foreign import ccall "MagickGetImageFormat" magickGetImageFormat+ :: Ptr MagickWand -> IO CString++-- | MagickSetImageFormat() sets the format of a particular image in a sequence.+foreign import ccall "MagickSetImageFormat" magickSetImageFormat+ :: Ptr MagickWand -> CString -> IO MagickBooleanType++-- | MagickStripImage() strips an image of all profiles and comments.+foreign import ccall "MagickStripImage" magickStripImage+ :: Ptr MagickWand -> IO MagickBooleanType++-- | MagickGetImageSignature() generates an SHA-256 message digest for the image pixel stream.+foreign import ccall "MagickGetImageSignature" magickGetImageSignature+ :: Ptr MagickWand -> IO CString++-- | MagickGetImageAlphaChannel() returns MagickFalse if the image alpha+-- channel is not activated. That is, the image is RGB rather than RGBA+-- or CMYK rather than CMYKA.+foreign import ccall "MagickGetImageAlphaChannel" magickGetImageAlphaChannel+ :: Ptr MagickWand -> IO MagickBooleanType++-- | MagickSetImageType() sets the image type.+foreign import ccall "MagickSetImageType" magickSetImageType+ :: Ptr MagickWand -> ImageType -> IO MagickBooleanType
+ Graphics/ImageMagick/MagickWand/FFI/WandProperties.hsc view
@@ -0,0 +1,136 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.ImageMagick.MagickWand.FFI.WandProperties+ where++import Foreign+import Foreign.C.String+import Foreign.C.Types++import Graphics.ImageMagick.MagickWand.FFI.Types+++foreign import ccall "MagickDeleteOption" magickDeleteOption+ :: Ptr MagickWand+ -> CString -- ^ the key+ -> IO MagickBooleanType++-- | MagickGetOption() returns a value associated with a wand+-- and the specified key. Use MagickRelinquishMemory() to free+-- the value when you are finished with it.+foreign import ccall "MagickGetOption" magickGetOption+ :: Ptr MagickWand+ -> CString -- ^ the key+ -> IO CString++-- | MagickSetOption() associates one or options with the wand+-- (e.g. MagickSetOption(wand,"jpeg:perserve","yes")).+foreign import ccall "MagickSetOption" magickSetOption+ :: Ptr MagickWand+ -> CString -- ^ the key+ -> CString -- ^ the value+ -> IO MagickBooleanType++-- | MagickGetOptions() returns all the option names that match the+-- specified pattern associated with a wand. Use MagickGetOption()+-- to return the value of a particular option. Use MagickRelinquishMemory()+-- to free the value when you are finished with it.+foreign import ccall "MagickGetOptions" magickGetOptions+ :: Ptr MagickWand+ -> CString -- ^ the pattern+ -> Ptr CSize+ -> IO (Ptr CString)++-- | MagickDeleteImageProperty() deletes a wand property.+foreign import ccall "MagickDeleteImageProperty" magickDeleteImageProperty+ :: Ptr MagickWand+ -> CString -- ^ the property+ -> IO MagickBooleanType++-- | MagickGetImageProperty() returns a value associated with the+-- specified property. Use MagickRelinquishMemory() to free the value+-- when you are finished with it.+foreign import ccall "MagickGetImageProperty" magickGetImageProperty+ :: Ptr MagickWand+ -> CString -- ^ the property+ -> IO CString++-- | MagickGetImageProperties() returns all the property names that+-- match the specified pattern associated with a wand. Use+-- MagickGetImageProperty() to return the value of a particular property.+-- Use MagickRelinquishMemory() to free the value when you are finished+-- with it.+foreign import ccall "MagickGetImageProperties" magickGetImageProperties+ :: Ptr MagickWand+ -> CString -- ^ the pattern+ -> Ptr CSize+ -> IO (Ptr CString)++-- | MagickSetImageProperty() associates a property with an image.+foreign import ccall "MagickSetImageProperty" magickSetImageProperty+ :: Ptr MagickWand+ -> CString -- ^ the property+ -> CString -- ^ the value+ -> IO MagickBooleanType++-- | MagickGetImageProfile() returns the named image profile.+foreign import ccall "MagickGetImageProfile" magickGetImageProfile+ :: Ptr MagickWand+ -> CString -- ^ the profile name+ -> Ptr CSize -- ^ the profile length+ -> IO (Ptr Word8)++-- | MagickRemoveImageProfile() removes the named image profile and+-- returns it.+foreign import ccall "MagickRemoveImageProfile" magickRemoveImageProfile+ :: Ptr MagickWand+ -> CString -- ^ the profile name+ -> Ptr CSize -- ^ the profile length+ -> IO (Ptr Word8)++-- | MagickSetImageProfile() adds a named profile to the magick wand.+-- If a profile with the same name already exists, it is replaced.+-- This method differs from the MagickProfileImage() method in that+-- it does not apply any CMS color profiles.+foreign import ccall "MagickSetImageProfile" magickSetImageProfile+ :: Ptr MagickWand+ -> CString -- ^ the profile name+ -> Ptr Word8 -- ^ the profile+ -> CSize -- ^ the profile length+ -> IO MagickBooleanType++-- | MagickGetImageProfiles() returns all the profile names that match+-- the specified pattern associated with a wand. Use+-- MagickGetImageProfile() to return the value of a particular property.+-- Use MagickRelinquishMemory() to free the value when you are finished+-- with it.+foreign import ccall "MagickGetImageProfiles" magickGetImageProfiles+ :: Ptr MagickWand+ -> CString -- ^ the pattern+ -> Ptr CSize+ -> IO (Ptr CString)++-- | MagickSetResolution() sets the image resolution.+foreign import ccall "MagickSetImageResolution" magickSetImageResolution+ :: Ptr MagickWand+ -> CDouble -- ^ x resolution+ -> CDouble -- ^ y resolution+ -> IO MagickBooleanType++-- | MagickGetResolution() gets the image resolution.+foreign import ccall "MagickGetImageResolution" magickGetImageResolution+ :: Ptr MagickWand+ -> Ptr CDouble -- ^ x resolution+ -> Ptr CDouble -- ^ y resolution+ -> IO MagickBooleanType++-- | MagickGetImageArtifacts() returns all the artifact names+-- that match the specified pattern associated with a wand.+-- Use MagickGetImageProperty() to return the value of a+-- particular artifact. Use MagickRelinquishMemory() to free+-- the value when you are finished with it.+foreign import ccall "MagickGetImageArtifacts" magickGetImageArtifacts+ :: Ptr MagickWand+ -> CString -- ^ the pattern+ -> Ptr CSize+ -> IO (Ptr CString)
+ LICENSE view
@@ -0,0 +1,103 @@+Before we get to the text of the license, lets just review what the license says in simple terms:++It allows you to:++ * freely download and use ImageMagick software, in whole or in part, for personal, company internal, or commercial purposes;+ * use ImageMagick software in packages or distributions that you create;+ * link against a library under a different license;+ * link code under a different license against a library under this license;+ * merge code into a work under a different license;+ * extend patent grants to any code using code under this license;+ * and extend patent protection.++It forbids you to:++ * redistribute any piece of ImageMagick-originated software without proper attribution;+ * use any marks owned by ImageMagick Studio LLC in any way that might state or imply that ImageMagick Studio LLC endorses your distribution;+ * use any marks owned by ImageMagick Studio LLC in any way that might state or imply that you created the ImageMagick software in question.++It requires you to:++ * include a copy of the license in any redistribution you may make that includes ImageMagick software;+ * provide clear attribution to ImageMagick Studio LLC for any distributions that include ImageMagick software.++It does not require you to:++ * include the source of the ImageMagick software itself, or of any modifications you may have made to it, in any redistribution you may assemble that includes it;+ * submit changes that you make to the software back to the ImageMagick Studio LLC (though such feedback is encouraged).++A few other clarifications include:++ * ImageMagick is freely available without charge;+ * you may include ImageMagick on a DVD as long as you comply with the terms of the license;+ * you can give modified code away for free or sell it under the terms of the ImageMagick license or distribute the result under a different license, but you need to acknowledge the use of the ImageMagick software;+ * the license is compatible with the GPL V3.+ * when exporting the ImageMagick software, review its export classification.++Terms and Conditions for Use, Reproduction, and Distribution++The legally binding and authoritative terms and conditions for use, reproduction, and distribution of ImageMagick follow:++Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization dedicated to making software imaging solutions freely available.++1. Definitions.++License shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.++Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.++Legal Entity shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, control means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.++You (or Your) shall mean an individual or Legal Entity exercising permissions granted by this License.++Source form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.++Object form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.++Work shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).++Derivative Works shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.++Contribution shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as Not a Contribution.++Contributor shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.++2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.++3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.++4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:++ * You must give any other recipients of the Work or Derivative Works a copy of this License; and+ * You must cause any modified files to carry prominent notices stating that You changed the files; and+ * You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and+ * If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.+You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.++5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.++6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.++7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.++8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.++9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.++How to Apply the License to your Work++To apply the ImageMagick License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information (don't include the brackets). The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.++ Copyright [yyyy] [name of copyright owner]++ Licensed under the ImageMagick License (the "License"); you may not use+ this file except in compliance with the License. You may obtain a copy+ of the License at++ http://www.imagemagick.org/script/license.php++ Unless required by applicable law or agreed to in writing, software+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the+ License for the specific language governing permissions and limitations+ under the License.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ examples/3dlogo.hs view
@@ -0,0 +1,217 @@+{-# LANGUAGE OverloadedStrings #-}+-- http://members.shaw.ca/el.supremo/MagickWand/3dlogo.htm++-- Better 3-D Logo Generation example+-- http://www.imagemagick.org/Usage/advanced/#3d-logos-2++import Graphics.ImageMagick.MagickWand+++main :: IO ()+main = do+ withMagickWandGenesis $ do+ localGenesis $ do+ {-+ convert -size 170x100 xc:black \+ -fill white -draw 'circle 50,50 13,50' \+ -draw 'circle 120,50 157,50' \+ -draw 'rectangle 50,13 120,87' \+ -fill black -draw 'circle 50,50 25,50' \+ -draw 'circle 120,50 145,50' \+ -draw 'rectangle 50,25 120,75' \+ -fill white -draw 'circle 60,50 40,50' \+ -draw 'circle 110,50 130,50' \+ -draw 'rectangle 60,30 110,70' \+ -gaussian 1x1 +matte logo_mask.png+ -}++ (_,mw) <- magickWand+ pw <- pixelWand+ (_,dw) <- drawingWand++ setSize mw 170 100+ mw `readImage` "xc:black"++ pw `setColor` "white"+ dw `setFillColor` pw++ drawCircle dw 50 50 13 50+ drawCircle dw 120 50 157 50+ drawRectangle dw 50 13 120 87++ pw `setColor` "black"++ dw `setFillColor` pw+ drawCircle dw 50 50 25 50+ drawCircle dw 50 50 25 50+ drawCircle dw 120 50 145 50+ drawRectangle dw 50 25 120 75++ pw `setColor` "white"+ dw `setFillColor` pw+ drawCircle dw 60 50 40 50+ drawCircle dw 110 50 130 50+ drawRectangle dw 60 30 110 70++ -- Now we draw the Drawing wand on to the Magick Wand+ mw `drawImage` dw++ gaussianBlurImage mw 1 1+ -- Turn the matte of == +matte+ mw `setImageMatte` False++ mw `writeImage` (Just "logo_mask.png")++ localGenesis $ do++ (_,mw) <- magickWand+ (_,mwc) <- magickWand+ pw <- pixelWand+ (_,dw) <- drawingWand+ {-+ convert ant_mask.png -fill red -draw 'color 0,0 reset' \+ ant_mask.png +matte -compose CopyOpacity -composite \+ -font Candice -pointsize 36 -fill white -stroke black \+ -gravity Center -annotate 0 "Ant" \+ ant.png+ -}++ mw `readImage` "logo_mask.png"++ pw `setColor` "red"+ dw `setFillColor` pw++ drawColor dw 0 0 resetMethod+ mw `drawImage` dw++ mwc `readImage` "logo_mask.png"+ mwc `setImageMatte` False++ compositeImage mw mwc copyOpacityCompositeOp 0 0++ -- Annotate gets all the font information from the drawingwand+ -- but draws the text on the magickwand+ -- I haven't got the Candice font so I'll use a pretty one+ -- that I know I have+ dw `setFont` "Lucida-Handwriting-Italic"+ dw `setFontSize` 36+ pw `setColor` "white"+ dw `setFillColor` pw++ pw `setColor` "black"+ dw `setStrokeColor` pw+ dw `setGravity` centerGravity+ annotateImage mw dw 0 0 0 "Ant"+ mw `writeImage` (Just "logo_ant.png")++{-+convert ant.png -fx A +matte -blur 0x6 -shade 110x30 -normalize \+ ant.png -compose Overlay -composite \+ ant.png -matte -compose Dst_In -composite \+ ant_3D.png+-}+ localGenesis $ do+ (_,mw) <- magickWand+ mw `readImage` "logo_ant.png"+ (_,mwf) <- fxImage mw "A"++ -- MagickSetImageMatte(mw,MagickFalse);+ -- +matte is the same as -alpha off+ -- mwf `setImageAlphaChannel` deactivateAlphaChannel+ blurImage mwf 0 6+ shadeImage mwf True 110 30+ normalizeImage mwf+ -- ant.png -compose Overlay -composite+ (_, mwc) <- magickWand+ mwc `readImage` "logo_ant.png"+ compositeImage mwf mwc overlayCompositeOp 0 0++ -- ant.png -matte -compose Dst_In -composite+ (_,mwc') <- magickWand+ mwc' `readImage` "logo_ant.png"+ -- -matte is the same as -alpha on+ -- I don't understand why the -matte in the command line+ -- does NOT operate on the image just read in (logo_ant.png in mwc)+ -- but on the image before it in the list+ -- It would appear that the -matte affects each wand currently in the+ -- command list because applying it to both wands gives the same result++ -- setImageAlphaChannel mwf setAlphaChannel+ -- setImageAlphaChannel mwc setAlphaChannel+ compositeImage mwf mwc' dstInCompositeOp 0 0++ writeImage mwf (Just "logo_ant_3D.png")+++ {- Now for the shadow+ convert ant_3D.png \( +clone -background navy -shadow 80x4+6+6 \) +swap \+ -background none -layers merge +repage ant_3D_shadowed.png+ -}+ localGenesis $ do+ pw <- pixelWand+ (_,mw) <- magickWand+ readImage mw "logo_ant_3D.png"++ (_,mwc) <- cloneMagickWand mw++ pw `setColor` "navy"+ mwc `setImageBackgroundColor` pw++ shadowImage mwc 80 4 6 6++ -- at this point+ -- mw = ant_3D.png+ -- mwc = +clone -background navy -shadow 80x4+6+6+ -- To do the +swap I create a new blank MagickWand and then+ -- put mwc and mw into it. ImageMagick probably doesn't do it+ -- this way but it works here and that's good enough for me!+ (_,mwf) <- magickWand+ mwf `addImage` mwc+ mwf `addImage` mw++ pw `setColor` "none"+ setImageBackgroundColor mwf pw+ (_,mwc') <- mergeImageLayers mwf mergeLayer+ mwc' `writeImage` (Just "logo_shadow_3D.png")+++ {-+ and now for the fancy background+ convert ant_3D_shadowed.png \+ \( +clone +repage +matte -fx 'rand()' -shade 120x30 \+ -fill grey70 -colorize 60 \+ -fill lavender -tint 100 \) -insert 0 \+ -flatten ant_3D_bg.jpg+ -}+ localGenesis $ do+ pw <- pixelWand+ (_,mw) <- magickWand+ mw `readImage` "logo_shadow_3D.png"++ (_,mwc) <- cloneMagickWand mw+ -- +repage+ resetImagePage mwc Nothing+ -- +matte is the same as -alpha off+ -- setImageAlphaChannel mwc deactivateAlphaChannel+ (_, mwf) <- fxImage mwc "rand()"++ shadeImage mwf True 120 30+ setColor pw "grey70"+ -- It seems that this must be a separate pixelwand for Colorize to work!+ pwo <- pixelWand+ -- AHA .. this is how to do a 60% colorize+ pwo `setColor` "rgb(60%,60%,60%)"+ colorizeImage mwf pw pwo++ pw `setColor` "lavender"+ -- and this is a 100% tint+ pwo `setColor` "rgb(100%,100%,100%)"+ tintImage mwf pw pwo++ (_, mwc') <- magickWand+ mwc' `addImage` mwf+ mwc' `addImage` mwc++ (_, mwf') <- mergeImageLayers mwc flattenLayer+ mwf' `writeImage` (Just "logo_bg_3D.jpg")+
+ examples/affine.hs view
@@ -0,0 +1,232 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/affine.htm+{-+ Originally inspired by:+http://www.imagemagick.org/discourse-server/viewtopic.php?f=2&t=12530+ The idea for these specific examples came from reading this:+http://www.csl.mtu.edu/cs4611/www/HillLectureNotes/CS4611%202D%20Affine%20Transformation.htm+ When reading that (and other web pages about affine) keep in mind+ that IM's ordering of the affine matrix as described at:+ http://imagemagick.org/script/command-line-options.php#affine+ orders the affine values and their multiplication like this:+ [x y 1] |sx rx 0|+ |ry sy 0|+ |tx ty 1|++ Whereas the CS4611 web page uses this (which, if nothing else, is tidier):+ |sx ry tx| |x|+ |rx sy ty| |y|+ |0 0 1 | |1|++ My multiplication routine is written to conform to the way IM+ specifies things.++ ALSO, I think there are a couple of errors on the CS4611 page.+ 1. In the example of rotation about a point, it says that first+ translate by V, then rotate, then translate by -V.+ But the matrix representation of this does -V,rotate,V.+ 2. Reflection across the x-axis is not correct as shown.+ When a point (x,y) is reflected across the x-axis its+ new coordinate is (x,-y) - the matrix shown in the example+ actually reflects across the y-axis - i.e. it produces (-x,y).+-}++import Data.Fixed (mod')+import Graphics.ImageMagick.MagickWand++-- typesafe angle logic could be imported form AC-Angle package++-- | Convert from degrees to radians.+radians :: Double -> Double+radians x = x / 180 * pi++-- | Convert from radians to degrees.+degrees :: Double -> Double+degrees x = x * 180 / pi++-- Set the affine array to translate by (x,y)+-- Set the affine array to scale the image by sx,sy+translate_affine :: (Floating x) => x -> x -> [x]+translate_affine x y =+ [ 1, 0, 0,+ 1, x, y ]++-- Set the affine array to scale the image by sx,sy+scale_affine :: (Floating x) => x -> x -> [x]+scale_affine sx sy =+ [ sx, 0, 0,+ sy, 0, 0 ]++-- get the affine array to rotate image by 'degrees' clockwise+rotate_affine :: Double -> [Double]+rotate_affine angle =+ [ cos (radians (angle `mod'` 360)), sin (radians (angle `mod'` 360)), -sin (radians (angle `mod'` 360)),+ cos (radians (angle `mod'` 360)), 0, 0 ]++-- Multiply two affine arrays and return the result.+affine_multiply :: (Floating x) => [x] -> [x] -> [x]+affine_multiply [a0,a1,a2,a3,a4,a5] [b0,b1,b2,b3,b4,b5] =+ [ a0*b0 + a1*b2, a0*b1 + a1*b3,+ a2*b0 + a3*b2, a2*b1 + a3*b3,+ a4*b0 + a5*b2 + b4, a4*b1 + a5*b3 + b5 ]+affine_multiply _ _ = error "incorrect list sizes"++main :: IO ()+main = withMagickWandGenesis $ do+ -- Remember that these operations are done with respect to the+ -- origin of the image which is the TOP LEFT CORNER.+ localGenesis $ do+ -- Example 1.+ -- Rotate logo: by 90 degrees (about the origin), scale by 50 percent and+ -- then move the image 240 in the x direction+ -- TODO: fix problem with 'leaky' pixel+ (_,mw) <- magickWand+ readImage mw "logo:"+ -- Set up the affine matrices+ -- rotate 90 degrees clockwise+ let+ r = rotate_affine 90+ -- scale by .5 in x and y+ s = scale_affine 0.5 0.5+ -- translate to (240,0)+ t = translate_affine 240 0+ -- now multiply them - note the order in+ -- which they are specified - in particular beware that+ -- temp = r*s is NOT necessarily the same as temp = s*r++ --first do the rotation and scaling+ -- temp = r*s+ temp = r `affine_multiply` s+ -- now the translation+ -- result = temp*t;+ result = temp `affine_multiply` t++ -- and then apply the result to the image+ distortImage mw affineProjectionDistortion result False++ writeImage mw (Just "logo_affine_1.jpg")++ localGenesis $ do+ -- Example 2+ -- Rotate logo: 30 degrees around the point (300,100)+ -- Since rotation is done around the origin, we must translate+ -- the point (300,100) up to the origin, do the rotation, and+ -- then translate back again+ (_,mw) <- magickWand+ readImage mw "logo:"++ let+ -- Initialize the required affines+ -- translate (300,100) to origin+ t1 = translate_affine (-300) (-100)+ -- rotate clockwise by 30 degrees+ r = rotate_affine 30+ -- translate back again+ t2 = translate_affine 300 100+ -- Now multiply the affine sequence+ -- temp = t1*r+ temp = t1 `affine_multiply` r+ -- result = temp*t2;+ result = temp `affine_multiply` t2++ distortImage mw affineProjectionDistortion result False++ writeImage mw (Just "logo_affine_2.jpg")++ localGenesis $ do+ -- Example 3+ -- Reflect the image about a line passing through the origin.+ -- If the line makes an angle of D degrees with the horizontal+ -- then this can be done by rotating the image by -D degrees so+ -- that the line is now (in effect) the x axis, reflect the image+ -- across the x axis, and then rotate everything back again.+ -- In this example, rather than just picking an arbitrary angle,+ -- let's say that we want the "logo:" image to be reflected across+ -- it's own major diagonal. Although we know the logo: image is+ -- 640x480 let's also generalize the code slightly so that it+ -- will still work if the name of the input image is changed.+ -- If the image has a width "w" and height "h", then the angle between+ -- the x-axis and the major diagonal is atan(h/w) (NOTE that this+ -- result is in RADIANS!)+ -- For this example I will also retain the original dimensions of the+ -- image so that anything that is reflected outside the borders of the+ -- input image is lost+ (_,mw) <- magickWand+ readImage mw "logo:"+ w <- getImageWidth mw+ h <- getImageHeight mw++ let+ -- Just convert the radians to degrees. This way I don't have+ -- to write a function which sets up an affine rotation for an+ -- argument specified in radians rather than degrees.+ -- You can always change this.+ angle_degrees = degrees(atan(realToFrac(h) / realToFrac(w)))+ -- Initialize the required affines+ -- Rotate diagonal to the x axis+ r1 = rotate_affine (-angle_degrees)+ -- Reflection affine (about x-axis)+ -- In this case there isn't a specific function to set the+ -- affine array (like there is for rotation and scaling)+ -- so use the function which sets an arbitrary affine+ reflect = [ 1, 0, 0,+ -1, 0, 0 ]+ -- rotate image back again+ r2 = rotate_affine angle_degrees+ -- temp = r1*reflect+ temp = r1 `affine_multiply` reflect+ -- result = temp*r2;+ result = temp `affine_multiply` r2++ distortImage mw affineProjectionDistortion result False++ writeImage mw (Just "logo_affine_3.jpg")++ localGenesis $ do+ -- Example 4+ -- Create a rotated gradient+ -- See: http:--www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=12707+ -- The affine in this one is essentially the same as the one in Example 2 but+ -- this example has a different use for the result+ let+ -- Dimensions of the final rectangle+ w = 600 :: Int+ h = 100 :: Int+ -- angle of clockwise rotation+ theta = 15 -- degrees+ -- Convert theta to radians+ rad_theta = radians theta+ -- Compute the dimensions of the rectangular gradient+ -- Don't let the rotation make the gradient rectangle any smaller+ -- than the required output (using `max`)+ gw = max w $ round (fromIntegral w * cos rad_theta + fromIntegral h * sin rad_theta + 0.5)+ gh = max h $ round (fromIntegral w * sin rad_theta + fromIntegral h * cos rad_theta + 0.5)++ (_,mw) <- magickWand+ setSize mw gw gh+ readImage mw "gradient:white-black"++ let+ -- Initialize the required affines+ -- translate centre of gradient to origin+ t1 = translate_affine (- fromIntegral gw / 2) (- fromIntegral gh / 2)+ -- rotate clockwise by theta degrees+ r = rotate_affine(theta)+ -- translate back again+ t2 = translate_affine (fromIntegral gw / 2) (fromIntegral gh / 2)+ -- Now multiply the affine sequences+ -- temp = t1*r+ temp = t1 `affine_multiply` r+ -- result = temp*t2;+ result = temp `affine_multiply` t2++ distortImage mw affineProjectionDistortion result False+ -- Get the size of the distorted image and crop out the middle+ nw <- getImageWidth mw+ nh <- getImageHeight mw+ cropImage mw w h ((nw - w) `div` 2) ((nh - h) `div` 2)+ writeImage mw (Just "rotgrad_2.png")+++
+ examples/bunny.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/bunny.htm+-- This implements the command:+-- convert bunny_grass.gif ( bunny_anim.gif -repage 0x0+5+15! ) \+-- -coalesce -delete 0 -deconstruct -loop 0 bunny_bgnd.gif+-- from Anthony's examples at: http://www.imagemagick.org/Usage/anim_basics/#cleared++import Control.Monad (forM_)+import Control.Monad.Trans.Resource (release)+import Graphics.ImageMagick.MagickWand++main :: IO ()+main = withMagickWandGenesis $ do+ {- Create a wand -}+ (mw0k,mw0) <- magickWand++ {- Read the first input image -}+ readImage mw0 "bunny_grass.gif"++ --( bunny_anim.gif -repage 0x0+5+15\! )+ -- We need a separate wand to do this bit in parentheses+ localGenesis $ do+ (_,aw) <- magickWand+ readImage aw "bunny_anim.gif"+ resetImagePage aw (Just "0x0+5+15!")++ -- Now we have to add the images in the aw wand on to the end+ -- of the mw wand.+ addImage mw0 aw+ -- thee aw wand is destoyed on exiting `localGenesis` so that it can be used+ -- for the next operation+++ -- -coalesce+ (aw0k, aw0) <- coalesceImages mw0++ -- do "-delete 0" by copying the images from the "aw" wand to+ -- the "mw" wand but omit the first one+ -- free up the mw wand and recreate it for this step+ release mw0k+ (_,mw1) <- magickWand+ n <- getNumberImages aw0+ forM_ [1..(n-1)] $ \i -> localGenesis $ do+ aw0 `setIteratorIndex` i+ (_,tw) <- getImage aw0+ addImage mw1 tw++ resetIterator mw1++ -- free up aw for the next step+ release aw0k++ -- -deconstruct+ -- Anthony says that MagickDeconstructImages is equivalent+ -- to MagickCompareImagesLayers so we'll use that++ (_,aw1) <- compareImageLayers mw1 compareAnyLayer++ -- -loop 0+ setOption aw1 "loop" "0"++ {- write the images into one file -}+ writeImages aw1 "bunny_bgnd.gif" True
+ examples/clipmask.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE OverloadedStrings #-}+-- | http://www.imagemagick.org/discourse-server/viewtopic.php?f=10&t=12285+-- and more recently: http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=16783+-- http://www.imagemagick.org/Usage/channels/#masked_compose+-- Replicate a masked composite:+-- convert -size 100x100 tile:tile_water.jpg tile:tile_disks.jpg \+-- mask_bite.png -composite compose_masked.png+--++import Graphics.ImageMagick.MagickWand+import Graphics.ImageMagick.MagickCore++main = do+ -- MagickWand *dest = NULL, *src = NULL, *mask = NULL;++ withMagickWandGenesis $ do++ -- Create the wands+ (_,dest) <- magickWand+ (_,mask) <- magickWand+ (_,src) <- magickWand++ setSize dest 100 100+ setSize src 100 100++ readImage dest "tile:tile_water.jpg" -- tile: ?+ readImage mask "mask_bite.png" -- ?++ -- When you create a mask, you use white for those parts that you want+ -- to show through and black for those which must not show through.+ -- But internally it's the opposite so the mask must be negated++ negateImage mask False+ setImageClipMask dest mask++ readImage src "tile:tile_disks.jpg"++ -- This does the src (overlay) over the dest (background)+ compositeImage dest src overCompositeOp 0 0++ writeImages dest "clip_out.jpg" True
+ examples/cyclops.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/cyclops.htm+-- http://www.imagemagick.org/discourse-server/viewtopic.php?f=18&t=12118+{-+magick convert cyclops.gif -bordercolor white -border 1x1 -matte \+ -fill none -fuzz 20% -draw "matte 0,0 floodfill" \+ -shave 1x1 cyclops_flood_3.png+-}++import Filesystem.Path.CurrentOS (decodeString)+import Graphics.ImageMagick.MagickWand+import Graphics.ImageMagick.MagickWand.FFI.Types++main :: IO ()+main =+ withMagickWandGenesis $ do+ (_,w) <- magickWand+ readImage w (decodeString src)++ fc <- pixelWand+ bc <- pixelWand++ fc `setColor` "none"+ bc `setColor` "white"++ borderImage w bc 1 1+ setImageAlphaChannel w setAlphaChannel+ channel <- parseChannelOption "rgba"+ floodfillPaintImage w channel fc 20 bc 0 0 False+ shaveImage w 1 1+ writeImages w (decodeString out) True++ where+ src = "cyclops_sm.gif"+ out = "cyclops_sm_flood.png"
+ examples/draw_shapes.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/draw_shapes.htm+-- There's no equivalent convert command for this. It is a demo of MagickWand.+-- Bits of this were pinched from+-- http://www.imagemagick.org/api/MagickWand/drawtest_8c-source.html++import Graphics.ImageMagick.MagickWand+import Graphics.ImageMagick.MagickWand.FFI.Types+++main :: IO ()+main =+ withMagickWandGenesis $ do+ (_,w) <- magickWand+ (_,dw) <- drawingWand+ c <- pixelWand++ let diameter = 640+ radius = (fromIntegral diameter) / 2++ c `setColor` "white"+ newImage w diameter diameter c++ dw `setStrokeOpacity` 1+ -- circle and rectangle+ pushDrawingWand dw++ -- Hmmmm. Very weird. rgb(0,0,1) draws a black line around the edge+ -- of the circle as it should. But rgb(0,0,0) or black don't.+ -- AND if I remove the PixelSetColor then it draws a white boundary+ -- around the rectangle (and presumably around the circle too)+ c `setColor` "rgb(0,0,1)"++ dw `setStrokeColor` c+ dw `setStrokeWidth` 4+ dw `setStrokeAntialias` True+ c `setColor` "red"+ -- dw `setStrokeOpacity` 1+ dw `setFillColor` c++ drawCircle dw radius radius radius (radius * 2)+ drawRectangle dw 50 13 120 87+ popDrawingWand dw++ -- rounded rectangle+ pushDrawingWand dw+ let poly1 = [+ PointInfo 378.1 81.72, PointInfo 381.1 79.56, PointInfo 384.3 78.12, PointInfo 387.6 77.33,+ PointInfo 391.1 77.11, PointInfo 394.6 77.62, PointInfo 397.8 78.77, PointInfo 400.9 80.57,+ PointInfo 403.6 83.02, PointInfo 523.9 216.8, PointInfo 526.2 219.7, PointInfo 527.6 223,+ PointInfo 528.4 226.4, PointInfo 528.6 229.8, PointInfo 528 233.3, PointInfo 526.9 236.5,+ PointInfo 525.1 239.5, PointInfo 522.6 242.2, PointInfo 495.9 266.3, PointInfo 493 268.5,+ PointInfo 489.7 269.9, PointInfo 486.4 270.8, PointInfo 482.9 270.9, PointInfo 479.5 270.4,+ PointInfo 476.2 269.3, PointInfo 473.2 267.5, PointInfo 470.4 265, PointInfo 350 131.2,+ PointInfo 347.8 128.3, PointInfo 346.4 125.1, PointInfo 345.6 121.7, PointInfo 345.4 118.2,+ PointInfo 346 114.8, PointInfo 347.1 111.5, PointInfo 348.9 108.5, PointInfo 351.4 105.8,+ PointInfo 378.1 81.72+ ]++ dw `setStrokeAntialias` True+ dw `setStrokeWidth` 2.016+ dw `setStrokeLineCap` roundCap+ dw `setStrokeLineJoin` roundJoin+ dw `setStrokeDashArray` []+ c `setColor`{- "#000080" -} "rgb(0,0,128)"+ -- If strokecolor is removed completely then the circle is not there+ dw `setStrokeColor` c+ -- But now I've added strokeopacity - 1=circle there 0=circle not there+ -- If opacity is 1 the black edge around the rectangle is visible+ dw `setStrokeOpacity` 1+ -- No effect+ {- dw `setFillRule` evenOddRule -}+ -- this doesn't affect the circle+ c `setColor` "#c2c280" {- "rgb(194,194,128)" -}+ dw `setFillColor` c+ -- 1=circle there 0=circle there but rectangle fill disappears+ -- dw `setFillOpacity` False+ drawPolygon dw poly1+ -- dw `setFillOpacity` True+ popDrawingWand dw++ pushDrawingWand dw+ -- yellow polygon+ let poly2 = [+ PointInfo 540 288, PointInfo 561.6 216, PointInfo 547.2 43.2, PointInfo 280.8 36,+ PointInfo 302.4 194.4, PointInfo 331.2 64.8, PointInfo 504 64.8, PointInfo 475.2 115.2,+ PointInfo 525.6 93.6, PointInfo 496.8 158.4, PointInfo 532.8 136.8, PointInfo 518.4 180,+ PointInfo 540 172.8, PointInfo 540 223.2, PointInfo 540 288+ ]+ dw `setStrokeAntialias` True+ dw `setStrokeWidth` 5.976+ dw `setStrokeLineCap` roundCap+ dw `setStrokeLineJoin` roundJoin+ dw `setStrokeDashArray` []+ c `setColor` "#4000c2"+ dw `setStrokeColor` c+ dw `setFillRule` evenOddRule+ c `setColor` "#ffff00"+ dw `setFillColor` c+ drawPolygon dw poly2+ popDrawingWand dw++ -- rotated and translated ellipse+ -- The DrawEllipse function only draws the ellipse with+ -- the major and minor axes orthogonally aligned. This also+ -- applies to some of the other functions such as DrawRectangle.+ -- If you want an ellipse that has the major axis rotated, you+ -- have to rotate the coordinate system before the ellipse is+ -- drawn. And you'll also want the ellipse somewhere on the+ -- image rather than at the top left (where the 0,0 origin is+ -- located) so before drawing the ellipse we move the origin to+ -- wherever we want the centre of the ellipse to be and then+ -- rotate the coordinate system by the angle of rotation we wish+ -- to apply to the ellipse and *then* we draw the ellipse.+ -- NOTE that doing all this within `pushDrawingWand`/`popDrawingWand`+ -- means that the coordinate system will be restored after+ -- the `popDrawingWand`+ pushDrawingWand dw+ c `setColor` "rgb(0,0,1)"+ dw `setStrokeColor` c+ dw `setStrokeWidth` 2+ dw `setStrokeAntialias` True+ c `setColor` "orange"+ -- dw `setStrokeOpacity` 1+ dw `setFillColor` c+ -- Be careful of the order in which you meddle with the+ -- coordinate system! Rotating and then translating is+ -- not the same as translating then rotating+ translate dw (radius/2) (3 * radius/2)+ rotate dw (-30)+ drawEllipse dw 0 0 (radius/8) (3*radius/8) 0 360+ popDrawingWand dw++ -- A line from the centre of the circle+ -- to the top left edge of the image+ drawLine dw 0 0 radius radius++ drawImage w dw++ writeImage w (Just "chart_test.jpg")
+ examples/extent.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE OverloadedStrings #-}++-- http://members.shaw.ca/el.supremo/MagickWand/extent.htm+-- convert logo: -background blue -extent 1024x768-192-144 logo_extent.jpg+-- Read an image and centre it on a larger 1024x768, extended canvas.+-- The input image must be no larger than 1024x768 because this code does not+-- check for errors++import Graphics.ImageMagick.MagickWand++main :: IO ()+main = do++ withMagickWandGenesis $ do+ (_,w) <- magickWand+ p <- pixelWand++ p `setColor` "blue"++ w `readImage` "logo:"++ width <- getImageWidth w+ height <- getImageHeight w++ w `setImageBackgroundColor` p++ extentImage w 1024 768 (-(1024-width) `div` 2) (-(768-height) `div` 2)++ w `writeImage` (Just "logo_extent.png")
+ examples/floodfill.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/floodfill.htm+--+-- Replace the white background area of 1st argument with transparent and don't forget+-- that for this the channel must be "rgba" and the output image must be PNG+-- or other format which supports transparency++import Graphics.ImageMagick.MagickWand++main = do+ withMagickWandGenesis $ do+ (_,w) <- magickWand+ readImage w "logo:"++ fc <- pixelWand+ bc <- pixelWand++ fc `setColor` "none"+ bc `setColor` "white"++ channel <- parseChannelOption "rgba"++ floodfillPaintImage w channel fc 20 bc 0 0 False++ w `writeImage` (Just "logo_floodfill.png")
+ examples/gel.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/gel.htm+-- "Gel" Effects example+-- http://www.imagemagick.org/Usage/advanced/#gel_effects++import Control.Exception.Lifted+import Control.Monad (void)+import Graphics.ImageMagick.MagickWand+import Prelude hiding (catch)+++main :: IO ()+main =+ withMagickWandGenesis $ do+ -- First step is to create the gel shape:+ {-+convert -size 100x60 xc:none \+ -fill red -draw 'circle 25,30 10,30' \+ -draw 'circle 75,30 90,30' \+ -draw 'rectangle 25,15 75,45' \+ gel_shape.png+-}+ localGenesis $ do+ -- Create a wand+ (_,mw) <- magickWand+ pw <- pixelWand+ (_,dw) <- drawingWand++ setSize mw 100 60+ readImage mw "xc:none"++ pw `setColor` "red"+ dw `setFillColor` pw+ drawCircle dw 25 30 10 30+ drawCircle dw 75 30 90 30+ drawRectangle dw 25 15 75 45++ -- Now we draw the Drawing wand on to the Magick Wand+ drawImage mw dw++ writeImage mw (Just "gel_shape.png")++ -- Next step is to create the gel highlight:+{-+convert gel_shape.png \+ \( +clone -fx A +matte -blur 0x12 -shade 110x0 -normalize \+ -sigmoidal-contrast 16,60% -evaluate multiply .5 \+ -roll +5+10 +clone -compose Screen -composite \) \+ -compose In -composite gel_highlight.png+-}+ localGenesis $ do+ (_,mw) <- magickWand+ readImage mw "gel_shape.png"++ (_,mwc) <- cloneMagickWand mw+ (_,mwf) <- fxImage mwc "A"+ -- TODO: fails, should we ignore it?+ ignoreExceptions (mw `setImageAlphaChannel` deactivateAlphaChannel)++ blurImage mwf 0 12+ shadeImage mwf True 110 0++ normalizeImage mwf+ -- The last argument is specified as a percentage on the command line+ -- but is specified to the function as a percentage of the QuantumRange+ sigmoidalContrastImage mwf True 16 (0.6 * quantumRange)++ evaluateImage mwf multiplyEvaluateOperator 0.5+ rollImage mwf 5 10++ -- The +clone operation copies the original but only so that+ -- it can be used in the following composite operation, so we don't+ -- actually need to do a clone, just reference the original image.+ compositeImage mwf mw screenCompositeOp 0 0++ compositeImage mw mwf inCompositeOp 0 0+ writeImage mw (Just "gel_highlight.png")++ -- Now create the gel border+{-+convert gel_highlight.png \+ \( +clone -fx A +matte -blur 0x2 -shade 0x90 -normalize \+ -blur 0x2 -negate -evaluate multiply .4 -negate -roll -.5-1 \+ +clone -compose Multiply -composite \) \+ -compose In -composite gel_border.png++-}+ localGenesis $ do+ (_,mw) <- magickWand+ readImage mw "gel_highlight.png"+ (_,mwc) <- cloneMagickWand mw+ (_,mwf) <- fxImage mwc "A"+ ignoreExceptions (mwf `setImageAlphaChannel` deactivateAlphaChannel)+ blurImage mwf 0 2+ shadeImage mwf True 0 90+ normalizeImage mwf+ blurImage mwf 0 2+ negateImage mwf False+ evaluateImage mwf multiplyEvaluateOperator 0.4+ negateImage mwf False+ rollImage mwf (-0.5) (-1)+ compositeImage mwf mw multiplyCompositeOp 0 0+ compositeImage mw mwf inCompositeOp 0 0+ writeImage mw (Just "gel_border.png")++ -- and finally the text and shadow effect+{-+ convert gel_border.png \+ -font Candice -pointsize 24 -fill white -stroke black \+ -gravity Center -annotate 0 "Gel" -trim -repage 0x0+4+4 \+ \( +clone -background navy -shadow 80x4+4+4 \) +swap \+ -background none -flatten gel_button.png+-}+ localGenesis $ do+ (_,mw) <- magickWand+ (_,dw) <- drawingWand+ pw <- pixelWand+ readImage mw "gel_border.png"+ dw `setFont` "Lucida-Handwriting-Italic"+ dw `setFontSize` 24+ pw `setColor` "white"+ dw `setFillColor` pw+ pw `setColor` "black"+ dw `setStrokeColor` pw+ dw `setGravity` centerGravity+ -- It is important to notice here that MagickAnnotateImage renders the text on+ -- to the MagickWand, NOT the DrawingWand. It only uses the DrawingWand for font+ -- and colour information etc.+ annotateImage mw dw 0 0 0 "Gel"+ trimImage mw 0+ resetImagePage mw (Just "0x0+4+4")+ (_,mwc) <- cloneMagickWand mw+ pw `setColor` "navy"+ mwc `setImageBackgroundColor` pw+ shadowImage mwc 80 4 4 4+ (_,mwf) <- magickWand+ addImage mwf mwc+ addImage mwf mw+ pw `setColor` "none"+ mwf `setImageBackgroundColor` pw+ (_,mw') <- mergeImageLayers mwf flattenLayer+ writeImage mw' (Just "gel_button.png")++ignoreExceptions f = catch (void f) (\(_::MagickWandException) -> return ())
+ examples/grayscale.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE OverloadedStrings #-}+--+-- Create a simple grayscale gradient using Pixel Iterators+--+import Control.Monad+import Data.ByteString.Char8 as S+import qualified Data.Vector.Storable as V+import Graphics.ImageMagick.MagickWand+import Text.Printf++main :: IO ()+main = withMagickWandGenesis $ do+ pWand <- pixelWand+ pWand `setColor` "white"+ (_,mWand) <- magickWand+ -- Create a 100x100 image with a default of white+ newImage mWand 100 100 pWand+ -- Get a new pixel iterator++ (_,it) <- pixelIterator mWand+ rows <- pixelIterateList it+ forM_ rows $ \row -> do+ (flip imapM_) row $ \x v -> do+ let gray = x*255 `div` 100+ hex = S.pack $ '#':(printf "%02x%02x%02x" gray gray gray)+ v `setColor` hex+ -- Sync writes the pixels back to the m_wand+ pixelSyncIterator it+ mWand `writeImage` (Just "bits_demo.gif")++imapM_ :: (Monad m, V.Storable a) => (Int -> a -> m ()) -> V.Vector a -> m ()+imapM_ f v = V.foldM'_ (\x a -> f x a >> return (x+1)) 1 v
+ examples/landscape_3d.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/landscape_3d.htm+-- This is derived from a PHP script at:+-- http://eclecticdjs.com/mike/tutorials/php/imagemagick/imagickpixeliterator/3D_landscape.php++import Control.Applicative ((<$>))+import Control.Monad+import Control.Monad.IO.Class (liftIO)+import Data.IORef+import Graphics.ImageMagick.MagickWand+++main :: IO ()+main = withMagickWandGenesis $ do+ -- input image+ -- The input image is at: "http://eclecticdjs.com/mike/temp/ball/fract6.jpg"+ let url = "fract6.jpg";+ -- output image+ let file = "3d_fractal.jpg";++ (_,image) <- magickWand+ pw <- pixelWand++ readImage image url+ -- scale it down+ -- w <- getImageWidth image+ -- h <- getImageHeight image++ pw `setColor` "transparent"+ shearImage image pw 45 0+ -- MessageBox(NULL,"B - Shear failed","",MB_OK);+ w0 <- getImageWidth image+ h0 <- getImageHeight image++ -- scale it to make it look like it is laying down+ scaleImage image w0 (h0 `div` 2)+ -- MessageBox(NULL,"C - Scale failed","",MB_OK);+ -- Get image stats+ w <- getImageWidth image+ h <- getImageHeight image++ -- Make a blank canvas to draw on+ (_,canvas) <- magickWand+ -- Use a colour from the input image+ getImagePixelColor image 0 0 pw+ newImage canvas w (h*2) pw++ let offset = h+ -- The original drawing method was to go along each row from top to bottom so that+ -- a line in the "front" (which is one lower down the picture) will be drawn over+ -- one behind it.+ -- The problem with this method is that every line is drawn even if it will be covered+ -- up by a line "in front" of it later on.+ -- The method used here goes up each column from left to right and only draws a line if+ -- it is longer than everything drawn so far in this column and will therefore be visible.+ -- With the new drawing method this takes 13 secs - the previous method took 59 secs+ -- loop through all points in image+ forM_ [0..(w-1)] $ \x -> localGenesis $ do+ -- The PHP version created, used and destroyed the drawingwand inside+ -- the inner loop but it is about 25% faster to do only the DrawLine+ -- inside the loop+ (_,line) <- drawingWand+ line_height <- liftIO $ newIORef 0 -- let line_height = 0+ forM_ [(h-1),(h-2)..0] $ \y -> do+ -- get (r,g,b) and grey value+ getImagePixelColor image x y pw+ -- 255* adjusts the rgb values to Q8 even if the IM being used is Q16+ r <- round <$> (255*) <$> getRed pw+ g <- round <$> (255*) <$> getGreen pw+ b <- round <$> (255*) <$> getBlue pw++ -- Calculate grayscale - a divisor of 10-25 seems to work well.+ -- grey = (r+g+b)/25;+ let grey = (r + g + b) `div` 15+ -- grey = (r+g+b)/10;+ -- Only draw a line if it will show "above" what's already been done+ current <- liftIO $ readIORef line_height+ when (current == 0 || current < grey) $ do+ line `setFillColor` pw+ line `setStrokeColor` pw+ -- Draw the part of the line that is visible+ let+ start_y = y + offset - current+ end_y = y - grey + offset+ drawLine line (fromIntegral x) (fromIntegral start_y) (fromIntegral x) (fromIntegral end_y)+ liftIO $ writeIORef line_height grey+ liftIO $ modifyIORef line_height (\n->n-1)++ -- Draw the lines on the image+ drawImage canvas line++ scaleImage canvas (w-h) (h*2)+ -- write canvas+ writeImage canvas (Just file)
+ examples/make_tile.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE OverloadedStrings #-}+-- http://members.shaw.ca/el.supremo/MagickWand/make_tile.htm+-- The program makes two tiles, one using the plasma: pseudo file and one using noise+-- See: http://www.imagemagick.org/Usage/canvas/#plasma_seeded+-- and: http://www.imagemagick.org/Usage/canvas/#random++-- convert -size 100x100 plasma:red-yellow ( +clone -flop ) +append \+-- ( +clone -flip ) -append -resize 50% tile_plasma.png+-- and+-- convert -size 100x100 xc: +noise Random -virtual-pixel tile \+-- -blur 0x10 -normalize ( +clone -flop ) +append \+-- ( +clone -flip ) -append -resize 50% tile_random.png++{-+ Basically this flops and flips the image and joins the four results together+ and then resizes the result by 50% so that it's the same size as the original.+ E.g. if the original image is "/", it creates the flop image "\" and then appends+ them side by side to give "/\". Then it takes this image and flips it which produces+ "\/" and then appends these one on top of the other to produce+ + /\+ \/++ and finally, since this image is now twice the size of the original, it is resized to 50%.+-}++import Graphics.ImageMagick.MagickWand+import Control.Monad.Trans.Resource+import Control.Monad (void)++-- make-tile creates a tileable image from an input image.+-- ( +clone -flop ) +append ( +clone -flip ) -append -resize 50%+makeTile mw outfile = localGenesis $ do+ (destroyMwc, mwc) <- cloneMagickWand mw+ flopImage mwc+ mw `addImage` mwc+ release destroyMwc++ mwc' <- mw `appendImages` False+ (destroyMwf, mwf) <- cloneMagickWand mwc+ flipImage mwf+ mwc `addImage` mwf+ release destroyMwf++ (_,mwf') <- mwc `appendImages` True++ w <- getImageWidth mwf'+ h <- getImageHeight mwf'+ -- 1 = Don't blur or sharpen image+ resizeImage mwf (w `div` 2) (h `div` 2) lanczosFilter 1+ mwf `writeImage` outfile++main = do+ withMagickWandGenesis $ do+ (destroyMw, mw) <- magickWand+ setSize mw 100 100+ readImage mw "plasma:red-yellow"+ makeTile mw (Just "tile_plasma.png")+ release destroyMw++ (destroyMw', mw') <- magickWand+ setSize mw' 100 100+ mw `readImage` "xc:"+ mw `addNoiseImage` randomNoise+ void $ mw `setVirtualPixelMethod` tileVirtualPixelMethod+ blurImage mw 0 10+ normalizeImage mw+ makeTile mw (Just "tile_random.png")+
+ examples/modulate.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE OverloadedStrings #-}+{-+ From: http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=12640++ Read the logo: image and use PixelIterators to produce two new images.+ Convert the image to the HSB and HSL colourspaces, cut the Lightness/Brightness+ by half and then write the images as logo_hsb.jpg and logo_hsl.jpg+ Note the colour distortion in the HSL result whereas the HSB image is what+ we'd expect to see when reducing an image's brightness by 50%.+ + As with my other examples, there is no error checking in this code.+ If you adapt this to your own use, you should add error checking to ensure+ that, for example, MagickReadImage succeeds and that the width and height+ of the image in mw are reasonable values.+-}+import Control.Monad.IO.Class+import Control.Monad+import qualified Data.Vector.Storable as V+import Graphics.ImageMagick.MagickWand++main = withMagickWandGenesis $ do+ (_,mw) <- magickWand+ + mw `readImage` "logo:"+ + width <- getImageWidth mw+ height <- getImageHeight mw++ (_,mwl) <- magickWand+ (_,mwb) <- magickWand++ p <- pixelWand+ p `setColor` "none"+ -- Set the hsl and hsb images to the same size as the input image+ newImage mwl width height p+ newImage mwb width height p+ -- Even though we won't be reading these images they must be initialized+ -- to something TODO: fails to work+ -- readImage mwl "xs:none"+ -- readImage mwb "xs:none"++ -- Create iterators for each image+ (_,imw) <- pixelIterator mw + (_,imwl) <- pixelIterator mwl+ (_,imwb) <- pixelIterator mwb+ + it1 <- pixelIterateList imw+ it2 <- pixelIterateList imwl+ it3 <- pixelIterateList imwb+ mapM_ (action imwl imwb) $ zip3 it1 it2 it3+ + -- write the results+ mwb `writeImage` (Just "logo_hsb.jpg")+ mwl `writeImage` (Just "logo_hsl.jpg")+ where+ action imwl imwb (pmw, pmwl, pmwb) = do+ V.zipWithM_ inner1 pmw pmwb + V.zipWithM_ inner2 pmw pmwl+ -- Sync writes the pixels back to the magick wands+ pixelSyncIterator imwl+ pixelSyncIterator imwb+ inner1 xmw xmwb = localGenesis $ do+ -- Get the RGB quanta from the source image+ qr <- getRedQuantum xmw+ qg <- getGreenQuantum xmw+ qb <- getBlueQuantum xmw++ -- Convert the source quanta to HSB+ (bh,bs,bb) <- convertRGBToHSB qr qg qb+ (qr1,qg1,qb1) <- convertHSBToRGB bh bs (0.5*bb)+ -- Set the pixel in the HSB output image+ xmwb `setRedQuantum` qr1+ xmwb `setGreenQuantum` qg1+ xmwb `setBlueQuantum` qb1+ inner2 xmw xmwl = localGenesis $ do+ qr <- getRedQuantum xmw+ qg <- getGreenQuantum xmw+ qb <- getBlueQuantum xmw+ -- Convert the source quanta to HSL+ (lh,ls,ll) <- convertRGBToHSL qr qg qb+ (qr2,qg2,qb2) <- convertHSLToRGB lh ls (ll*0.5)+ -- Set the pixel in the HSL output image+ xmwl `setRedQuantum` qr2+ xmwl `setGreenQuantum` qg2+ xmwl `setBlueQuantum` qb2++zipWith3M_ f a b c = V.zipWithM_ f (V.zipWith g a b) c+ where g a b = (a,b)+ f' f (a,b) c = f a b c
+ examples/pixel_mod.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/pixel_mod.htm+-- example/pixel_mod.c+-- Change the colour of one pixel in the logo: image+-- using either DrawPoint or a RegionIterator++import Control.Applicative ((<$>))+import Data.Maybe+import Data.Vector.Storable ((!))+import Graphics.ImageMagick.MagickWand++main :: IO ()+main = withMagickWandGenesis $ do+ {- Create a wand -}+ (_,mw) <- magickWand+ {- Read the input image -}+ readImage mw "logo:"+ -- Change this define to `False` to use the region iterator instead of the Draw+ let useDraw = True+ if useDraw+ then do+ -- Get a one-pixel region at coordinate 200,100+ (_,iterator) <- pixelRegionIterator mw 200 100 1 1+ pixels <- fromJust <$> pixelGetNextIteratorRow iterator+ -- Modify the pixel+ pixels!0 `setColor` "red"+ -- then sync it back into the wand+ pixelSyncIterator iterator+ else do+ fill <- pixelWand+ (_,dw) <- drawingWand+ -- Set the fill to "red" or you can do the same thing with this:+ -- PixelSetColor(fill,"rgb(255,0,0)");+ fill `setColor` "red"+ dw `setFillColor` fill+ -- Uses the current Fill as the colour of the point at 200,100+ drawPoint dw 200 100+ {-+ srand(time(0));+ for(i=0;i<50;i++) {+ // plonk some random black pixels in the image+ j = rand()%DS_WIDTH;+ k = rand()%DS_HEIGHT;+ image[k*DS_WIDTH+j] = 0;+ }+ -}+ drawImage mw dw++ {- write it -}+ writeImage mw (Just "logo_pixel.gif")
+ examples/reflect.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/reflect.htm+{- convert logo: '(' logo: -resize 100%x50%! -flip -size 640x240 \+ gradient:white-black +matte -compose copyopacity -composite ')' \+ -append logo_reflect.png -}+import Graphics.ImageMagick.MagickWand+import Graphics.ImageMagick.MagickWand.FFI.Types++main :: IO ()+main = withMagickWandGenesis $ do+ (_,mw) <- magickWand+ readImage mw "logo:"+ -- We know that logo: is 640x480 but in the general case+ -- we need to get the dimensions of the image+ w <- getImageWidth mw+ h <- getImageHeight mw++ -- +matte is the same as -alpha off+ -- This does it the "new" way but if your IM doesn't have this+ -- then MagickSetImageMatte(mw,MagickFalse); can be used+ -- TODO: fails, should we ignore it?+ mw `setImageAlphaChannel` deactivateAlphaChannel+ -- clone the input image+ (_,mwr) <- magickWand--cloneMagickWand mw+ readImage mwr "logo:"+ -- Resize it+ resizeImage mwr w (h `div` 2) lanczosFilter 1+ -- Flip the image over to form the reflection+ flipImage mwr+ -- Create the gradient image which will be used as the alpha+ -- channel in the reflection image+ (_,mwg) <- magickWand+ setSize mwg w (h `div` 2)+ readImage mwg "gradient:white-black"++ -- Copy the gradient in to the alpha channel of the reflection image+ compositeImage mwr mwg copyOpacityCompositeOp 0 0++ -- Add the reflection image to the wand which holds the original image+ addImage mw mwr++ -- Append the reflection to the bottom (MagickTrue) of the original image+ (_,mwg') <- appendImages mw True++ -- and save the result+ writeImage mwg' (Just "logo_reflect.png")
+ examples/resize.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/resize.htm+--+-- convert logo: -filter lanczos -resize 50% -quality 95 logo_resize.jpg+-- Read an image, resize it by 50% and sharpen it, and then save as+-- a high quality JPG+-- Note that ImageMagick's default quality is 75.++import Graphics.ImageMagick.MagickWand++main :: IO ()+main = do+ withMagickWandGenesis $ do+ (_,w) <- magickWand++ -- Read the image+ readImage w "logo:"++ -- Cut them in half but make sure they don't underflow+ width <- fmap safeHalf (getImageWidth w)+ height <- fmap safeHalf (getImageHeight w)++ -- Resize the image using the Lanczos filter+ -- The blur factor is a 'Double', where > 1 is blurry, < 1 is sharp+ -- I haven't figured out how you would change the blur parameter of MagickResizeImage+ -- on the command line so I have set it to its default of one.+ resizeImage w width height lanczosFilter 1++ -- Set the compression quality to 95 (high quality = low compression)+ setImageCompressionQuality w 95++ -- Write the new image+ writeImages w "logo_resize.jpg" True++ where+ safeHalf = max 1 . (`div`2)+
+ examples/round_mask.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE OverloadedStrings #-}+-- Last updated 2008/11/04 11:11++-- http://www.imagemagick.org/discourse-server/viewtopic.php?f=10&t=10993+-- convert -size 640x480 xc:none -fill white -draw 'roundRectangle 15,15 624,464 15,15' logo: -compose SrcIn -composite mask_result.png+--++import Graphics.ImageMagick.MagickWand++main :: IO ()+main =+ withMagickWandGenesis $ do+ (_,mWand) <- magickWand+ (_,lWand) <- magickWand+ pWand <- pixelWand+ (_,dWand) <- drawingWand+ -- Create the initial 640x480 transparent canvas+ pWand `setColor` "none"++ newImage mWand 640 480 pWand++ pWand `setColor` "white"++ dWand `setFillColor` pWand++ drawRoundRectangle dWand 15 15 624 464 15 15++ mWand `drawImage` dWand++ lWand `readImage` "logo:"++ -- Note that MagickSetImageCompose is usually only used for the MagickMontageImage+ -- function and isn't used or needed by MagickCompositeImage++ compositeImage mWand lWand srcInCompositeOp 0 0++ -- Write the new image+ writeImages mWand "mask_result.png" True
+ examples/text_effects.hs view
@@ -0,0 +1,315 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+-- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/text_effects.htm+{- There's no equivalent convert command for this. It is a demo of MagickWand.+See this forum thread for the genesis of these effects+http://www.imagemagick.org/discourse-server/viewtopic.php?f=6&t=11586+and Anthony's Text Effects page at:+http://www.imagemagick.org/Usage/fonts/+-}++import Control.Monad (when)+import Control.Monad.IO.Class (MonadIO)+import Control.Monad.Trans.Resource+import Data.ByteString (ByteString)+import Data.Text (Text)+import qualified Data.Text as T+import Filesystem.Path.CurrentOS+import Graphics.ImageMagick.MagickCore.Types+import Graphics.ImageMagick.MagickWand+import Prelude hiding (FilePath)++-- see http://www.imagemagick.org/Usage/#font about using fonts with IM+font :: ByteString+font = "VerdanaBI"++-- Text effect 1 - shadow effect using MagickShadowImage+-- This is derived from Anthony's Soft Shadow effect+-- convert -size 300x100 xc:none -font Candice -pointsize 72 \+-- -fill white -stroke black -annotate +25+65 'Anthony' \+-- \( +clone -background navy -shadow 70x4+5+5 \) +swap \+-- -background lightblue -flatten -trim +repage font_shadow_soft.jpg++-- NOTE - if an image has a transparent background, adding a border of any colour other+-- than "none" will remove all the transparency and replace it with the border's colour+textEffect1 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()+textEffect1 w dw pw = do+ pw `setColor` "none"+ -- Create a new transparent image+ newImage w 350 100 pw+ -- Set up a 72 point white font+ pw `setColor` "white"+ dw `setFillColor` pw+ dw `setFont` font+ dw `setFontSize` 72+ -- Add a black outline to the text+ pw `setColor` "black"+ dw `setStrokeColor` pw+ -- Turn antialias on - not sure this makes a difference+ dw `setTextAntialias` True+ -- Now draw the text+ drawAnnotation dw 25 65 "Magick"+ -- Draw the image on to the magick_wand+ drawImage w dw++ -- Trim the image down to include only the text+ trimImage w 0+ -- equivalent to the command line +repage+ resetImagePage w Nothing++ -- Make a copy of the text image+ (_,cloneW) <- cloneMagickWand w+ -- Set the background colour to blue for the shadow+ pw `setColor` "blue"+ w `setImageBackgroundColor` pw++ -- Opacity is a real number indicating (apparently) percentage+ shadowImage w 70 4 5 5++ -- Composite the text on top of the shadow+ compositeImage w cloneW overCompositeOp 5 5++ (_,w') <- magickWand+ -- Create a new image the same size as the text image and put a solid colour+ -- as its background+ pw `setColor` "rgb(125,215,255)"+ width <- getImageWidth w+ height <- getImageHeight w+ newImage w' width height pw+ -- Now composite the shadowed text over the plain background+ compositeImage w' w overCompositeOp 0 0+ -- and write the result+ writeImage w' (Just "text_shadow.png")+++-- Given a pattern name (which MUST have a leading #) and a pattern file,+-- set up a pattern URL for later reference in the specified drawing wand+-- Currently only used in Text Effect 2+setTilePattern :: (MonadResource m) => PDrawingWand -> Text -> FilePath -> m ()+setTilePattern dw patternName patternFile = do+ (_,w) <- magickWand+ readImage w patternFile+ -- Read the tile's width and height+ width <- getImageWidth w+ height <- getImageHeight w++ pushPattern dw (T.tail patternName) 0 0 (realToFrac width) (realToFrac height)+ drawComposite dw srcOverCompositeOp 0 0 0 0 w+ popPattern dw+ dw `setFillPatternURL` patternName+++-- Text effect 2 - tiled text using the builtin checkerboard pattern+-- Anthony's Tiled Font effect+-- convert -size 320x100 xc:lightblue -font Candice -pointsize 72 \+-- -tile pattern:checkerboard -annotate +28+68 'Anthony' \+-- font_tile.jpg+textEffect2 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()+textEffect2 w dw pw = do+ setTilePattern dw "#check" "pattern:checkerboard"++ pw `setColor` "lightblue"+ -- Create a new transparent image+ newImage w 320 100 pw++ -- Set up a 72 point font+ dw `setFont` font+ dw `setFontSize` 72+ -- Now draw the text+ drawAnnotation dw 28 68 "Magick"+ -- Draw the image on to the magick_wand+ drawImage w dw+ -- Trim the image+ trimImage w 0+ -- Add a transparent border+ pw `setColor` "lightblue"+ borderImage w pw 5 5+ -- and write it+ writeImage w (Just "text_pattern.png")++-- Text effect 3 - arc font (similar to http://www.imagemagick.org/Usage/fonts/#arc)+-- convert -size 320x100 xc:lightblue -font Candice -pointsize 72 \+-- -annotate +25+65 'Anthony' -distort Arc 120 \+-- -trim +repage -bordercolor lightblue -border 10 font_arc.jpg+textEffect3 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()+textEffect3 w dw pw = do+ -- Create a 320x100 lightblue canvas+ pw `setColor` "lightblue"+ newImage w 320 100 pw++ -- Set up a 72 point font+ dw `setFont` font+ dw `setFontSize` 72+ -- Now draw the text+ drawAnnotation dw 25 65 "Magick"+ -- Draw the image on to the magick_wand+ drawImage w dw++ let dargs = [120]+ distortImage w arcDistortion dargs False+ -- Trim the image+ trimImage w 0+ -- Add the border+ pw `setColor` "lightblue"+ borderImage w pw 10 10++ -- and write it+ writeImage w (Just "text_arc.png")+++-- Text effect 4 - bevelled font http://www.imagemagick.org/Usage/fonts/#bevel+-- convert -size 320x100 xc:black -font Candice -pointsize 72 \+-- -fill white -annotate +25+65 'Anthony' \+-- -shade 140x60 font_beveled.jpg+textEffect4 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()+textEffect4 w dw pw = do+ let colorize = False+ -- Create a 320x100 canvas+ pw `setColor` "gray"+ newImage w 320 100 pw+ -- Set up a 72 point font+ dw `setFont` font+ dw `setFontSize` 72+ -- Set up a 72 point white font+ pw `setColor` "white"+ dw `setFillColor` pw+ -- Now draw the text+ drawAnnotation dw 25 65 "Magick"+ -- Draw the image on to the magick_wand+ drawImage w dw+ -- the "gray" parameter must be true to get the effect shown on Anthony's page+ shadeImage w True 140 60++ when colorize $ do+ pw `setColor` "yellow"+ dw `setFillColor` pw+ pw' <- pixelWand+ pw' `setColor` "gold"+ colorizeImage w pw pw'++ -- and write it+ writeImage w (Just "text_bevel.png")+++-- Text effect 5 and 6 - Plain text and then Barrel distortion+textEffects5_6 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()+textEffects5_6 w dw pw = do+ -- Create a 320x100 transparent canvas+ pw `setColor` "none"+ newImage w 320 100 pw++ -- Set up a 72 point font+ dw `setFont` font+ dw `setFontSize` 72+ -- Now draw the text+ drawAnnotation dw 25 65 "Magick"+ -- Draw the image on to the magick_wand+ drawImage w dw+ writeImage w (Just"text_plain.png")++ -- Trim the image+ trimImage w 0+ -- Add the border+ pw `setColor` "none"+ borderImage w pw 10 10+ -- MagickSetImageMatte(magick_wand,MagickTrue);+ -- MagickSetImageVirtualPixelMethod(magick_wand,TransparentVirtualPixelMethod);+ -- d_args[0] = 0.1;d_args[1] = -0.25;d_args[2] = -0.25; [3] += .1+ -- The first value should be positive. If it is negative the image is *really* distorted+ -- d_args[0] = 0.0;+ -- d_args[1] = 0.0;+ -- d_args[2] = 0.5;+ -- d_args[3] should normally be chosen such the sum of all 4 values is 1+ -- so that the result is the same size as the original+ -- You can override the sum with a different value+ -- If the sum is greater than 1 the resulting image will be smaller than the original+ -- d_args[3] = 1 - (d_args[0] + d_args[1] + d_args[2]);+ -- Make the result image smaller so that it isn't as likely+ -- to overflow the edges+ -- d_args[3] += 0.1;+ -- 0.0,0.0,0.5,0.5,0.0,0.0,-0.5,1.9+ -- d_args[3] = 0.5;+ -- d_args[4] = 0.0;+ -- d_args[5] = 0.0;+ -- d_args[6] = -0.5;+ -- d_args[7] = 1.9;++ let d_args = [0, 0, 0.5, 1 - (0 + 0 + 0.5), 0, 0, -0.5, 1.9]+ -- DON'T FORGET to set the correct number of arguments here+ distortImage w barrelDistortion d_args True+ -- MagickResetImagePage(magick_wand,"");+ -- Trim the image again+ trimImage w 0+ -- Add the border+ pw `setColor` "none"+ borderImage w pw 10 10+ -- and write it+ writeImage w (Just "text_barrel.png")++-- Text effect 7 - Polar distortion+textEffect7 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()+textEffect7 w dw pw = do+ -- Create a 320x200 transparent canvas+ pw `setColor` "none"+ newImage w 320 200 pw++ -- Set up a 72 point font+ dw `setFont` font+ dw `setFontSize` 72+ -- Now draw the text+ drawAnnotation dw 25 65 "Magick"+ -- Draw the image on to the magick_wand+ drawImage w dw++ distortImage w polarDistortion [0] True+ -- MagickResetImagePage(magick_wand,"");+ -- Trim the image again+ trimImage w 0+ -- Add the border+ pw `setColor` "none"+ borderImage w pw 10 10+ -- and write it+ writeImage w (Just "text_polar.png")++-- Text effect 8 - Shepard's distortion+textEffect8 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()+textEffect8 w dw pw = do+ -- Create a 320x200 transparent canvas+ pw `setColor` "none"+ newImage w 640 480 pw++ -- Set up a 72 point font+ dw `setFont` font+ dw `setFontSize` 72+ -- Now draw the text+ drawAnnotation dw 50 240 "Magick Rocks"+ -- Draw the image on to the magick_wand+ drawImage w dw+ let d_args = [ 150.0, 190.0, 100.0, 290.0, 500.0, 200.0, 430.0, 130.0 ]+ distortImage w shepardsDistortion d_args True++ -- Trim the image+ trimImage w 0+ -- Add the border+ pw `setColor` "none"+ borderImage w pw 10 10+ -- and write it+ writeImage w (Just "text_shepards.png")++runEffect :: (MonadIO m, MonadUnsafeIO m, MonadThrow m, MonadBaseControl IO m) =>+ (PMagickWand -> PDrawingWand -> PPixelWand -> ResourceT m ()) -> m ()+runEffect e = localGenesis $ do+ (_,w) <- magickWand+ (_,dw) <- drawingWand+ pw <- pixelWand+ e w dw pw++main :: IO ()+main = withMagickWandGenesis $ do+ runEffect textEffect1+ runEffect textEffect2+ runEffect textEffect3+ runEffect textEffect4+ runEffect textEffects5_6+ runEffect textEffect7+ runEffect textEffect8
+ examples/tilt_shift.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE OverloadedStrings #-}+{-+ Implement Anthony's tilt-shift example from http://www.imagemagick.org/Usage/photos/#tilt_shift+ NOTE that I use the -function version - not the linear one+ convert beijing_md.jpg -sigmoidal-contrast 15x30% \+ \( +clone -sparse-color Barycentric '0,0 black 0,%[fx:h-1] gray80' \+ -function polynomial 4,-4,1 \) \+ -compose Blur -set option:compose:args 15 -composite \+ beijing_model.jpg+-}++import Graphics.ImageMagick.MagickWand+import qualified Data.Vector.Storable as V++main = do++ -- arguments for MagickSparseColorImage+ -- Note that the colours are stored as separate *normalized* RGB components+ let funclist = V.fromList [4,-4,1]+ withMagickWandGenesis $ do+ (_,mw) <- magickWand+ mw `readImage` "beijing_md.jpg"+ h <- getImageHeight mw+ let arglist = V.fromList [0,0, + {-RGB black-} 0,0,0, + 0, fromIntegral (h-1), + {-RGB white-} 1, 1, 1]+ -- arglist[6] = ; --TODO+ sigmoidalContrastImage mw True 15 (quantumRange*30/100)+ (_, cw) <- cloneMagickWand mw+ sparseColorImage cw (blueChannel ^|^ greenChannel ^|^ redChannel) barycentricColorInterpolate arglist+ -- Do the polynomial function+ functionImage cw polynomialFunction funclist+ -- -set option:compose:args 15+ setImageArtifact cw "compose:args" "15"++ compositeImage mw cw blurCompositeOp 0 0+ mw `writeImage` (Just "beijing_model.jpg")
+ examples/trans_paint.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE OverloadedStrings #-}+-- http://members.shaw.ca/el.supremo/MagickWand/trans_paint.htm+-- Last updated 2008/11/25 08:48+--+-- Use MagickTransparentPaintImage to change *all* white pixels+-- to transparent in the logo: image++import Graphics.ImageMagick.MagickWand++main = do+ -- start image magick block+ withMagickWandGenesis $ do+ (_, w) <- magickWand+ readImage w "logo: "+ -- Set up the pixelwand containing the colour to be "targeted"+ -- by transparency+ t <- pixelWand+ t `setColor` "white"++ -- Change the transparency of all colours which match target (with+ -- fuzz applied). In this case they are made completely transparent (0)+ -- but you can set this to any value from 0 to 1.+ transparentPaintImage w t 0 fuzz False++ writeImages w "logo_white.png" True+ where+ -- A larger fuzz value allows more colours "near" white to be+ -- modified. A fuzz of zero only allows an exact match with the+ -- given colour+ fuzz = 0
+ examples/wandtest.hs view
@@ -0,0 +1,172 @@+{-# LANGUAGE OverloadedStrings #-}+import Control.Monad (forM_, when)+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Trans.Resource (release)+import Data.Int+import qualified Data.Text as T+import Data.Vector.Storable (Vector, (!))+import qualified Data.Vector.Storable as V+import Data.Word+import Graphics.ImageMagick.MagickWand+import Graphics.ImageMagick.MagickWand.FFI.Types+import System.Exit+import Text.Printf (printf)++throwAPIException w = undefined++exitWithMessage msg = liftIO $ do+ putStrLn msg+ exitFailure++iterateWand magick_wand = magickIterate magick_wand $ \w -> do+ i <- getIteratorIndex w+ s <- getImageScene w+ liftIO $ putStrLn $ printf "index %2d scene %2d" i s+++main :: IO ()+main = withMagickWandGenesis $ do+ (_,magick_wand) <- magickWand+ setSize magick_wand 640 480+ size <- getSize magick_wand+ when (size /= (640,480)) $ exitWithMessage "Unexpected magick wand size"+ liftIO $ putStrLn "Reading images...\n"+ readImage magick_wand "sequence.miff"+ n <- getNumberImages magick_wand+ when (n /= 5) $ liftIO $ putStrLn $ printf "read %02d images; expected 5" n+ liftIO $ putStrLn "Iterate forward..."+ iterateWand magick_wand++ liftIO $ putStrLn "Iterate reverse..."+ magickIterateReverse magick_wand $ \w -> do+ i <- getIteratorIndex w+ s <- getImageScene w+ liftIO $ putStrLn $ printf "index %2d scene %2d" i s++ liftIO $ putStrLn "Remove scene 1..."+ setIteratorIndex magick_wand 1+ (clone_key,clone_wand) <- getImage magick_wand+ removeImage magick_wand+ iterateWand magick_wand++ liftIO $ putStrLn "Insert scene 1 back in sequence..."+ setIteratorIndex magick_wand 0+ addImage magick_wand clone_wand+ iterateWand magick_wand++ liftIO $ putStrLn "Set scene 2 to scene 1..."+ setIteratorIndex magick_wand 2+ setImage magick_wand clone_wand+ release clone_key+ iterateWand magick_wand++ liftIO $ putStrLn "Apply image processing options..."+ cropImage magick_wand 60 60 10 10+ resetIterator magick_wand+ background <- pixelWand+ background `setColor` "#000000"+ rotateImage magick_wand background 90.0+ border <- pixelWand+ background `setColor` "green"+ border `setColor` "black"+ floodfillPaintImage magick_wand compositeChannels background+ (0.01*quantumRange) border 0 0 False++ (drawing_key,drawing_wand) <- drawingWand+ pushDrawingWand drawing_wand+ rotate drawing_wand 45+ drawing_wand `setFontSize` 18+ fill <- pixelWand+ fill `setColor` "green"+ drawing_wand `setFillColor` fill+ -- ? fill=DestroyPixelWand(fill);+ drawAnnotation drawing_wand 15 5 "Magick"+ popDrawingWand drawing_wand+ setIteratorIndex magick_wand 1+ drawImage magick_wand drawing_wand+ annotateImage magick_wand drawing_wand 70 5 90 "Image"+ release drawing_key++ let primary_colors = [+ 0, 0, 0,+ 0, 0, 255,+ 0, 255, 0,+ 0, 255, 255,+ 255, 255, 255,+ 255, 0, 0,+ 255, 0, 255,+ 255, 255, 0,+ 128, 128, 128+ ] :: [Word8]++ setIteratorIndex magick_wand 2+ importImagePixels magick_wand 10 10 3 3 "RGB" primary_colors+ pixels <- exportImagePixels magick_wand 10 10 3 3 "RGB"+ when (pixels /= primary_colors) $ exitWithMessage "Get pixels does not match set pixels"++ setIteratorIndex magick_wand 3+ resizeImage magick_wand 50 50 undefinedFilter 1.0+ magickIterate magick_wand $ \w -> do+ setImageDepth w 8+ setImageCompression w rleCompression++ resetIterator magick_wand+ setIteratorIndex magick_wand 4+ liftIO $ putStrLn "Utilitize pixel iterator to draw diagonal..."+ (iterator_key,iterator) <- pixelIterator magick_wand+ pixelRows <- pixelIterateList iterator+ forM_ (zip [0..] pixelRows) $ \(i, pixelRow) -> do+ pixelRow!i `setColor` "#224466"+ pixelSyncIterator iterator+ release iterator_key++ liftIO $ putStrLn "Write to wandtest_out.miff..."+ writeImages magick_wand "wandtest_out.miff" True+ liftIO $ putStrLn "Change image format from \"MIFF\" to \"GIF\"..."+ setImageFormat magick_wand "GIF"+ let wandDelay = 3+ newDelay = 100 * wandDelay+ liftIO $ putStrLn $ printf "Set delay between frames to %d seconds..." wandDelay+ setImageDelay magick_wand newDelay+ delay <- getImageDelay magick_wand+ when (delay /= newDelay) $ exitWithMessage "Get delay does not match set delay"+ liftIO $ putStrLn "Write to wandtest_out.gif..."+ writeImages magick_wand "wandtest_out.gif" True++ let customOption = "custom option"+ customOptionName = "wand:custom-option"+ liftIO $ putStrLn "Set, list, get, and delete wand option..."+ setOption magick_wand customOptionName customOption+ option <- getOption magick_wand customOptionName+ when (option /= customOption) $ exitWithMessage "Option does not match"+ options <- getOptions magick_wand "*"+ forM_ options $ \o -> liftIO $ putStrLn $ printf " %s" (T.unpack o)+ deleteOption magick_wand customOptionName++ let customPropertyName = "wand:custom-property"+ customProperty = "custom profile"+ liftIO $ putStrLn "Set, list, get, and delete wand property..."+ setImageProperty magick_wand customPropertyName customProperty+ property <- getImageProperty magick_wand customPropertyName+ when (property /= customProperty) $ exitWithMessage "Property does not match"+ properties <- getImageProperties magick_wand "*"+ forM_ properties $ \p -> liftIO $ putStrLn $ printf " %s" (T.unpack p)+ deleteImageProperty magick_wand customPropertyName++ let profileName = "sRGB"+ liftIO $ putStrLn "Set, list, get, and remove sRGB color profile..."+ setImageProfile magick_wand profileName sRGBProfile+ profile <- getImageProfile magick_wand profileName+ when (profile /= sRGBProfile) $ exitWithMessage "Profile does not match"+ profiles <- getImageProfiles magick_wand "*"+ forM_ profiles $ \p -> liftIO $ putStrLn $ printf " %s" (T.unpack p)+ removedProfile <- removeImageProfile magick_wand profileName+ when (removedProfile /= sRGBProfile) $ exitWithMessage "Profile does not match"+ liftIO $ putStrLn "Wand tests pass."++-- only first 24 bytes from wandtest.c taken (no actual need for 60k profile)+sRGBProfile :: Vector Word8+sRGBProfile = V.fromList [+ 0x00, 0x00, 0xee, 0x20, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00,+ 0x73, 0x70, 0x61, 0x63, 0x52, 0x47, 0x42, 0x20, 0x4c, 0x61, 0x62, 0x20+ ]
+ imagemagick.cabal view
@@ -0,0 +1,495 @@+Name: imagemagick+Version: 0.0.1+Synopsis: bindings to imagemagick library+License: OtherLicense+License-file: LICENSE+Author: Alexander Vershilov, Kirill Zaborsky+Maintainer: alexander.vershilov@gmail.com+-- Copyright:+Category: Graphics+Build-type: Simple+Cabal-version: >=1.8+Description: Basic image magick bindings.++Flag buildExamples+ description: Build examples+ default: False+++Library+ Exposed-modules: Graphics.ImageMagick.MagickCore+ , Graphics.ImageMagick.MagickCore.FFI.Gem+ , Graphics.ImageMagick.MagickCore.FFI.Log+ , Graphics.ImageMagick.MagickCore.FFI.MagickCore+ , Graphics.ImageMagick.MagickCore.FFI.Mime+ , Graphics.ImageMagick.MagickCore.FFI.Option+ , Graphics.ImageMagick.MagickCore.Types.FFI.CacheView+ , Graphics.ImageMagick.MagickCore.Types.FFI.Composite+ , Graphics.ImageMagick.MagickCore.Types.FFI.Compress+ , Graphics.ImageMagick.MagickCore.Types.FFI.Constitute+ , Graphics.ImageMagick.MagickCore.Types.FFI.Distort+ , Graphics.ImageMagick.MagickCore.Types.FFI.Exception+ , Graphics.ImageMagick.MagickCore.Types.FFI.Fx+ , Graphics.ImageMagick.MagickCore.Types.FFI.Geometry+ , Graphics.ImageMagick.MagickCore.Types.FFI.Image+ , Graphics.ImageMagick.MagickCore.Types.FFI.Layer+ , Graphics.ImageMagick.MagickCore.Types.FFI.Log+ , Graphics.ImageMagick.MagickCore.Types.FFI.PaintMethod+ , Graphics.ImageMagick.MagickCore.Types.FFI.PixelPacket+ , Graphics.ImageMagick.MagickCore.Types.FFI.Statistic+ , Graphics.ImageMagick.MagickCore.Types.FFI.Types+ , Graphics.ImageMagick.MagickCore.Types.FFI.ChannelType+ , Graphics.ImageMagick.MagickCore.Types.FFI.MagickFunction+ , Graphics.ImageMagick.MagickCore.Types.FFI.FilterTypes+ , Graphics.ImageMagick.MagickCore.Types.FFI.AlphaChannelType+ , Graphics.ImageMagick.MagickCore.Types.FFI.ColorspaceType+ , Graphics.ImageMagick.MagickCore.Types.MBits+ , Graphics.ImageMagick.MagickCore.Exception+ , Graphics.ImageMagick.MagickWand+ , Graphics.ImageMagick.MagickWand.FFI.ImageDrawing+ , Graphics.ImageMagick.MagickWand.FFI.DrawingWand+ , Graphics.ImageMagick.MagickWand.FFI.MagickWand+ , Graphics.ImageMagick.MagickWand.FFI.PixelIterator+ , Graphics.ImageMagick.MagickWand.FFI.PixelWand+ , Graphics.ImageMagick.MagickWand.FFI.Types+ , Graphics.ImageMagick.MagickWand.FFI.WandImage+ , Graphics.ImageMagick.MagickWand.FFI.WandProperties+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+ Build-tools: hsc2hs+++executable resize+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ Main-is: examples/resize.hs+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable extent+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ Main-is: examples/extent.hs+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable floodfill+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ Main-is: examples/floodfill.hs+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable cyclops+ Main-is: examples/cyclops.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable clipmask+ Main-is: examples/clipmask.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable paint-trans+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ Main-is: examples/trans_paint.hs+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable round-mask+ Main-is: examples/round_mask.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable make-tile+ Main-is: examples/make_tile.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand++executable draw-shapes+ Main-is: examples/draw_shapes.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable text-effects+ Main-is: examples/text_effects.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable gel+ Main-is: examples/gel.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , lifted-base >= 0.1 && <0.3+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand++executable reflect+ Main-is: examples/reflect.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable 3dlogo+ Main-is: examples/3dlogo.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable affine+ Main-is: examples/affine.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable grayscale+ Main-is: examples/grayscale.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False++ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable modulate+ Main-is: examples/modulate.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+ Buildable: False+++executable landscape3d+ Main-is: examples/landscape_3d.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable tilt-shift+ Main-is: examples/tilt_shift.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable bunny+ Main-is: examples/bunny.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable pixel-mod+ Main-is: examples/pixel_mod.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++executable wandtest+ Main-is: examples/wandtest.hs+ If flag(buildExamples)+ Buildable: True+ Else+ Buildable: False+ build-depends: base >= 4.0 && <5.0+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ extensions: EmptyDataDecls+ Ghc-options: -Wall+ pkgconfig-depends: ImageMagick, MagickWand+++test-suite image-tests+ type: exitcode-stdio-1.0+ main-is: test/ImageTest.hs+ build-depends: base >= 4.0 && <5.0+ , lifted-base >= 0.1 && <0.3+ , directory+ , resourcet >= 0.3 && <0.5+ , transformers == 0.3.*+ , vector >= 0.9 && <0.11+ , bytestring >= 0.9 && <0.11+ , text == 0.11.*+ , system-filepath == 0.4.*+ , imagemagick+ , QuickCheck >= 2+ , HUnit+ , test-framework+ , test-framework-hunit+ , test-framework-quickcheck2+ Ghc-options: -Wall+ extensions: EmptyDataDecls+ pkgconfig-depends: ImageMagick, MagickWand+++source-repository head+ type: git+ location: git://github.com/qnikst/imagemagick.git
+ test/ImageTest.hs view
@@ -0,0 +1,405 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Main (main) where+import Control.Applicative+import Control.Exception.Lifted+import Control.Monad+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Trans.Resource+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import Data.Maybe+import qualified Data.Vector.Storable as V+import Data.Word+import Filesystem.Path+import Filesystem.Path.CurrentOS (decodeString, encodeString)+import Prelude hiding (FilePath, catch)+import System.Directory (getTemporaryDirectory,+ removeFile)+import System.IO (hClose, openTempFile)++import Test.Framework (Test, defaultMain, testGroup)+import Test.Framework.Providers.HUnit+import Test.HUnit hiding (Test)++import Graphics.ImageMagick.MagickWand+++main :: IO ()+main = defaultMain tests++-- tests mostly taken from wand(http://dahlia.kr/wand/) source code+tests :: [Test]+tests =+ [+ testGroup "Behaves to spec"+ [+ testCase "reading file" test_readImage+ , testCase "getting & reading blob" test_getReadImageBlob+ , testCase "reading blob" test_readImageBlob+ , testCase "magick wand cloning" test_cloneWand+ , testCase "writing image" test_writeImage+ , testCase "width/height getters" test_size+ , testCase "image depth getter" test_getDepth+ , testCase "image depth setter" test_setDepth+ , testCase "jpeg format" test_formatJpeg+ , testCase "png format" test_formatPng+ , testCase "set format" test_setFormat+ , testCase "set bad format" test_setBadFormat+ , testCase "getting jpeg compression quality" test_getCompressionQuality+ , testCase "setting jpeg compression quality" test_setCompressionQuality+ , testCase "stripping" test_strip+ , testCase "trimming" test_trim+ , testCase "format to MIME conversion" test_mime+ , testCase "iterate" test_iterate+ , testCase "getitng pixel" test_pixel+ , testCase "cropping image" test_crop+ , testCase "resizing image" test_resize+ , testCase "rotating image" test_rotate+ , testCase "image signature" test_signature+ , testCase "getting alpha channel" test_getImageAlphaChannel+ , testCase "setting alpha channel" test_setImageAlphaChannel+ , testCase "getting background color" test_getImageBackgroundColor+ , testCase "setting background color" test_setImageBackgroundColor+ , testCase "watermark" test_watermark+ , testCase "reset" test_reset+ ]+ ]+++test_readImage :: IO ()+test_readImage = withImage "mona-lisa.jpg" $ \w -> do+ width <- getImageWidth w+ liftIO $ width @?= 402++test_readImageBlob :: IO ()+test_readImageBlob = withWand $ \w -> do+ blob <- liftIO $ BS.readFile (encodeString (dataFile "mona-lisa.jpg"))+ readImageBlob w blob+ width <- getImageWidth w+ liftIO $ width @?= 402++test_cloneWand :: IO ()+test_cloneWand = withImage "mona-lisa.jpg" $ \w -> do+ size <- getImageSize w+ (_,w') <- cloneMagickWand w+ size' <- getImageSize w'+ liftIO $ size' @?= size++test_writeImage :: IO ()+test_writeImage = withImage "mona-lisa.jpg" $ \w -> do+ size <- getImageSize w+ d <- liftIO $ getTemporaryDirectory+ (tmpName, hTemp) <- liftIO $ openTempFile d ""+ liftIO $ hClose hTemp+ writeImage w (Just (decodeString tmpName))+ (_,w') <- magickWand+ readImage w' (decodeString tmpName)+ size' <- getImageSize w'+ liftIO $ removeFile tmpName+ liftIO $ size' @?= size++test_getReadImageBlob :: IO ()+test_getReadImageBlob = withImage "mona-lisa.jpg" $ \w -> do+ size <- getImageSize w+ blob <- getImageBlob w+ (_,w') <- magickWand+ readImageBlob w' blob+ size' <- getImageSize w'+ liftIO $ size' @?= size++test_size :: IO ()+test_size = withImage "mona-lisa.jpg" $ \w -> do+ size <- getImageSize w+ liftIO $ size @?= (402,599)++test_getDepth :: IO ()+test_getDepth = withImage "mona-lisa.jpg" $ \w -> do+ depth <- getImageDepth w+ liftIO $ depth @?= 8++test_setDepth :: IO ()+test_setDepth = withImage "mona-lisa.jpg" $ \w -> do+ let newDepth = 16+ setImageDepth w newDepth+ depth <- getImageDepth w+ liftIO $ depth @?= newDepth++test_formatJpeg :: IO ()+test_formatJpeg = withImage "mona-lisa.jpg" $ \w -> do+ format <- getImageFormat w+ liftIO $ format @?= "JPEG"++test_formatPng :: IO ()+test_formatPng = withImage "croptest.png" $ \w -> do+ format <- getImageFormat w+ liftIO $ format @?= "PNG"++test_setFormat :: IO ()+test_setFormat = withImage "mona-lisa.jpg" $ \w -> do+ setImageFormat w "PNG"+ format <- getImageFormat w+ liftIO $ format @?= "PNG"+ bs <- getImageBlob w+ (_,w') <- magickWand+ readImageBlob w' bs+ format' <- getImageFormat w'+ liftIO $ format' @?= format++test_setBadFormat :: IO ()+test_setBadFormat = withImage "mona-lisa.jpg" $+ \w -> assertMagickWandException $ setImageFormat w "HANKY"++test_getCompressionQuality :: IO ()+test_getCompressionQuality = withImage "mona-lisa.jpg" $ \w -> do+ quality <- getImageCompressionQuality w+ liftIO $ quality @?= 80++test_setCompressionQuality :: IO ()+test_setCompressionQuality = withImage "mona-lisa.jpg" $ \w -> do+ let quality = 50+ setImageCompressionQuality w quality+ quality' <- getImageCompressionQuality w+ liftIO $ quality' @?= quality+ bs <- getImageBlob w+ (_,w') <- magickWand+ readImageBlob w' bs+ quality'' <- getImageCompressionQuality w'+ liftIO $ quality'' @?= quality++test_strip :: IO ()+test_strip = withImage "beach.jpg"$ \w -> do+ originalLength <- BS.length <$> getImageBlob w+ stripImage w+ strippedLength <- BS.length <$> getImageBlob w+ liftIO $ assertBool "stripped should be shorter than original" $ strippedLength < originalLength++test_trim :: IO ()+test_trim = withImage "trimtest.png" $ \w -> do+ (width,height) <- getImageSize w+ trimImage w fuzz+ (width',height') <- getImageSize w+ liftIO $ assertBool "width should be trimmed" $ width' < width+ liftIO $ assertBool "height should be trimmed" $ height' < height++test_mime :: IO ()+test_mime = withMagickWandGenesis $ do+ mime <- toMime "JPG"+ liftIO $ assertBool "jpg should convert to either image/jpeg or image/x-jpeg" $+ mime `elem` ["image/jpeg", "image/x-jpeg"]+ mime' <- toMime "PNG"+ liftIO $ assertBool "jpg should convert to either image/png or image/x-png" $+ mime' `elem` ["image/png", "image/x-png"]++test_iterate :: IO ()+test_iterate = withImage "croptest.png" $ \w -> do+ black <- getColorPW "#000"+ transparent <- getColorPW "transparent"+ (_,it) <- pixelIterator w+ rows <- pixelIterateList it+ forM_ (zip [0..] rows) $ \(i, row) -> do+ when (i `mod` 3 == 0) $ do -- condition to make test a bit faster+ let rowLength = V.length row+ liftIO $ rowLength @?= 300+ if i >= 100 && i < 200+ then do+ let+ assertPixel j pw | j >= 100 && j < 200 = assertEqualPW black pw+ assertPixel _ pw = assertEqualPW transparent pw+ V.zipWithM_ assertPixel (V.enumFromN (0::Word16) rowLength) row+ else do+ V.forM_ row $ assertEqualPW transparent+ liftIO $ (length rows) @?= 300++test_pixel :: IO ()+test_pixel = withImage "croptest.png" $ \w -> do+ transparent <- getColorPW "transparent"+ black <- getColorPW "#000"+ pw <- pixelWand+ getImagePixelColor w 0 0 pw+ assertEqualPW pw transparent+ getImagePixelColor w 99 99 pw+ assertEqualPW pw transparent+ getImagePixelColor w 100 100 pw+ assertEqualPW pw black+ getImagePixelColor w 150 150 pw+ assertEqualPW pw black+ getImagePixelColor w 201 201 pw+ assertEqualPW pw transparent++test_crop :: IO ()+test_crop = withImage "croptest.png" $ \w -> do+ black <- getColorPW "#000"+ cropImage w 100 100 100 100+ size <- getImageSize w+ liftIO $ size @?= (100,100)+ (_,it) <- pixelIterator w+ rows <- pixelIterateList it+ forM_ rows $ \row -> V.forM_ row (assertEqualPW black)++test_resize :: IO ()+test_resize = withImage "mona-lisa.jpg" $ \w -> do+ size <- getImageSize w+ liftIO $ size @?= (402,599)+ resizeImage w 100 100 undefinedFilter 1+ size' <- getImageSize w+ liftIO $ size' @?= (100,100)++test_rotate :: IO ()+test_rotate = withImage "rotatetest.gif" $ \w -> do+ transparent <- getColorPW "transparent"+ black <- getColorPW "black"+ white <- getColorPW "white"+ red <- getColorPW "red"+ size <- getImageSize w+ liftIO $ size @?= (150,100)+ localGenesis $ do+ (_,w') <- cloneMagickWand w+ rotateImage w' transparent 360+ size' <- getImageSize w'+ liftIO $ size' @?= size+ assertColorAtXY w' black ( 0,50)+ assertColorAtXY w' black (74,50)+ assertColorAtXY w' black ( 0,99)+ assertColorAtXY w' black (74,99)+ assertColorAtXY w' white (75,50)+ assertColorAtXY w' white (75,99)+ localGenesis $ do+ (_,w') <- cloneMagickWand w+ rotateImage w' transparent 90+ size' <- getImageSize w'+ liftIO $ size' @?= (100,150)+ (_,it) <- pixelIterator w'+ rows <- pixelIterateList it+ forM_ (zip [0..] rows) $ \(y,row) -> do+ let+ assertPixel x pw | x < 50 && y < 75 = assertEqualPW black pw+ assertPixel _ pw = assertEqualPW white pw+ V.zipWithM_ assertPixel (V.enumFromN (0::Word16) (V.length row)) row+ localGenesis $ do+ (_,w') <- cloneMagickWand w+ rotateImage w' red 45+ (width', height') <- getImageSize w'+ liftIO $ assertBool "size should be (>=176)x(<=178)" $+ width' >= 176 && height' <= 178+ assertColorAtXY w' red ( 0, 0)+ assertColorAtXY w' red ( 0, height'-1)+ assertColorAtXY w' red (width'-1, 0)+ assertColorAtXY w' red (width'-1, height'-1)+ assertColorAtXY w' black ( 2, 70)+ assertColorAtXY w' black (35, 37)+ assertColorAtXY w' black (85, 88)+ assertColorAtXY w' black (52,120)++test_signature :: IO ()+test_signature = withImage "mona-lisa.jpg" $ \w -> do+ let signature = "f7695e173f691f59c5939e1898eafa6491bdf1439c60ecce7edfe4b3d101bf22"+ testedSignature <- getImageSignature w+ liftIO $ testedSignature @?= signature++test_getImageAlphaChannel :: IO ()+test_getImageAlphaChannel = do+ withImage "watermark.png" $ \w -> do+ alphaCh <- getImageAlphaChannel w+ liftIO $ alphaCh @?= True+ withImage "mona-lisa.jpg" $ \w -> do+ alphaCh <- getImageAlphaChannel w+ liftIO $ alphaCh @?= False++test_setImageAlphaChannel :: IO ()+test_setImageAlphaChannel = withImage "watermark.png" $ \w -> do+ alphaCh <- getImageAlphaChannel w+ liftIO $ alphaCh @?= True+ setImageAlphaChannel w activateAlphaChannel+ alphaCh' <- getImageAlphaChannel w+ liftIO $ alphaCh' @?= False++test_getImageBackgroundColor :: IO ()+test_getImageBackgroundColor = withImage "mona-lisa.jpg" $ \w -> do+ white <- getColorPW "white"+ bg <- getImageBackgroundColor w+ assertEqualPW bg white++test_setImageBackgroundColor :: IO ()+test_setImageBackgroundColor = withImage "croptest.png" $ \w -> do+ transparent <- getColorPW "transparent"+ setImageBackgroundColor w transparent+ bg <- getImageBackgroundColor w+ assertEqualPW bg transparent++test_watermark :: IO ()+test_watermark = withImage "beach.jpg" $ \w -> do+ (_,watermark) <- magickWand+ readImage watermark (dataFile "watermark.png")+ setIteratorIndex watermark 0+ setImageType watermark trueColorMatteType+ evaluateImageChannel watermark opacityChannel subtractEvaluateOperator (0.3 * quantumRange)+ compositeImage w watermark overCompositeOp 0 0+ (_,marked) <- magickWand+ readImage marked (dataFile "marked.png")+ sig1 <- getImageSignature marked+ sig2 <- getImageSignature w+ liftIO $ sig2 @?= sig1++test_reset :: IO ()+test_reset = withImage "sasha.jpg" $ \w -> do+ transparent <- getColorPW "transparent"+ rotateImage w transparent 45+ resetImagePage w Nothing+ cropImage w 170 170 0 0+ resetImagePage w Nothing+ sig1 <- getImageSignature w+ (_,control) <- magickWand+ readImage control (dataFile "resettest.png")+ sig2 <- getImageSignature control+ liftIO $ sig1 @?= sig2++-- helpers++fuzz :: Double+fuzz = 10++dataFile :: String -> FilePath+dataFile name = decodeString ("data/" ++ name)++withWand f = withMagickWandGenesis $ do+ (_,w) <- magickWand+ f w++withImage name f = withWand $ \w -> do+ readImage w (dataFile name)+ f w++getImageSize :: (MonadResource m) => PMagickWand -> m (Int, Int)+getImageSize w = do+ width <- getImageWidth w+ height <- getImageHeight w+ return (width,height)++-- TODO fix to Text+getColorPW :: (MonadResource m) => ByteString -> m PPixelWand+getColorPW color = do+ pw <- pixelWand+ pw `setColor` color+ return pw++assertMagickWandException :: (MonadResource m, MonadBaseControl IO m) => m a -> m ()+assertMagickWandException action =+ catch (action >> (liftIO $ assertFailure "Expected MagickWandException"))+ (\(_::MagickWandException) -> return ())++assertEqualPW :: (MonadResource m) => PPixelWand -> PPixelWand -> m ()+assertEqualPW pw1 pw2 = do+ a1 <- getAlpha pw1+ a2 <- getAlpha pw2+ similar <- isPixelWandSimilar pw1 pw2 fuzz+-- let x = show (a1,a2,similar)+ liftIO $ assertBool "colors should be similar" $ (a1 == a2) && similar++assertColorAtXY :: (MonadResource m) => PMagickWand -> PPixelWand -> (Int,Int) -> m ()+assertColorAtXY w pw1 (x,y) = do+ pw2 <- pixelWand+ getImagePixelColor w x y pw2+ assertEqualPW pw1 pw2