PageRenderTime 28ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/examples/text_effects.hs

https://gitlab.com/stallmanifold/imagemagick
Haskell | 313 lines | 154 code | 37 blank | 122 comment | 0 complexity | dc821fa4c6cc27981806b845f067b7a5 MD5 | raw file
  1. {-# LANGUAGE FlexibleContexts #-}
  2. {-# LANGUAGE OverloadedStrings #-}
  3. -- | Example taken from: http://members.shaw.ca/el.supremo/MagickWand/text_effects.htm
  4. {- There's no equivalent convert command for this. It is a demo of MagickWand.
  5. See this forum thread for the genesis of these effects
  6. http://www.imagemagick.org/discourse-server/viewtopic.php?f=6&t=11586
  7. and Anthony's Text Effects page at:
  8. http://www.imagemagick.org/Usage/fonts/
  9. -}
  10. import Control.Monad (when)
  11. import Control.Monad.IO.Class (MonadIO)
  12. import Control.Monad.Trans.Resource
  13. import Data.ByteString (ByteString)
  14. import Data.Text (Text)
  15. import qualified Data.Text as T
  16. import Graphics.ImageMagick.MagickCore.Types
  17. import Graphics.ImageMagick.MagickWand
  18. -- see http://www.imagemagick.org/Usage/#font about using fonts with IM
  19. font :: ByteString
  20. font = "VerdanaBI"
  21. -- Text effect 1 - shadow effect using MagickShadowImage
  22. -- This is derived from Anthony's Soft Shadow effect
  23. -- convert -size 300x100 xc:none -font Candice -pointsize 72 \
  24. -- -fill white -stroke black -annotate +25+65 'Anthony' \
  25. -- \( +clone -background navy -shadow 70x4+5+5 \) +swap \
  26. -- -background lightblue -flatten -trim +repage font_shadow_soft.jpg
  27. -- NOTE - if an image has a transparent background, adding a border of any colour other
  28. -- than "none" will remove all the transparency and replace it with the border's colour
  29. textEffect1 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()
  30. textEffect1 w dw pw = do
  31. pw `setColor` "none"
  32. -- Create a new transparent image
  33. newImage w 350 100 pw
  34. -- Set up a 72 point white font
  35. pw `setColor` "white"
  36. dw `setFillColor` pw
  37. dw `setFont` font
  38. dw `setFontSize` 72
  39. -- Add a black outline to the text
  40. pw `setColor` "black"
  41. dw `setStrokeColor` pw
  42. -- Turn antialias on - not sure this makes a difference
  43. dw `setTextAntialias` True
  44. -- Now draw the text
  45. drawAnnotation dw 25 65 "Magick"
  46. -- Draw the image on to the magick_wand
  47. drawImage w dw
  48. -- Trim the image down to include only the text
  49. trimImage w 0
  50. -- equivalent to the command line +repage
  51. resetImagePage w Nothing
  52. -- Make a copy of the text image
  53. (_,cloneW) <- cloneMagickWand w
  54. -- Set the background colour to blue for the shadow
  55. pw `setColor` "blue"
  56. w `setImageBackgroundColor` pw
  57. -- Opacity is a real number indicating (apparently) percentage
  58. shadowImage w 70 4 5 5
  59. -- Composite the text on top of the shadow
  60. compositeImage w cloneW overCompositeOp 5 5
  61. (_,w') <- magickWand
  62. -- Create a new image the same size as the text image and put a solid colour
  63. -- as its background
  64. pw `setColor` "rgb(125,215,255)"
  65. width <- getImageWidth w
  66. height <- getImageHeight w
  67. newImage w' width height pw
  68. -- Now composite the shadowed text over the plain background
  69. compositeImage w' w overCompositeOp 0 0
  70. -- and write the result
  71. writeImage w' (Just "text_shadow.png")
  72. -- Given a pattern name (which MUST have a leading #) and a pattern file,
  73. -- set up a pattern URL for later reference in the specified drawing wand
  74. -- Currently only used in Text Effect 2
  75. setTilePattern :: (MonadResource m) => PDrawingWand -> Text -> FilePath -> m ()
  76. setTilePattern dw patternName patternFile = do
  77. (_,w) <- magickWand
  78. readImage w (T.pack patternFile)
  79. -- Read the tile's width and height
  80. width <- getImageWidth w
  81. height <- getImageHeight w
  82. pushPattern dw (T.tail patternName) 0 0 (realToFrac width) (realToFrac height)
  83. drawComposite dw srcOverCompositeOp 0 0 0 0 w
  84. popPattern dw
  85. dw `setFillPatternURL` patternName
  86. -- Text effect 2 - tiled text using the builtin checkerboard pattern
  87. -- Anthony's Tiled Font effect
  88. -- convert -size 320x100 xc:lightblue -font Candice -pointsize 72 \
  89. -- -tile pattern:checkerboard -annotate +28+68 'Anthony' \
  90. -- font_tile.jpg
  91. textEffect2 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()
  92. textEffect2 w dw pw = do
  93. setTilePattern dw "#check" "pattern:checkerboard"
  94. pw `setColor` "lightblue"
  95. -- Create a new transparent image
  96. newImage w 320 100 pw
  97. -- Set up a 72 point font
  98. dw `setFont` font
  99. dw `setFontSize` 72
  100. -- Now draw the text
  101. drawAnnotation dw 28 68 "Magick"
  102. -- Draw the image on to the magick_wand
  103. drawImage w dw
  104. -- Trim the image
  105. trimImage w 0
  106. -- Add a transparent border
  107. pw `setColor` "lightblue"
  108. borderImage w pw 5 5
  109. -- and write it
  110. writeImage w (Just "text_pattern.png")
  111. -- Text effect 3 - arc font (similar to http://www.imagemagick.org/Usage/fonts/#arc)
  112. -- convert -size 320x100 xc:lightblue -font Candice -pointsize 72 \
  113. -- -annotate +25+65 'Anthony' -distort Arc 120 \
  114. -- -trim +repage -bordercolor lightblue -border 10 font_arc.jpg
  115. textEffect3 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()
  116. textEffect3 w dw pw = do
  117. -- Create a 320x100 lightblue canvas
  118. pw `setColor` "lightblue"
  119. newImage w 320 100 pw
  120. -- Set up a 72 point font
  121. dw `setFont` font
  122. dw `setFontSize` 72
  123. -- Now draw the text
  124. drawAnnotation dw 25 65 "Magick"
  125. -- Draw the image on to the magick_wand
  126. drawImage w dw
  127. let dargs = [120]
  128. distortImage w arcDistortion dargs False
  129. -- Trim the image
  130. trimImage w 0
  131. -- Add the border
  132. pw `setColor` "lightblue"
  133. borderImage w pw 10 10
  134. -- and write it
  135. writeImage w (Just "text_arc.png")
  136. -- Text effect 4 - bevelled font http://www.imagemagick.org/Usage/fonts/#bevel
  137. -- convert -size 320x100 xc:black -font Candice -pointsize 72 \
  138. -- -fill white -annotate +25+65 'Anthony' \
  139. -- -shade 140x60 font_beveled.jpg
  140. textEffect4 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()
  141. textEffect4 w dw pw = do
  142. let colorize = False
  143. -- Create a 320x100 canvas
  144. pw `setColor` "gray"
  145. newImage w 320 100 pw
  146. -- Set up a 72 point font
  147. dw `setFont` font
  148. dw `setFontSize` 72
  149. -- Set up a 72 point white font
  150. pw `setColor` "white"
  151. dw `setFillColor` pw
  152. -- Now draw the text
  153. drawAnnotation dw 25 65 "Magick"
  154. -- Draw the image on to the magick_wand
  155. drawImage w dw
  156. -- the "gray" parameter must be true to get the effect shown on Anthony's page
  157. shadeImage w True 140 60
  158. when colorize $ do
  159. pw `setColor` "yellow"
  160. dw `setFillColor` pw
  161. pw' <- pixelWand
  162. pw' `setColor` "gold"
  163. colorizeImage w pw pw'
  164. -- and write it
  165. writeImage w (Just "text_bevel.png")
  166. -- Text effect 5 and 6 - Plain text and then Barrel distortion
  167. textEffects5_6 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()
  168. textEffects5_6 w dw pw = do
  169. -- Create a 320x100 transparent canvas
  170. pw `setColor` "none"
  171. newImage w 320 100 pw
  172. -- Set up a 72 point font
  173. dw `setFont` font
  174. dw `setFontSize` 72
  175. -- Now draw the text
  176. drawAnnotation dw 25 65 "Magick"
  177. -- Draw the image on to the magick_wand
  178. drawImage w dw
  179. writeImage w (Just"text_plain.png")
  180. -- Trim the image
  181. trimImage w 0
  182. -- Add the border
  183. pw `setColor` "none"
  184. borderImage w pw 10 10
  185. -- MagickSetImageMatte(magick_wand,MagickTrue);
  186. -- MagickSetImageVirtualPixelMethod(magick_wand,TransparentVirtualPixelMethod);
  187. -- d_args[0] = 0.1;d_args[1] = -0.25;d_args[2] = -0.25; [3] += .1
  188. -- The first value should be positive. If it is negative the image is *really* distorted
  189. -- d_args[0] = 0.0;
  190. -- d_args[1] = 0.0;
  191. -- d_args[2] = 0.5;
  192. -- d_args[3] should normally be chosen such the sum of all 4 values is 1
  193. -- so that the result is the same size as the original
  194. -- You can override the sum with a different value
  195. -- If the sum is greater than 1 the resulting image will be smaller than the original
  196. -- d_args[3] = 1 - (d_args[0] + d_args[1] + d_args[2]);
  197. -- Make the result image smaller so that it isn't as likely
  198. -- to overflow the edges
  199. -- d_args[3] += 0.1;
  200. -- 0.0,0.0,0.5,0.5,0.0,0.0,-0.5,1.9
  201. -- d_args[3] = 0.5;
  202. -- d_args[4] = 0.0;
  203. -- d_args[5] = 0.0;
  204. -- d_args[6] = -0.5;
  205. -- d_args[7] = 1.9;
  206. let d_args = [0, 0, 0.5, 1 - (0 + 0 + 0.5), 0, 0, -0.5, 1.9]
  207. -- DON'T FORGET to set the correct number of arguments here
  208. distortImage w barrelDistortion d_args True
  209. -- MagickResetImagePage(magick_wand,"");
  210. -- Trim the image again
  211. trimImage w 0
  212. -- Add the border
  213. pw `setColor` "none"
  214. borderImage w pw 10 10
  215. -- and write it
  216. writeImage w (Just "text_barrel.png")
  217. -- Text effect 7 - Polar distortion
  218. textEffect7 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()
  219. textEffect7 w dw pw = do
  220. -- Create a 320x200 transparent canvas
  221. pw `setColor` "none"
  222. newImage w 320 200 pw
  223. -- Set up a 72 point font
  224. dw `setFont` font
  225. dw `setFontSize` 72
  226. -- Now draw the text
  227. drawAnnotation dw 25 65 "Magick"
  228. -- Draw the image on to the magick_wand
  229. drawImage w dw
  230. distortImage w polarDistortion [0] True
  231. -- MagickResetImagePage(magick_wand,"");
  232. -- Trim the image again
  233. trimImage w 0
  234. -- Add the border
  235. pw `setColor` "none"
  236. borderImage w pw 10 10
  237. -- and write it
  238. writeImage w (Just "text_polar.png")
  239. -- Text effect 8 - Shepard's distortion
  240. textEffect8 :: (MonadResource m) => PMagickWand -> PDrawingWand -> PPixelWand -> m ()
  241. textEffect8 w dw pw = do
  242. -- Create a 320x200 transparent canvas
  243. pw `setColor` "none"
  244. newImage w 640 480 pw
  245. -- Set up a 72 point font
  246. dw `setFont` font
  247. dw `setFontSize` 72
  248. -- Now draw the text
  249. drawAnnotation dw 50 240 "Magick Rocks"
  250. -- Draw the image on to the magick_wand
  251. drawImage w dw
  252. let d_args = [ 150.0, 190.0, 100.0, 290.0, 500.0, 200.0, 430.0, 130.0 ]
  253. distortImage w shepardsDistortion d_args True
  254. -- Trim the image
  255. trimImage w 0
  256. -- Add the border
  257. pw `setColor` "none"
  258. borderImage w pw 10 10
  259. -- and write it
  260. writeImage w (Just "text_shepards.png")
  261. runEffect :: (MonadIO m, MonadThrow m, MonadBaseControl IO m) =>
  262. (PMagickWand -> PDrawingWand -> PPixelWand -> ResourceT m ()) -> m ()
  263. runEffect e = localGenesis $ do
  264. (_,w) <- magickWand
  265. (_,dw) <- drawingWand
  266. pw <- pixelWand
  267. e w dw pw
  268. main :: IO ()
  269. main = withMagickWandGenesis $ do
  270. runEffect textEffect1
  271. runEffect textEffect2
  272. runEffect textEffect3
  273. runEffect textEffect4
  274. runEffect textEffects5_6
  275. runEffect textEffect7
  276. runEffect textEffect8