{-# 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