rdp-rmagick 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (388) hide show
  1. data/ChangeLog +769 -0
  2. data/Doxyfile +1514 -0
  3. data/README-Mac-OSX.txt +1 -0
  4. data/README.md +231 -0
  5. data/build_tarball.rake +215 -0
  6. data/doc/comtasks.html +287 -0
  7. data/doc/constants.html +1581 -0
  8. data/doc/css/doc.css +299 -0
  9. data/doc/css/popup.css +34 -0
  10. data/doc/css/ref.css +67 -0
  11. data/doc/draw.html +3269 -0
  12. data/doc/ex/InitialCoords.rb +23 -0
  13. data/doc/ex/NewCoordSys.rb +32 -0
  14. data/doc/ex/OrigCoordSys.rb +18 -0
  15. data/doc/ex/PreserveAspectRatio.rb +205 -0
  16. data/doc/ex/RotateScale.rb +37 -0
  17. data/doc/ex/Skew.rb +38 -0
  18. data/doc/ex/Use01.rb +16 -0
  19. data/doc/ex/Use02.rb +21 -0
  20. data/doc/ex/Use03.rb +16 -0
  21. data/doc/ex/ViewBox.rb +33 -0
  22. data/doc/ex/adaptive_threshold.rb +10 -0
  23. data/doc/ex/add_noise.rb +17 -0
  24. data/doc/ex/affine.rb +48 -0
  25. data/doc/ex/affine_transform.rb +20 -0
  26. data/doc/ex/arc.rb +49 -0
  27. data/doc/ex/arcpath.rb +33 -0
  28. data/doc/ex/arcs01.rb +28 -0
  29. data/doc/ex/arcs02.rb +61 -0
  30. data/doc/ex/average.rb +15 -0
  31. data/doc/ex/axes.rb +64 -0
  32. data/doc/ex/baseline_shift01.rb +18 -0
  33. data/doc/ex/bilevel_channel.rb +9 -0
  34. data/doc/ex/blur_image.rb +12 -0
  35. data/doc/ex/border.rb +10 -0
  36. data/doc/ex/bounding_box.rb +44 -0
  37. data/doc/ex/cbezier1.rb +42 -0
  38. data/doc/ex/cbezier2.rb +42 -0
  39. data/doc/ex/cbezier3.rb +42 -0
  40. data/doc/ex/cbezier4.rb +43 -0
  41. data/doc/ex/cbezier5.rb +43 -0
  42. data/doc/ex/cbezier6.rb +53 -0
  43. data/doc/ex/channel.rb +26 -0
  44. data/doc/ex/charcoal.rb +12 -0
  45. data/doc/ex/chop.rb +29 -0
  46. data/doc/ex/circle.rb +33 -0
  47. data/doc/ex/circle01.rb +17 -0
  48. data/doc/ex/clip_path.rb +60 -0
  49. data/doc/ex/coalesce.rb +60 -0
  50. data/doc/ex/color_fill_to_border.rb +29 -0
  51. data/doc/ex/color_floodfill.rb +28 -0
  52. data/doc/ex/color_histogram.rb +48 -0
  53. data/doc/ex/color_reset.rb +11 -0
  54. data/doc/ex/colorize.rb +16 -0
  55. data/doc/ex/colors.rb +64 -0
  56. data/doc/ex/compose_mask.rb +23 -0
  57. data/doc/ex/composite.rb +135 -0
  58. data/doc/ex/composite_layers.rb +53 -0
  59. data/doc/ex/composite_tiled.rb +23 -0
  60. data/doc/ex/contrast.rb +36 -0
  61. data/doc/ex/crop.rb +31 -0
  62. data/doc/ex/crop_with_gravity.rb +46 -0
  63. data/doc/ex/cubic01.rb +45 -0
  64. data/doc/ex/cubic02.rb +94 -0
  65. data/doc/ex/cycle_colormap.rb +21 -0
  66. data/doc/ex/dissolve.rb +13 -0
  67. data/doc/ex/drawcomp.rb +42 -0
  68. data/doc/ex/drop_shadow.rb +60 -0
  69. data/doc/ex/edge.rb +11 -0
  70. data/doc/ex/ellipse.rb +45 -0
  71. data/doc/ex/ellipse01.rb +22 -0
  72. data/doc/ex/emboss.rb +11 -0
  73. data/doc/ex/enhance.rb +28 -0
  74. data/doc/ex/equalize.rb +11 -0
  75. data/doc/ex/evenodd.rb +43 -0
  76. data/doc/ex/fill_pattern.rb +26 -0
  77. data/doc/ex/flatten_images.rb +36 -0
  78. data/doc/ex/flip.rb +11 -0
  79. data/doc/ex/flop.rb +11 -0
  80. data/doc/ex/font_styles.rb +34 -0
  81. data/doc/ex/fonts.rb +20 -0
  82. data/doc/ex/frame.rb +12 -0
  83. data/doc/ex/gaussian_blur.rb +11 -0
  84. data/doc/ex/get_multiline_type_metrics.rb +42 -0
  85. data/doc/ex/get_pixels.rb +48 -0
  86. data/doc/ex/get_type_metrics.rb +146 -0
  87. data/doc/ex/gradientfill.rb +27 -0
  88. data/doc/ex/grav.rb +46 -0
  89. data/doc/ex/gravity.rb +79 -0
  90. data/doc/ex/group.rb +26 -0
  91. data/doc/ex/hatchfill.rb +27 -0
  92. data/doc/ex/image.rb +46 -0
  93. data/doc/ex/images/Apple.miff +0 -0
  94. data/doc/ex/images/Ballerina.jpg +0 -0
  95. data/doc/ex/images/Ballerina3.jpg +0 -0
  96. data/doc/ex/images/Button_0.gif +0 -0
  97. data/doc/ex/images/Button_1.gif +0 -0
  98. data/doc/ex/images/Button_2.gif +0 -0
  99. data/doc/ex/images/Button_3.gif +0 -0
  100. data/doc/ex/images/Button_4.gif +0 -0
  101. data/doc/ex/images/Button_5.gif +0 -0
  102. data/doc/ex/images/Button_6.gif +0 -0
  103. data/doc/ex/images/Button_7.gif +0 -0
  104. data/doc/ex/images/Button_8.gif +0 -0
  105. data/doc/ex/images/Button_9.gif +0 -0
  106. data/doc/ex/images/Button_A.gif +0 -0
  107. data/doc/ex/images/Button_B.gif +0 -0
  108. data/doc/ex/images/Button_C.gif +0 -0
  109. data/doc/ex/images/Button_D.gif +0 -0
  110. data/doc/ex/images/Button_E.gif +0 -0
  111. data/doc/ex/images/Button_F.gif +0 -0
  112. data/doc/ex/images/Button_G.gif +0 -0
  113. data/doc/ex/images/Button_H.gif +0 -0
  114. data/doc/ex/images/Button_I.gif +0 -0
  115. data/doc/ex/images/Button_J.gif +0 -0
  116. data/doc/ex/images/Button_K.gif +0 -0
  117. data/doc/ex/images/Button_L.gif +0 -0
  118. data/doc/ex/images/Button_M.gif +0 -0
  119. data/doc/ex/images/Button_N.gif +0 -0
  120. data/doc/ex/images/Button_O.gif +0 -0
  121. data/doc/ex/images/Button_P.gif +0 -0
  122. data/doc/ex/images/Button_Q.gif +0 -0
  123. data/doc/ex/images/Button_R.gif +0 -0
  124. data/doc/ex/images/Button_S.gif +0 -0
  125. data/doc/ex/images/Button_T.gif +0 -0
  126. data/doc/ex/images/Button_U.gif +0 -0
  127. data/doc/ex/images/Button_V.gif +0 -0
  128. data/doc/ex/images/Button_W.gif +0 -0
  129. data/doc/ex/images/Button_X.gif +0 -0
  130. data/doc/ex/images/Button_Y.gif +0 -0
  131. data/doc/ex/images/Button_Z.gif +0 -0
  132. data/doc/ex/images/Cheetah.jpg +0 -0
  133. data/doc/ex/images/Coffee.wmf +0 -0
  134. data/doc/ex/images/Flower_Hat.jpg +0 -0
  135. data/doc/ex/images/Gold_Statue.jpg +0 -0
  136. data/doc/ex/images/Hot_Air_Balloons.jpg +0 -0
  137. data/doc/ex/images/Hot_Air_Balloons_H.jpg +0 -0
  138. data/doc/ex/images/Leaf.miff +0 -0
  139. data/doc/ex/images/No.wmf +0 -0
  140. data/doc/ex/images/Polynesia.jpg +0 -0
  141. data/doc/ex/images/Red_Rocks.jpg +0 -0
  142. data/doc/ex/images/Rocks_On_Beach.miff +0 -0
  143. data/doc/ex/images/Shorts.jpg +0 -0
  144. data/doc/ex/images/Snake.wmf +0 -0
  145. data/doc/ex/images/Violin.jpg +0 -0
  146. data/doc/ex/images/Yellow_Rose.miff +0 -0
  147. data/doc/ex/images/big-duck.gif +0 -0
  148. data/doc/ex/images/duck.gif +0 -0
  149. data/doc/ex/images/duck0.gif +0 -0
  150. data/doc/ex/images/duck1.gif +0 -0
  151. data/doc/ex/images/duck10.gif +0 -0
  152. data/doc/ex/images/duck11.gif +0 -0
  153. data/doc/ex/images/duck12.gif +0 -0
  154. data/doc/ex/images/duck13.gif +0 -0
  155. data/doc/ex/images/duck14.gif +0 -0
  156. data/doc/ex/images/duck15.gif +0 -0
  157. data/doc/ex/images/duck2.gif +0 -0
  158. data/doc/ex/images/duck3.gif +0 -0
  159. data/doc/ex/images/duck4.gif +0 -0
  160. data/doc/ex/images/duck5.gif +0 -0
  161. data/doc/ex/images/duck6.gif +0 -0
  162. data/doc/ex/images/duck7.gif +0 -0
  163. data/doc/ex/images/duck8.gif +0 -0
  164. data/doc/ex/images/duck9.gif +0 -0
  165. data/doc/ex/images/graydient230x6.gif +0 -0
  166. data/doc/ex/images/logo400x83.gif +0 -0
  167. data/doc/ex/images/model.miff +0 -0
  168. data/doc/ex/images/notimplemented.gif +0 -0
  169. data/doc/ex/images/smile.miff +0 -0
  170. data/doc/ex/images/spin.gif +0 -0
  171. data/doc/ex/implode.rb +34 -0
  172. data/doc/ex/level.rb +11 -0
  173. data/doc/ex/level_colors.rb +11 -0
  174. data/doc/ex/line.rb +42 -0
  175. data/doc/ex/line01.rb +23 -0
  176. data/doc/ex/mask.rb +36 -0
  177. data/doc/ex/matte_fill_to_border.rb +40 -0
  178. data/doc/ex/matte_floodfill.rb +33 -0
  179. data/doc/ex/matte_replace.rb +40 -0
  180. data/doc/ex/median_filter.rb +28 -0
  181. data/doc/ex/modulate.rb +11 -0
  182. data/doc/ex/mono.rb +23 -0
  183. data/doc/ex/morph.rb +26 -0
  184. data/doc/ex/mosaic.rb +35 -0
  185. data/doc/ex/motion_blur.rb +11 -0
  186. data/doc/ex/negate.rb +11 -0
  187. data/doc/ex/negate_channel.rb +9 -0
  188. data/doc/ex/nested_rvg.rb +21 -0
  189. data/doc/ex/nonzero.rb +43 -0
  190. data/doc/ex/normalize.rb +11 -0
  191. data/doc/ex/oil_paint.rb +11 -0
  192. data/doc/ex/opacity.rb +37 -0
  193. data/doc/ex/ordered_dither.rb +11 -0
  194. data/doc/ex/path.rb +64 -0
  195. data/doc/ex/pattern1.rb +25 -0
  196. data/doc/ex/pattern2.rb +26 -0
  197. data/doc/ex/polaroid.rb +28 -0
  198. data/doc/ex/polygon.rb +24 -0
  199. data/doc/ex/polygon01.rb +23 -0
  200. data/doc/ex/polyline.rb +23 -0
  201. data/doc/ex/polyline01.rb +23 -0
  202. data/doc/ex/posterize.rb +8 -0
  203. data/doc/ex/preview.rb +9 -0
  204. data/doc/ex/qbezierpath.rb +52 -0
  205. data/doc/ex/quad01.rb +36 -0
  206. data/doc/ex/quantize-m.rb +25 -0
  207. data/doc/ex/radial_blur.rb +9 -0
  208. data/doc/ex/raise.rb +8 -0
  209. data/doc/ex/random_threshold_channel.rb +13 -0
  210. data/doc/ex/rect01.rb +15 -0
  211. data/doc/ex/rect02.rb +22 -0
  212. data/doc/ex/rectangle.rb +35 -0
  213. data/doc/ex/reduce_noise.rb +28 -0
  214. data/doc/ex/remap.rb +12 -0
  215. data/doc/ex/remap_images.rb +21 -0
  216. data/doc/ex/resize_to_fill.rb +10 -0
  217. data/doc/ex/resize_to_fit.rb +10 -0
  218. data/doc/ex/roll.rb +9 -0
  219. data/doc/ex/rotate.rb +45 -0
  220. data/doc/ex/rotate_f.rb +14 -0
  221. data/doc/ex/roundrect.rb +34 -0
  222. data/doc/ex/rubyname.rb +30 -0
  223. data/doc/ex/rvg_clippath.rb +14 -0
  224. data/doc/ex/rvg_linecap.rb +43 -0
  225. data/doc/ex/rvg_linejoin.rb +41 -0
  226. data/doc/ex/rvg_opacity.rb +19 -0
  227. data/doc/ex/rvg_pattern.rb +26 -0
  228. data/doc/ex/rvg_stroke_dasharray.rb +12 -0
  229. data/doc/ex/segment.rb +11 -0
  230. data/doc/ex/sepiatone.rb +8 -0
  231. data/doc/ex/shade.rb +11 -0
  232. data/doc/ex/shadow.rb +31 -0
  233. data/doc/ex/shave.rb +15 -0
  234. data/doc/ex/shear.rb +10 -0
  235. data/doc/ex/sketch.rb +18 -0
  236. data/doc/ex/skewx.rb +52 -0
  237. data/doc/ex/skewy.rb +47 -0
  238. data/doc/ex/smile.rb +125 -0
  239. data/doc/ex/solarize.rb +11 -0
  240. data/doc/ex/sparse_color.rb +55 -0
  241. data/doc/ex/splice.rb +9 -0
  242. data/doc/ex/spread.rb +11 -0
  243. data/doc/ex/stegano.rb +55 -0
  244. data/doc/ex/stroke_dasharray.rb +43 -0
  245. data/doc/ex/stroke_fill.rb +11 -0
  246. data/doc/ex/stroke_linecap.rb +44 -0
  247. data/doc/ex/stroke_linejoin.rb +48 -0
  248. data/doc/ex/stroke_width.rb +49 -0
  249. data/doc/ex/swirl.rb +17 -0
  250. data/doc/ex/text.rb +37 -0
  251. data/doc/ex/text01.rb +17 -0
  252. data/doc/ex/text_align.rb +36 -0
  253. data/doc/ex/text_antialias.rb +38 -0
  254. data/doc/ex/text_styles.rb +21 -0
  255. data/doc/ex/text_undercolor.rb +28 -0
  256. data/doc/ex/texture_fill_to_border.rb +34 -0
  257. data/doc/ex/texture_floodfill.rb +32 -0
  258. data/doc/ex/texturefill.rb +25 -0
  259. data/doc/ex/threshold.rb +13 -0
  260. data/doc/ex/to_blob.rb +14 -0
  261. data/doc/ex/translate.rb +39 -0
  262. data/doc/ex/transparent.rb +38 -0
  263. data/doc/ex/transpose.rb +9 -0
  264. data/doc/ex/transverse.rb +9 -0
  265. data/doc/ex/tref01.rb +25 -0
  266. data/doc/ex/triangle01.rb +16 -0
  267. data/doc/ex/trim.rb +24 -0
  268. data/doc/ex/tspan01.rb +18 -0
  269. data/doc/ex/tspan02.rb +19 -0
  270. data/doc/ex/tspan03.rb +21 -0
  271. data/doc/ex/unsharp_mask.rb +28 -0
  272. data/doc/ex/viewex.rb +35 -0
  273. data/doc/ex/vignette.rb +12 -0
  274. data/doc/ex/watermark.rb +28 -0
  275. data/doc/ex/wave.rb +9 -0
  276. data/doc/ex/wet_floor.rb +59 -0
  277. data/doc/ex/writing_mode01.rb +27 -0
  278. data/doc/ex/writing_mode02.rb +26 -0
  279. data/doc/ilist.html +2056 -0
  280. data/doc/image1.html +4680 -0
  281. data/doc/image2.html +3665 -0
  282. data/doc/image3.html +4522 -0
  283. data/doc/imageattrs.html +1638 -0
  284. data/doc/imusage.html +514 -0
  285. data/doc/index.html +416 -0
  286. data/doc/info.html +1499 -0
  287. data/doc/magick.html +565 -0
  288. data/doc/optequiv.html +2435 -0
  289. data/doc/rvg.html +975 -0
  290. data/doc/rvgclip.html +248 -0
  291. data/doc/rvggroup.html +305 -0
  292. data/doc/rvgimage.html +289 -0
  293. data/doc/rvgpattern.html +475 -0
  294. data/doc/rvgshape.html +406 -0
  295. data/doc/rvgstyle.html +270 -0
  296. data/doc/rvgtext.html +465 -0
  297. data/doc/rvgtspan.html +238 -0
  298. data/doc/rvgtut.html +530 -0
  299. data/doc/rvguse.html +145 -0
  300. data/doc/rvgxform.html +294 -0
  301. data/doc/scripts/doc.js +22 -0
  302. data/doc/scripts/stripeTables.js +23 -0
  303. data/doc/struct.html +1339 -0
  304. data/doc/usage.html +1621 -0
  305. data/examples/constitute.rb +7 -0
  306. data/examples/crop_with_gravity.rb +46 -0
  307. data/examples/demo.rb +324 -0
  308. data/examples/describe.rb +44 -0
  309. data/examples/find_similar_region.rb +34 -0
  310. data/examples/histogram.rb +325 -0
  311. data/examples/identify.rb +187 -0
  312. data/examples/image_opacity.rb +29 -0
  313. data/examples/import_export.rb +31 -0
  314. data/examples/pattern_fill.rb +38 -0
  315. data/examples/rotating_text.rb +45 -0
  316. data/examples/spinner.rb +50 -0
  317. data/examples/thumbnail.rb +65 -0
  318. data/examples/vignette.rb +79 -0
  319. data/ext/RMagick/Makefile +180 -0
  320. data/ext/RMagick/RMagick2.so +0 -0
  321. data/ext/RMagick/extconf.h +119 -0
  322. data/ext/RMagick/extconf.rb +406 -0
  323. data/ext/RMagick/mkmf.log +3022 -0
  324. data/ext/RMagick/rmagick.c +394 -0
  325. data/ext/RMagick/rmagick.h +1307 -0
  326. data/ext/RMagick/rmagick.o +0 -0
  327. data/ext/RMagick/rmdraw.c +1991 -0
  328. data/ext/RMagick/rmdraw.o +0 -0
  329. data/ext/RMagick/rmenum.c +1224 -0
  330. data/ext/RMagick/rmenum.o +0 -0
  331. data/ext/RMagick/rmfill.c +717 -0
  332. data/ext/RMagick/rmfill.o +0 -0
  333. data/ext/RMagick/rmilist.c +1217 -0
  334. data/ext/RMagick/rmilist.o +0 -0
  335. data/ext/RMagick/rmimage.c +15099 -0
  336. data/ext/RMagick/rmimage.o +0 -0
  337. data/ext/RMagick/rminfo.c +2567 -0
  338. data/ext/RMagick/rminfo.o +0 -0
  339. data/ext/RMagick/rmmain.c +1705 -0
  340. data/ext/RMagick/rmmain.o +0 -0
  341. data/ext/RMagick/rmmontage.c +511 -0
  342. data/ext/RMagick/rmmontage.o +0 -0
  343. data/ext/RMagick/rmpixel.c +1103 -0
  344. data/ext/RMagick/rmpixel.o +0 -0
  345. data/ext/RMagick/rmstruct.c +1047 -0
  346. data/ext/RMagick/rmstruct.o +0 -0
  347. data/ext/RMagick/rmutil.c +1730 -0
  348. data/ext/RMagick/rmutil.o +0 -0
  349. data/lib/RMagick.rb +1962 -0
  350. data/lib/rvg/clippath.rb +48 -0
  351. data/lib/rvg/container.rb +131 -0
  352. data/lib/rvg/deep_equal.rb +56 -0
  353. data/lib/rvg/describable.rb +53 -0
  354. data/lib/rvg/embellishable.rb +417 -0
  355. data/lib/rvg/misc.rb +740 -0
  356. data/lib/rvg/paint.rb +55 -0
  357. data/lib/rvg/pathdata.rb +131 -0
  358. data/lib/rvg/rvg.rb +283 -0
  359. data/lib/rvg/stretchable.rb +168 -0
  360. data/lib/rvg/stylable.rb +124 -0
  361. data/lib/rvg/text.rb +187 -0
  362. data/lib/rvg/to_c.rb +103 -0
  363. data/lib/rvg/transformable.rb +133 -0
  364. data/lib/rvg/units.rb +66 -0
  365. data/metaconfig +7 -0
  366. data/post-clean.rb +12 -0
  367. data/post-install.rb +50 -0
  368. data/post-setup.rb +254 -0
  369. data/rmagick.gemspec +20 -0
  370. data/setup.rb +1585 -0
  371. data/test/Draw.rb +121 -0
  372. data/test/Image1.rb +762 -0
  373. data/test/Image2.rb +1308 -0
  374. data/test/Image3.rb +1001 -0
  375. data/test/ImageList1.rb +808 -0
  376. data/test/ImageList2.rb +389 -0
  377. data/test/Image_attributes.rb +682 -0
  378. data/test/Import_Export.rb +116 -0
  379. data/test/Info.rb +349 -0
  380. data/test/Magick.rb +364 -0
  381. data/test/Pixel.rb +120 -0
  382. data/test/Preview.rb +62 -0
  383. data/test/all_basic.rb +39 -0
  384. data/test/cmyk.icm +0 -0
  385. data/test/srgb.icm +0 -0
  386. data/test/test.0 +0 -0
  387. data/uninstall.rb +74 -0
  388. metadata +455 -0
Binary file
@@ -0,0 +1,1730 @@
1
+ /**************************************************************************//**
2
+ * Utility functions for RMagick.
3
+ *
4
+ * Copyright © 2002 - 2009 by Timothy P. Hunter
5
+ *
6
+ * Changes since Nov. 2009 copyright © by Benjamin Thomas and Omer Bar-or
7
+ *
8
+ * @file rmutil.c
9
+ * @version $Id: rmutil.c,v 1.182 2009/12/21 10:34:58 baror Exp $
10
+ * @author Tim Hunter
11
+ ******************************************************************************/
12
+
13
+ #include "rmagick.h"
14
+ #include <errno.h>
15
+
16
+ static void handle_exception(ExceptionInfo *, Image *, ErrorRetention);
17
+
18
+
19
+ /**
20
+ * ImageMagick safe version of malloc.
21
+ *
22
+ * No Ruby usage (internal function)
23
+ *
24
+ * Notes:
25
+ * - Use when managing memory that ImageMagick may have allocated or may free.
26
+ * - If malloc fails, it raises an exception.
27
+ * - magick_safe_malloc and magick_safe_realloc prevent exceptions caused by
28
+ * integer overflow. Added in 6.3.5-9 but backwards compatible with prior
29
+ * releases.
30
+ *
31
+ * @param count the number of quantum elements to allocate
32
+ * @param quantum the number of bytes in each quantum
33
+ * @return a pointer to a block of memory that is at least count*quantum
34
+ */
35
+ void *
36
+ magick_safe_malloc(const size_t count, const size_t quantum)
37
+ {
38
+ void *ptr;
39
+
40
+ ptr = AcquireQuantumMemory(count, quantum);
41
+ if (!ptr)
42
+ {
43
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
44
+ }
45
+ return ptr;
46
+ }
47
+
48
+
49
+ /**
50
+ * ImageMagick version of malloc.
51
+ *
52
+ * No Ruby usage (internal function)
53
+ *
54
+ * @param size the size of memory to allocate
55
+ * @return pointer to a block of memory
56
+ */
57
+ void *
58
+ magick_malloc(const size_t size)
59
+ {
60
+ void *ptr;
61
+ ptr = AcquireMagickMemory(size);
62
+ if (!ptr)
63
+ {
64
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
65
+ }
66
+
67
+ return ptr;
68
+ }
69
+
70
+
71
+ /**
72
+ * ImageMagick version of free.
73
+ *
74
+ * No Ruby usage (internal function)
75
+ *
76
+ * @param ptr pointer to the existing block of memory
77
+ */
78
+ void
79
+ magick_free(void *ptr)
80
+ {
81
+ (void) RelinquishMagickMemory(ptr);
82
+ }
83
+
84
+
85
+ /**
86
+ * ImageMagick safe version of realloc.
87
+ *
88
+ * No Ruby usage (internal function)
89
+ *
90
+ * Notes:
91
+ * - Use when managing memory that ImageMagick may have allocated or may free.
92
+ * - If malloc fails, it raises an exception.
93
+ * - magick_safe_malloc and magick_safe_realloc prevent exceptions caused by
94
+ * integer overflow. Added in 6.3.5-9 but backwards compatible with prior
95
+ * releases.
96
+ *
97
+ * @param memory the existing block of memory
98
+ * @param count the number of quantum elements to allocate
99
+ * @param quantum the number of bytes in each quantum
100
+ * @return a pointer to a block of memory that is at least count*quantum in size
101
+ */
102
+ void *
103
+ magick_safe_realloc(void *memory, const size_t count, const size_t quantum)
104
+ {
105
+ void *v;
106
+ v = ResizeQuantumMemory(memory, count, quantum);
107
+ if (!v)
108
+ {
109
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
110
+ }
111
+ return v;
112
+ }
113
+
114
+
115
+ /**
116
+ * ImageMagick version of realloc.
117
+ *
118
+ * No Ruby usage (internal function)
119
+ *
120
+ * @param ptr pointer to the existing block of memory
121
+ * @param size the new size of memory to allocate
122
+ * @return pointer to a block of memory
123
+ */
124
+ void *
125
+ magick_realloc(void *ptr, const size_t size)
126
+ {
127
+ void *v;
128
+ v = ResizeMagickMemory(ptr, size);
129
+ if (!v)
130
+ {
131
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
132
+ }
133
+ return v;
134
+ }
135
+
136
+
137
+ /**
138
+ * Make a copy of a string in malloc'd memory.
139
+ *
140
+ * No Ruby usage (internal function)
141
+ *
142
+ * Notes:
143
+ * - Any existing string pointed to by *new_str is freed.
144
+ * - CloneString asserts if no memory. No need to check its return value.
145
+ *
146
+ * @param new_str pointer to the new string
147
+ * @param str the string to copy
148
+ */
149
+ void
150
+ magick_clone_string(char **new_str, const char *str)
151
+ {
152
+ (void) CloneString(new_str, str);
153
+ }
154
+
155
+
156
+ /**
157
+ * Compare s1 and s2 ignoring case.
158
+ *
159
+ * No Ruby usage (internal function)
160
+ *
161
+ * @param s1 the first string
162
+ * @param s2 the second string
163
+ * @return same as strcmp(3)
164
+ */
165
+ int
166
+ rm_strcasecmp(const char *s1, const char *s2)
167
+ {
168
+ while (*s1 && *s2)
169
+ {
170
+ if (toupper(*s1) != toupper(*s2))
171
+ {
172
+ break;
173
+ }
174
+ s1 += 1;
175
+ s2 += 1;
176
+ }
177
+ return (int)(*s1 - *s2);
178
+ }
179
+
180
+
181
+ /**
182
+ * Compare s1 and s2 ignoring case.
183
+ *
184
+ * No Ruby usage (internal function)
185
+ *
186
+ * @param s1 the first string
187
+ * @param s2 the second string
188
+ * @param n number of characters to compare
189
+ * @return same as strcmp(3)
190
+ */
191
+ int
192
+ rm_strncasecmp(const char *s1, const char *s2, size_t n)
193
+ {
194
+ if (n == 0)
195
+ {
196
+ return 0;
197
+ }
198
+ while (toupper(*s1) == toupper(*s2))
199
+ {
200
+ if (--n == 0 || *s1 == '\0')
201
+ {
202
+ return 0;
203
+ }
204
+ s1 += 1;
205
+ s2 += 1;
206
+ }
207
+ return (int)(*s1 - *s2);
208
+ }
209
+
210
+
211
+ /**
212
+ * Raise exception if array too short.
213
+ *
214
+ * No Ruby usage (internal function)
215
+ *
216
+ * @param ary the array
217
+ * @param len the minimum length
218
+ * @throw IndexError
219
+ */
220
+ void
221
+ rm_check_ary_len(VALUE ary, long len)
222
+ {
223
+ if (RARRAY_LEN(ary) < len)
224
+ {
225
+ rb_raise(rb_eIndexError, "not enough elements in array - expecting %ld, got %ld",
226
+ len, (long)RARRAY_LEN(ary));
227
+ }
228
+ }
229
+
230
+
231
+ /**
232
+ * Raise an error if the image has been destroyed.
233
+ *
234
+ * No Ruby usage (internal function)
235
+ *
236
+ * @param obj the image
237
+ * @return the C image structure for the image
238
+ * @throw DestroyedImageError
239
+ */
240
+ Image *
241
+ rm_check_destroyed(VALUE obj)
242
+ {
243
+ Image *image;
244
+
245
+ Data_Get_Struct(obj, Image, image);
246
+ if (!image)
247
+ {
248
+ rb_raise(Class_DestroyedImageError, "destroyed image");
249
+ }
250
+
251
+ return image;
252
+ }
253
+
254
+
255
+ /**
256
+ * Raise an error if the image has been destroyed or is frozen.
257
+ *
258
+ * No Ruby usage (internal function)
259
+ *
260
+ * @param obj the image
261
+ * @return the C image structure for the image
262
+ */
263
+ Image *
264
+ rm_check_frozen(VALUE obj)
265
+ {
266
+ Image *image = rm_check_destroyed(obj);
267
+ rb_check_frozen(obj);
268
+ return image;
269
+ }
270
+
271
+
272
+ /**
273
+ * Overrides freeze in classes that can't be frozen.
274
+ *
275
+ * No Ruby usage (internal function)
276
+ *
277
+ * @param obj the object of the class to override
278
+ * @return 0
279
+ * @throw TypeError
280
+ */
281
+ VALUE
282
+ rm_no_freeze(VALUE obj)
283
+ {
284
+ rb_raise(rb_eTypeError, "can't freeze %s", rb_class2name(CLASS_OF(obj)));
285
+ return (VALUE)0;
286
+ }
287
+
288
+
289
+ /**
290
+ * Return obj.to_s, or obj if obj is already a string.
291
+ *
292
+ * No Ruby usage (internal function)
293
+ *
294
+ * @param obj a Ruby object
295
+ * @return a String representation of obj
296
+ */
297
+ VALUE
298
+ rm_to_s(VALUE obj)
299
+ {
300
+
301
+ if (TYPE(obj) != T_STRING)
302
+ {
303
+ return rb_funcall(obj, rm_ID_to_s, 0);
304
+ }
305
+ return obj;
306
+ }
307
+
308
+
309
+ /**
310
+ * Supply our own version of the "obsolete" rb_str2cstr.
311
+ *
312
+ * No Ruby usage (internal function)
313
+ *
314
+ * @param str the Ruby string
315
+ * @param len pointer to a long in which to store the number of characters
316
+ * @return a C string version of str
317
+ */
318
+ char *
319
+ rm_str2cstr(VALUE str, long *len)
320
+ {
321
+ StringValue(str);
322
+ if (len)
323
+ {
324
+ *len = RSTRING_LEN(str);
325
+ }
326
+ return RSTRING_PTR(str);
327
+ }
328
+
329
+
330
+ /**
331
+ * Try to convert the argument to a double, raise an exception if fail.
332
+ *
333
+ * No Ruby usage (internal function)
334
+ *
335
+ * @param arg the argument
336
+ * @return arg
337
+ */
338
+ static VALUE
339
+ arg_is_number(VALUE arg)
340
+ {
341
+ double d;
342
+ d = NUM2DBL(arg);
343
+ d = d; // satisfy icc
344
+ return arg;
345
+ }
346
+
347
+
348
+ /**
349
+ * Called when `rb_str_to_str' raises an exception.
350
+ *
351
+ * No Ruby usage (internal function)
352
+ *
353
+ * @param arg the argument
354
+ * @return 0
355
+ * @throw TypeError
356
+ */
357
+ static VALUE
358
+ rescue_not_str(VALUE arg)
359
+ {
360
+ rb_raise(rb_eTypeError, "argument must be a number or a string in the form 'NN%%' (%s given)",
361
+ rb_class2name(CLASS_OF(arg)));
362
+ return (VALUE)0;
363
+ }
364
+
365
+
366
+ /**
367
+ * Return a double between 0.0 and max (the second argument), inclusive. If the
368
+ * argument is a number convert to a Float object, otherwise it's supposed to be
369
+ * a string in the form * "NN%". Convert to a number and then to a Float.
370
+ *
371
+ * No Ruby usage (internal function)
372
+ *
373
+ * @param arg the argument
374
+ * @param max the maximum allowed value
375
+ * @return a double
376
+ */
377
+ double
378
+ rm_percentage(VALUE arg, double max)
379
+ {
380
+ double pct;
381
+ long pct_long;
382
+ char *pct_str, *end;
383
+ int not_num;
384
+
385
+ // Try to convert the argument to a number. If failure, sets not_num to non-zero.
386
+ (void) rb_protect(arg_is_number, arg, &not_num);
387
+
388
+ if (not_num)
389
+ {
390
+ arg = rb_rescue(rb_str_to_str, arg, rescue_not_str, arg);
391
+ pct_str = StringValuePtr(arg);
392
+ errno = 0;
393
+ pct_long = strtol(pct_str, &end, 10);
394
+ if (errno == ERANGE)
395
+ {
396
+ rb_raise(rb_eRangeError, "`%s' out of range", pct_str);
397
+ }
398
+ if (*end != '\0' && *end != '%')
399
+ {
400
+ rb_raise(rb_eArgError, "expected percentage, got `%s'", pct_str);
401
+ }
402
+
403
+ if (*end == '%' && pct_long != 0)
404
+ {
405
+ pct = (((double)pct_long) / 100.0) * max;
406
+ }
407
+ else
408
+ {
409
+ pct = (double) pct_long;
410
+ }
411
+ if (pct < 0.0)
412
+ {
413
+ rb_raise(rb_eArgError, "percentages may not be negative (got `%s')", pct_str);
414
+ }
415
+ }
416
+ else
417
+ {
418
+ pct = NUM2DBL(arg);
419
+ if (pct < 0.0)
420
+ {
421
+ rb_raise(rb_eArgError, "percentages may not be negative (got `%g')", pct);
422
+ }
423
+ }
424
+
425
+ return pct;
426
+ }
427
+
428
+
429
+ /**
430
+ * Return 0 if rb_num2dbl doesn't raise an exception.
431
+ *
432
+ * No Ruby usage (internal function)
433
+ *
434
+ * @param obj the object to convert to a double
435
+ * @return 0
436
+ */
437
+ static VALUE
438
+ check_num2dbl(VALUE obj)
439
+ {
440
+ (void) rb_num2dbl(obj);
441
+ return INT2FIX(1);
442
+ }
443
+
444
+
445
+ /**
446
+ * Called if rb_num2dbl raises an exception.
447
+ *
448
+ * No Ruby usage (internal function)
449
+ *
450
+ * @param ignored a Ruby object (unused)
451
+ * @return 0
452
+ */
453
+ static VALUE
454
+ rescue_not_dbl(VALUE ignored)
455
+ {
456
+ ignored = ignored; // defeat gcc message
457
+ return INT2FIX(0);
458
+ }
459
+
460
+
461
+ /**
462
+ * Return 1 if the object can be converted to a double, 0 otherwise.
463
+ *
464
+ * No Ruby usage (internal function)
465
+ *
466
+ * @param obj the object
467
+ * @return 1 or 0
468
+ */
469
+ int
470
+ rm_check_num2dbl(VALUE obj)
471
+ {
472
+ return FIX2INT(rb_rescue(check_num2dbl, obj, rescue_not_dbl, (VALUE)0));
473
+ }
474
+
475
+
476
+ /**
477
+ * Given a string in the form NN% return the corresponding double.
478
+ *
479
+ * No Ruby usage (internal function)
480
+ *
481
+ * @param str the string
482
+ * @return a double
483
+ */
484
+ double
485
+ rm_str_to_pct(VALUE str)
486
+ {
487
+ long pct;
488
+ char *pct_str, *end;
489
+
490
+ str = rb_rescue(rb_str_to_str, str, rescue_not_str, str);
491
+ pct_str = StringValuePtr(str);
492
+ errno = 0;
493
+ pct = strtol(pct_str, &end, 10);
494
+
495
+ if (errno == ERANGE)
496
+ {
497
+ rb_raise(rb_eRangeError, "`%s' out of range", pct_str);
498
+ }
499
+ if (*end != '%')
500
+ {
501
+ rb_raise(rb_eArgError, "expected percentage, got `%s'", pct_str);
502
+ }
503
+ if (pct < 0L)
504
+ {
505
+ rb_raise(rb_eArgError, "percentages may not be negative (got `%s')", pct_str);
506
+ }
507
+
508
+ return pct / 100.0;
509
+ }
510
+
511
+
512
+ /**
513
+ * If the argument is a number, convert it to a double. Otherwise it's supposed
514
+ * to be a string in the form 'NN%'. Return a percentage of QuantumRange.
515
+ *
516
+ * No Ruby usage (internal function)
517
+ *
518
+ * @param fuzz_arg the fuzz argument
519
+ * @return a double
520
+ * @see Image_fuzz
521
+ * @see Image_fuzz_eq
522
+ */
523
+ double
524
+ rm_fuzz_to_dbl(VALUE fuzz_arg)
525
+ {
526
+ double fuzz;
527
+ char *fuzz_str, *end;
528
+ int not_num;
529
+
530
+ // Try to convert the argument to a number. If failure, sets not_num to non-zero.
531
+ (void) rb_protect(arg_is_number, fuzz_arg, &not_num);
532
+
533
+ if (not_num)
534
+ {
535
+ // Convert to string, issue error message if failure.
536
+ fuzz_arg = rb_rescue(rb_str_to_str, fuzz_arg, rescue_not_str, fuzz_arg);
537
+ fuzz_str = StringValuePtr(fuzz_arg);
538
+ errno = 0;
539
+ fuzz = strtod(fuzz_str, &end);
540
+ if (errno == ERANGE)
541
+ {
542
+ rb_raise(rb_eRangeError, "`%s' out of range", fuzz_str);
543
+ }
544
+ if(*end == '%')
545
+ {
546
+ if (fuzz < 0.0)
547
+ {
548
+ rb_raise(rb_eArgError, "percentages may not be negative (got `%s')", fuzz_str);
549
+ }
550
+ fuzz = (fuzz * QuantumRange) / 100.0;
551
+ }
552
+ else if(*end != '\0')
553
+ {
554
+ rb_raise(rb_eArgError, "expected percentage, got `%s'", fuzz_str);
555
+ }
556
+ }
557
+ else
558
+ {
559
+ fuzz = NUM2DBL(fuzz_arg);
560
+ if (fuzz < 0.0)
561
+ {
562
+ rb_raise(rb_eArgError, "fuzz may not be negative (got `%g')", fuzz);
563
+ }
564
+ }
565
+
566
+ return fuzz;
567
+ }
568
+
569
+
570
+ /**
571
+ * Convert a application-supplied number to a Quantum. If the object is a Float,
572
+ * truncate it before converting.
573
+ *
574
+ * No Ruby usage (internal function)
575
+ *
576
+ * Notes:
577
+ * - Ruby says that 2147483647.5 doesn't fit into an unsigned long. If you
578
+ * truncate it, it works.
579
+ * - Should use this only when the input value is possibly subject to this
580
+ * problem.
581
+ *
582
+ * @param obj the application-supplied number
583
+ * @return a Quantum
584
+ */
585
+ Quantum
586
+ rm_app2quantum(VALUE obj)
587
+ {
588
+ volatile VALUE v = obj;
589
+
590
+ if (TYPE(obj) == T_FLOAT)
591
+ {
592
+ v = rb_funcall(obj, rm_ID_to_i, 0);
593
+ }
594
+
595
+ return NUM2QUANTUM(v);
596
+ }
597
+
598
+
599
+ /**
600
+ * Send the "cur_image" method to the object. If 'img' is an ImageList, then
601
+ * cur_image is self[\@scene]. If 'img' is an image, then cur_image is simply
602
+ * 'self'.
603
+ *
604
+ * No Ruby usage (internal function)
605
+ *
606
+ * @param img the object
607
+ * @return the return value from "cur_image"
608
+ */
609
+ VALUE
610
+ rm_cur_image(VALUE img)
611
+ {
612
+ return rb_funcall(img, rm_ID_cur_image, 0);
613
+ }
614
+
615
+
616
+ /**
617
+ * Map the color intensity to a named color.
618
+ *
619
+ * No Ruby usage (internal function)
620
+ *
621
+ * @param image the image
622
+ * @param color the color intensity as a PixelPacket
623
+ * @return the named color as a String
624
+ * @see rm_pixelpacket_to_color_name_info
625
+ */
626
+ VALUE
627
+ rm_pixelpacket_to_color_name(Image *image, PixelPacket *color)
628
+ {
629
+ char name[MaxTextExtent];
630
+ ExceptionInfo exception;
631
+
632
+ GetExceptionInfo(&exception);
633
+
634
+ (void) QueryColorname(image, color, X11Compliance, name, &exception);
635
+ CHECK_EXCEPTION()
636
+ (void) DestroyExceptionInfo(&exception);
637
+
638
+ return rb_str_new2(name);
639
+ }
640
+
641
+
642
+ /**
643
+ * Map the color intensity to a named color.
644
+ *
645
+ * No Ruby usage (internal function)
646
+ *
647
+ * Notes:
648
+ * - Simply create an Image from the Info, call QueryColorname, and then
649
+ * destroy the Image.
650
+ * - If the Info structure is NULL, creates a new one.
651
+ * - The default depth is always used, and the matte value is set to False,
652
+ * which means "don't use the alpha channel".
653
+ *
654
+ * @param info the info
655
+ * @param color the color intensity as a PixelPacket
656
+ * @return the named color as a String
657
+ * @see rm_pixelpacket_to_color_name
658
+ */
659
+ VALUE
660
+ rm_pixelpacket_to_color_name_info(Info *info, PixelPacket *color)
661
+ {
662
+ Image *image;
663
+ Info *my_info;
664
+ volatile VALUE color_name;
665
+
666
+ my_info = info ? info : CloneImageInfo(NULL);
667
+
668
+ image = AcquireImage(info);
669
+ image->matte = MagickFalse;
670
+ color_name = rm_pixelpacket_to_color_name(image, color);
671
+ (void) DestroyImage(image);
672
+ if (!info)
673
+ {
674
+ (void) DestroyImageInfo(my_info);
675
+ }
676
+
677
+ return color_name;
678
+ }
679
+
680
+
681
+ /**
682
+ * Write a temporary copy of the image to the IM registry.
683
+ *
684
+ * No Ruby usage (internal function)
685
+ *
686
+ * Notes:
687
+ * - The `temp_name' argument must point to an char array of size
688
+ * MaxTextExtent.
689
+ *
690
+ * @param image the image
691
+ * @param temp_name the temporary name to use
692
+ * @return the "filename" of the registered image
693
+ */
694
+ void
695
+ rm_write_temp_image(Image *image, char *temp_name)
696
+ {
697
+
698
+ #define TMPNAM_CLASS_VAR "@@_tmpnam_"
699
+
700
+ MagickBooleanType okay;
701
+ ExceptionInfo exception;
702
+ volatile VALUE id_value;
703
+ int id;
704
+
705
+ GetExceptionInfo(&exception);
706
+
707
+
708
+ // 'id' is always the value of its previous use
709
+ if (rb_cvar_defined(Module_Magick, rb_intern(TMPNAM_CLASS_VAR)) == Qtrue)
710
+ {
711
+ id_value = rb_cv_get(Module_Magick, TMPNAM_CLASS_VAR);
712
+ id = FIX2INT(id_value);
713
+ }
714
+ else
715
+ {
716
+ id = 0;
717
+ rb_cv_set(Module_Magick, TMPNAM_CLASS_VAR, INT2FIX(id));
718
+ }
719
+
720
+ id += 1;
721
+ rb_cv_set(Module_Magick, TMPNAM_CLASS_VAR, INT2FIX(id));
722
+ sprintf(temp_name, "mpri:%d", id);
723
+
724
+ // Omit "mpri:" from filename to form the key
725
+ okay = SetImageRegistry(ImageRegistryType, temp_name+5, image, &exception);
726
+ CHECK_EXCEPTION()
727
+ DestroyExceptionInfo(&exception);
728
+ if (!okay)
729
+ {
730
+ rb_raise(rb_eRuntimeError, "SetImageRegistry failed.");
731
+ }
732
+
733
+ }
734
+
735
+
736
+ /**
737
+ * Delete the temporary image from the registry.
738
+ *
739
+ * No Ruby usage (internal function)
740
+ *
741
+ * @param temp_name the name of temporary image in the registry.
742
+ */
743
+ void
744
+ rm_delete_temp_image(char *temp_name)
745
+ {
746
+ MagickBooleanType okay = DeleteImageRegistry(temp_name+5);
747
+
748
+ if (!okay)
749
+ {
750
+ rb_warn("DeleteImageRegistry failed for `%s'", temp_name);
751
+ }
752
+ }
753
+
754
+
755
+ /**
756
+ * Raise NotImplementedError.
757
+ *
758
+ * No Ruby usage (internal function)
759
+ *
760
+ * Notes:
761
+ * - Called when a xMagick API is not available.
762
+ * - Replaces Ruby's rb_notimplement function.
763
+ *
764
+ * @throw NotImpError
765
+ */
766
+ void
767
+ rm_not_implemented(void)
768
+ {
769
+
770
+ rb_raise(rb_eNotImpError, "the `%s' method is not supported by ImageMagick "
771
+ MagickLibVersionText, rb_id2name(THIS_FUNC()));
772
+ }
773
+
774
+
775
+ /**
776
+ * Create a new ImageMagickError object and raise an exception.
777
+ *
778
+ * No Ruby usage (internal function)
779
+ *
780
+ * Notes:
781
+ * - This funky technique allows me to safely add additional information to
782
+ * the ImageMagickError object in both 1.6.8 and 1.8.0.
783
+ *
784
+ * @param msg the error mesage
785
+ * @param loc the location of the error
786
+ * @throw ImageMagickError
787
+ * @see www.ruby_talk.org/36408.
788
+ */
789
+ void
790
+ rm_magick_error(const char *msg, const char *loc)
791
+ {
792
+ volatile VALUE exc, mesg, extra;
793
+
794
+ mesg = rb_str_new2(msg);
795
+ extra = loc ? rb_str_new2(loc) : Qnil;
796
+
797
+ exc = rb_funcall(Class_ImageMagickError, rm_ID_new, 2, mesg, extra);
798
+ (void) rb_funcall(rb_cObject, rb_intern("raise"), 1, exc);
799
+ }
800
+
801
+
802
+ /**
803
+ * Initialize a new ImageMagickError object - store the "loc" string in the
804
+ * \@magick_location instance variable.
805
+ *
806
+ * Ruby usage:
807
+ * - @verbatim ImageMagickError#initialize(msg) @endverbatim
808
+ * - @verbatim ImageMagickError#initialize(msg, loc) @endverbatim
809
+ *
810
+ * Notes:
811
+ * - Default loc is nil
812
+ *
813
+ * @param argc number of input arguments
814
+ * @param argv array of input arguments
815
+ * @param self this object
816
+ * @return self
817
+ */
818
+ VALUE
819
+ ImageMagickError_initialize(int argc, VALUE *argv, VALUE self)
820
+ {
821
+ VALUE super_argv[1] = {(VALUE)0};
822
+ int super_argc = 0;
823
+ volatile VALUE extra = Qnil;
824
+
825
+ switch(argc)
826
+ {
827
+ case 2:
828
+ extra = argv[1];
829
+ case 1:
830
+ super_argv[0] = argv[0];
831
+ super_argc = 1;
832
+ case 0:
833
+ break;
834
+ default:
835
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 to 2)", argc);
836
+ }
837
+
838
+ (void) rb_call_super(super_argc, (const VALUE *)super_argv);
839
+ (void) rb_iv_set(self, "@"MAGICK_LOC, extra);
840
+
841
+
842
+ return self;
843
+ }
844
+
845
+
846
+ /**
847
+ * Backport GetImageProperty for pre-6.3.1 versions of ImageMagick.
848
+ *
849
+ * No Ruby usage (internal function)
850
+ *
851
+ * @param img the image
852
+ * @param property the property name
853
+ * @return the property value
854
+ */
855
+ const char *
856
+ rm_get_property(const Image *img, const char *property)
857
+ {
858
+ return GetImageProperty(img, property);
859
+ }
860
+
861
+
862
+ /**
863
+ * Backport SetImageProperty for pre-6.3.1 versions of ImageMagick.
864
+ *
865
+ * No Ruby usage (internal function)
866
+ *
867
+ * @param image the image
868
+ * @param property the property name
869
+ * @param value the property value
870
+ * @return true if successful, otherwise false
871
+ */
872
+ MagickBooleanType
873
+ rm_set_property(Image *image, const char *property, const char *value)
874
+ {
875
+ return SetImageProperty(image, property, value);
876
+ }
877
+
878
+
879
+ /**
880
+ * If a "user" option is present in the Info, assign its value to a "user"
881
+ * artifact in each image.
882
+ *
883
+ * No Ruby usage (internal function)
884
+ *
885
+ * @param images a list of images
886
+ * @param info the info
887
+ */
888
+ void rm_set_user_artifact(Image *images, Info *info)
889
+ {
890
+ #if defined(HAVE_SETIMAGEARTIFACT)
891
+ Image *image;
892
+ const char *value;
893
+
894
+ value = GetImageOption(info, "user");
895
+ if (value)
896
+ {
897
+ image = GetFirstImageInList(images);
898
+ while (image)
899
+ {
900
+ (void) SetImageArtifact(image, "user", value);
901
+ image = GetNextImageInList(image);
902
+ }
903
+ }
904
+ #else
905
+ images = images;
906
+ info = info;
907
+ #endif
908
+ }
909
+
910
+
911
+ /**
912
+ * Collect optional method arguments via Magick::OptionalMethodArguments.
913
+ *
914
+ * No Ruby usage (internal function)
915
+ *
916
+ * Notes:
917
+ * - Creates an instance of Magick::OptionalMethodArguments, then yields to a
918
+ * block in the context of the instance.
919
+ *
920
+ * @param img the image
921
+ */
922
+ void
923
+ rm_get_optional_arguments(VALUE img)
924
+ {
925
+ volatile VALUE OptionalMethodArguments;
926
+ volatile VALUE opt_args;
927
+ VALUE argv[1];
928
+
929
+ // opt_args = Magick::OptionalMethodArguments.new(img)
930
+ // opt_args.instance_eval { block }
931
+ if (rb_block_given_p())
932
+ {
933
+ OptionalMethodArguments = rb_const_get_from(Module_Magick, rb_intern("OptionalMethodArguments"));
934
+ argv[0] = img;
935
+ opt_args = rb_class_new_instance(1, argv, OptionalMethodArguments);
936
+ (void) rb_obj_instance_eval(0, NULL, opt_args);
937
+ }
938
+
939
+ return;
940
+ }
941
+
942
+
943
+ #if defined(HAVE_SETIMAGEARTIFACT)
944
+ /**
945
+ * Copy image options from the Info structure to the Image structure.
946
+ *
947
+ * No Ruby usage (internal function)
948
+ *
949
+ * @param image the Image structure to modify
950
+ * @param info the Info structure
951
+ */
952
+ static void copy_options(Image *image, Info *info)
953
+ {
954
+ char property[MaxTextExtent];
955
+ const char *value, *option;
956
+
957
+ ResetImageOptionIterator(info);
958
+ for (option = GetNextImageOption(info); option; option = GetNextImageOption(info))
959
+ {
960
+ value = GetImageOption(info,option);
961
+ if (value)
962
+ {
963
+ strncpy(property, value, MaxTextExtent);
964
+ property[MaxTextExtent-1] = '\0';
965
+ (void) SetImageArtifact(image, property, value);
966
+ }
967
+ }
968
+ }
969
+ #endif
970
+
971
+
972
+ /**
973
+ * Propagate ImageInfo values to the Image
974
+ *
975
+ * No Ruby usage (internal function)
976
+ *
977
+ * @param image the Image structure to modify
978
+ * @param info the Info structure
979
+ * @see SyncImageSettings in mogrify.c in ImageMagick
980
+ */
981
+ void rm_sync_image_options(Image *image, Info *info)
982
+ {
983
+ MagickStatusType flags;
984
+ GeometryInfo geometry_info;
985
+ const char *option;
986
+
987
+ // The option strings will be set only when their attribute values were
988
+ // set in the optional argument block.
989
+ option = GetImageOption(info,"background");
990
+ if (option)
991
+ {
992
+ image->background_color = info->background_color;
993
+ }
994
+
995
+ option = GetImageOption(info,"bordercolor");
996
+ if (option)
997
+ {
998
+ image->border_color = info->border_color;
999
+ }
1000
+
1001
+ if (info->colorspace != UndefinedColorspace)
1002
+ {
1003
+ image->colorspace = info->colorspace;
1004
+ }
1005
+
1006
+ if (info->compression != UndefinedCompression)
1007
+ {
1008
+ image->compression = info->compression;
1009
+ }
1010
+
1011
+ option = GetImageOption(info, "delay");
1012
+ if (option)
1013
+ {
1014
+ image->delay = strtoul(option, NULL, 0);
1015
+ }
1016
+
1017
+ if (info->density)
1018
+ {
1019
+ flags = ParseGeometry(info->density, &geometry_info);
1020
+ image->x_resolution = geometry_info.rho;
1021
+ image->y_resolution = geometry_info.sigma;
1022
+ if ((flags & SigmaValue) == 0)
1023
+ {
1024
+ image->y_resolution = image->x_resolution;
1025
+ }
1026
+ }
1027
+
1028
+ if (info->depth != 0)
1029
+ {
1030
+ image->depth = info->depth;
1031
+ }
1032
+
1033
+ option = GetImageOption(info, "dispose");
1034
+ if (option)
1035
+ {
1036
+ image->dispose = rm_dispose_to_enum(option);
1037
+ }
1038
+
1039
+ if (info->extract)
1040
+ {
1041
+ ParseAbsoluteGeometry(info->extract, &image->extract_info);
1042
+ }
1043
+
1044
+ if (info->fuzz != 0.0)
1045
+ {
1046
+ image->fuzz = info->fuzz;
1047
+ }
1048
+
1049
+ option = GetImageOption(info, "gravity");
1050
+ if (option)
1051
+ {
1052
+ image->gravity = rm_gravity_to_enum(option);
1053
+ }
1054
+
1055
+ if (info->interlace != NoInterlace)
1056
+ {
1057
+ image->interlace = info->interlace;
1058
+ }
1059
+
1060
+ option = GetImageOption(info,"mattecolor");
1061
+ if (option)
1062
+ {
1063
+ image->matte_color = info->matte_color;
1064
+ }
1065
+
1066
+ if (info->orientation != UndefinedOrientation)
1067
+ {
1068
+ image->orientation = info->orientation;
1069
+ }
1070
+
1071
+ if (info->page)
1072
+ {
1073
+ (void)ParseAbsoluteGeometry(info->page, &image->page);
1074
+ }
1075
+
1076
+ if (info->quality != 0UL)
1077
+ {
1078
+ image->quality = info->quality;
1079
+ }
1080
+
1081
+ option = GetImageOption(info, "scene");
1082
+ if (option)
1083
+ {
1084
+ image->scene = info->scene;
1085
+ }
1086
+
1087
+ option = GetImageOption(info, "tile-offset");
1088
+ if (option)
1089
+ {
1090
+ (void)ParseAbsoluteGeometry(option, &image->tile_offset);
1091
+ }
1092
+
1093
+ option = GetImageOption(info, "transparent");
1094
+ if (option)
1095
+ {
1096
+ image->transparent_color = info->transparent_color;
1097
+ }
1098
+
1099
+ #if defined(HAVE_ST_TYPE)
1100
+ if (info->type != UndefinedType)
1101
+ {
1102
+ image->type = info->type;
1103
+ }
1104
+ #endif
1105
+
1106
+ if (info->units != UndefinedResolution)
1107
+ {
1108
+ if (image->units != info->units)
1109
+ {
1110
+ switch (image->units)
1111
+ {
1112
+ case PixelsPerInchResolution:
1113
+ {
1114
+ if (info->units == PixelsPerCentimeterResolution)
1115
+ {
1116
+ image->x_resolution /= 2.54;
1117
+ image->y_resolution /= 2.54;
1118
+ }
1119
+ break;
1120
+ }
1121
+ case PixelsPerCentimeterResolution:
1122
+ {
1123
+ if (info->units == PixelsPerInchResolution)
1124
+ {
1125
+ image->x_resolution *= 2.54;
1126
+ image->y_resolution *= 2.54;
1127
+ }
1128
+ break;
1129
+ }
1130
+ default:
1131
+ break;
1132
+ }
1133
+ }
1134
+
1135
+ image->units = info->units;
1136
+ }
1137
+
1138
+ #if defined(HAVE_SETIMAGEARTIFACT)
1139
+ copy_options(image, info);
1140
+ #endif
1141
+ }
1142
+
1143
+
1144
+ /**
1145
+ * Replicate old (ImageMagick < 6.3.2) EXIF:* functionality using
1146
+ * GetImageProperty by returning the exif entries as a single string, separated
1147
+ * by \n's. Do this so that RMagick.rb works no matter which version of
1148
+ * ImageMagick is in use.
1149
+ *
1150
+ * No Ruby usage (internal function)
1151
+ *
1152
+ * @param image the image
1153
+ * @return string representation of exif properties
1154
+ * @see magick/identify.c in ImageMagick
1155
+ */
1156
+ VALUE
1157
+ rm_exif_by_entry(Image *image)
1158
+ {
1159
+ const char *property, *value;
1160
+ char *str;
1161
+ size_t len = 0, property_l, value_l;
1162
+ volatile VALUE v;
1163
+
1164
+ (void) GetImageProperty(image, "exif:*");
1165
+ ResetImagePropertyIterator(image);
1166
+ property = GetNextImageProperty(image);
1167
+
1168
+ // Measure the exif properties and values
1169
+ while (property)
1170
+ {
1171
+ // ignore properties that don't start with "exif:"
1172
+ property_l = strlen(property);
1173
+ if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0)
1174
+ {
1175
+ if (len > 0)
1176
+ {
1177
+ len += 1; // there will be a \n between property=value entries
1178
+ }
1179
+ len += property_l - 5;
1180
+ value = GetImageProperty(image,property);
1181
+ if (value)
1182
+ {
1183
+ // add 1 for the = between property and value
1184
+ len += 1 + strlen(value);
1185
+ }
1186
+ }
1187
+ property = GetNextImageProperty(image);
1188
+ }
1189
+
1190
+ if (len == 0)
1191
+ {
1192
+ return Qnil;
1193
+ }
1194
+ str = xmalloc(len);
1195
+ len = 0;
1196
+
1197
+ // Copy the exif properties and values into the string.
1198
+ ResetImagePropertyIterator(image);
1199
+ property = GetNextImageProperty(image);
1200
+
1201
+ while (property)
1202
+ {
1203
+ property_l = strlen(property);
1204
+ if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0)
1205
+ {
1206
+ if (len > 0)
1207
+ {
1208
+ str[len++] = '\n';
1209
+ }
1210
+ memcpy(str+len, property+5, property_l-5);
1211
+ len += property_l - 5;
1212
+ value = GetImageProperty(image,property);
1213
+ if (value)
1214
+ {
1215
+ value_l = strlen(value);
1216
+ str[len++] = '=';
1217
+ memcpy(str+len, value, value_l);
1218
+ len += value_l;
1219
+ }
1220
+ }
1221
+ property = GetNextImageProperty(image);
1222
+ }
1223
+
1224
+ v = rb_str_new(str, len);
1225
+ xfree(str);
1226
+ return v;
1227
+ }
1228
+
1229
+
1230
+ /**
1231
+ * Replicate old (ImageMagick < 6.3.2) EXIF:! functionality using
1232
+ * GetImageProperty by returning the exif entries as a single string, separated
1233
+ * by \n's. Do this so that RMagick.rb works no matter which version of
1234
+ * ImageMagick is in use.
1235
+ *
1236
+ * No Ruby usage (internal function)
1237
+ *
1238
+ * @param image the image
1239
+ * @return string representation of exif properties
1240
+ * @see magick/identify.c in ImageMagick
1241
+ */
1242
+ VALUE
1243
+ rm_exif_by_number(Image *image)
1244
+ {
1245
+ const char *property, *value;
1246
+ char *str;
1247
+ size_t len = 0, property_l, value_l;
1248
+ volatile VALUE v;
1249
+
1250
+ (void) GetImageProperty(image, "exif:!");
1251
+ ResetImagePropertyIterator(image);
1252
+ property = GetNextImageProperty(image);
1253
+
1254
+ // Measure the exif properties and values
1255
+ while (property)
1256
+ {
1257
+ // ignore properties that don't start with "#"
1258
+ property_l = strlen(property);
1259
+ if (property_l > 1 && property[0] == '#')
1260
+ {
1261
+ if (len > 0)
1262
+ {
1263
+ len += 1; // there will be a \n between property=value entries
1264
+ }
1265
+ len += property_l;
1266
+ value = GetImageProperty(image,property);
1267
+ if (value)
1268
+ {
1269
+ // add 1 for the = between property and value
1270
+ len += 1 + strlen(value);
1271
+ }
1272
+ }
1273
+ property = GetNextImageProperty(image);
1274
+ }
1275
+
1276
+ if (len == 0)
1277
+ {
1278
+ return Qnil;
1279
+ }
1280
+ str = xmalloc(len);
1281
+ len = 0;
1282
+
1283
+ // Copy the exif properties and values into the string.
1284
+ ResetImagePropertyIterator(image);
1285
+ property = GetNextImageProperty(image);
1286
+
1287
+ while (property)
1288
+ {
1289
+ property_l = strlen(property);
1290
+ if (property_l > 1 && property[0] == '#')
1291
+ {
1292
+ if (len > 0)
1293
+ {
1294
+ str[len++] = '\n';
1295
+ }
1296
+ memcpy(str+len, property, property_l);
1297
+ len += property_l;
1298
+ value = GetImageProperty(image,property);
1299
+ if (value)
1300
+ {
1301
+ value_l = strlen(value);
1302
+ str[len++] = '=';
1303
+ memcpy(str+len, value, value_l);
1304
+ len += value_l;
1305
+ }
1306
+ }
1307
+ property = GetNextImageProperty(image);
1308
+ }
1309
+
1310
+ v = rb_str_new(str, len);
1311
+ xfree(str);
1312
+ return v;
1313
+ }
1314
+
1315
+
1316
+ /**
1317
+ * Get the values from a Geometry object and return them in C variables.
1318
+ *
1319
+ * No Ruby usage (internal function)
1320
+ *
1321
+ * Notes:
1322
+ * - No return value: modifies x, y, width, height, and flag
1323
+ *
1324
+ * @param geom the Geometry object
1325
+ * @param x pointer to the x position of the start of the rectangle
1326
+ * @param y pointer to the y position of the start of the rectangle
1327
+ * @param width pointer to the width of the rectangle
1328
+ * @param height pointer to the height of the rectangle
1329
+ * @param flag pointer to the Geometry's flag
1330
+ */
1331
+ void
1332
+ rm_get_geometry(
1333
+ VALUE geom,
1334
+ long *x,
1335
+ long *y,
1336
+ unsigned long *width,
1337
+ unsigned long *height,
1338
+ int *flag)
1339
+ {
1340
+ VALUE v;
1341
+
1342
+ v = rb_funcall(geom, rm_ID_x, 0);
1343
+ *x = NUM2LONG(v);
1344
+ v = rb_funcall(geom, rm_ID_y, 0);
1345
+ *y = NUM2LONG(v);
1346
+ v = rb_funcall(geom, rm_ID_width, 0);
1347
+ *width = NUM2ULONG(v);
1348
+ v = rb_funcall(geom, rm_ID_height, 0);
1349
+ *height = NUM2ULONG(v);
1350
+
1351
+ // Getting the flag field is a bit more difficult since it's
1352
+ // supposed to be an instance of the GeometryValue Enum class. We
1353
+ // may not know the VALUE for the GeometryValue class, and we
1354
+ // need to check that the flag field is an instance of that class.
1355
+ if (flag)
1356
+ {
1357
+ MagickEnum *magick_enum;
1358
+
1359
+ v = rb_funcall(geom, rm_ID_flag, 0);
1360
+ if (!Class_GeometryValue)
1361
+ {
1362
+ Class_GeometryValue = rb_const_get(Module_Magick, rm_ID_GeometryValue);
1363
+ }
1364
+ if (CLASS_OF(v) != Class_GeometryValue)
1365
+ {
1366
+ rb_raise(rb_eTypeError, "wrong enumeration type - expected %s, got %s"
1367
+ , rb_class2name(Class_GeometryValue),rb_class2name(CLASS_OF(v)));
1368
+ }
1369
+ Data_Get_Struct(v, MagickEnum, magick_enum);
1370
+ *flag = magick_enum->val;
1371
+ }
1372
+
1373
+ }
1374
+
1375
+
1376
+ /**
1377
+ * Clone an image, handle errors.
1378
+ *
1379
+ * No Ruby usage (internal function)
1380
+ *
1381
+ * Notes:
1382
+ * - Don't trace creation - the clone may not be used as an Image object. Let
1383
+ * the caller do the trace if desired.
1384
+ *
1385
+ * @param image the image to clone
1386
+ * @return the cloned image
1387
+ */
1388
+ Image *
1389
+ rm_clone_image(Image *image)
1390
+ {
1391
+ Image *clone;
1392
+ ExceptionInfo exception;
1393
+
1394
+ GetExceptionInfo(&exception);
1395
+ clone = CloneImage(image, 0, 0, MagickTrue, &exception);
1396
+ if (!clone)
1397
+ {
1398
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1399
+ }
1400
+ rm_check_exception(&exception, clone, DestroyOnError);
1401
+ (void) DestroyExceptionInfo(&exception);
1402
+
1403
+ return clone;
1404
+ }
1405
+
1406
+
1407
+ /**
1408
+ * SetImage(Info)ProgressMonitor exit.
1409
+ *
1410
+ * No Ruby usage (internal function)
1411
+ *
1412
+ * Notes:
1413
+ * - ImageMagick's "tag" argument is unused. We pass along the method name
1414
+ * instead.
1415
+ *
1416
+ * @param tag ImageMagick argument (unused)
1417
+ * @param of the offset type
1418
+ * @param sp the size type
1419
+ * @param client_data pointer to the progress method to call
1420
+ * @return true if calling client_data returns a non-nil value, otherwise false
1421
+ */
1422
+ MagickBooleanType
1423
+ rm_progress_monitor(
1424
+ const char *tag,
1425
+ const MagickOffsetType of,
1426
+ const MagickSizeType sp,
1427
+ void *client_data)
1428
+ {
1429
+ volatile VALUE rval;
1430
+ volatile VALUE method, offset, span;
1431
+
1432
+ tag = tag; // defeat gcc message
1433
+
1434
+ #if defined(HAVE_LONG_LONG) // defined in Ruby's defines.h
1435
+ offset = rb_ll2inum(of);
1436
+ span = rb_ull2inum(sp);
1437
+ #else
1438
+ offset = rb_int2big((long)of);
1439
+ span = rb_uint2big((unsigned long)sp);
1440
+ #endif
1441
+
1442
+ method = rb_str_new2(rb_id2name(THIS_FUNC()));
1443
+
1444
+ rval = rb_funcall((VALUE)client_data, rm_ID_call, 3, method, offset, span);
1445
+
1446
+ return RTEST(rval) ? MagickTrue : MagickFalse;
1447
+ }
1448
+
1449
+
1450
+ /**
1451
+ * Remove the ImageMagick links between images in an scene sequence.
1452
+ *
1453
+ * No Ruby usage (internal function)
1454
+ *
1455
+ * Notes:
1456
+ * - The images remain grouped via the ImageList
1457
+ *
1458
+ * @param image the image
1459
+ */
1460
+ void
1461
+ rm_split(Image *image)
1462
+ {
1463
+
1464
+ if (!image)
1465
+ {
1466
+ rb_bug("RMagick FATAL: split called with NULL argument.");
1467
+ }
1468
+ while (image)
1469
+ {
1470
+ (void) RemoveFirstImageFromList(&image);
1471
+ }
1472
+ }
1473
+
1474
+
1475
+ /**
1476
+ * If an ExceptionInfo struct in a list of images indicates a warning, issue a
1477
+ * warning message. If an ExceptionInfo struct indicates an error, raise an
1478
+ * exception and optionally destroy the images.
1479
+ *
1480
+ * No Ruby usage (internal function)
1481
+ *
1482
+ * @param imglist the list of images
1483
+ * @param retention retention strategy in case of an error (either RetainOnError
1484
+ * or DestroyOnError)
1485
+ */
1486
+ void
1487
+ rm_check_image_exception(Image *imglist, ErrorRetention retention)
1488
+ {
1489
+ ExceptionInfo exception;
1490
+ Image *badboy = NULL;
1491
+ Image *image;
1492
+
1493
+ if (imglist == NULL)
1494
+ {
1495
+ return;
1496
+ }
1497
+
1498
+ GetExceptionInfo(&exception);
1499
+
1500
+ // Find the image with the highest severity
1501
+ image = GetFirstImageInList(imglist);
1502
+ while (image)
1503
+ {
1504
+ if (image->exception.severity != UndefinedException)
1505
+ {
1506
+ if (!badboy || image->exception.severity > badboy->exception.severity)
1507
+ {
1508
+ badboy = image;
1509
+ InheritException(&exception, &badboy->exception);
1510
+ }
1511
+
1512
+ ClearMagickException(&image->exception);
1513
+ }
1514
+ image = GetNextImageInList(image);
1515
+ }
1516
+
1517
+ if (badboy)
1518
+ {
1519
+ rm_check_exception(&exception, imglist, retention);
1520
+ }
1521
+
1522
+ (void) DestroyExceptionInfo(&exception);
1523
+ }
1524
+
1525
+
1526
+ /**
1527
+ * Call handle_exception if there is an exception to handle.
1528
+ *
1529
+ * No Ruby usage (internal function)
1530
+ *
1531
+ * @param exception information about the exception
1532
+ * @param imglist the images that caused the exception
1533
+ * @param retention retention strategy in case of an error (either RetainOnError
1534
+ * or DestroyOnError)
1535
+ */
1536
+ void
1537
+ rm_check_exception(ExceptionInfo *exception, Image *imglist, ErrorRetention retention)
1538
+ {
1539
+ if (exception->severity == UndefinedException)
1540
+ {
1541
+ return;
1542
+ }
1543
+
1544
+ handle_exception(exception, imglist, retention);
1545
+ }
1546
+
1547
+
1548
+
1549
+ /**
1550
+ * Called from ImageMagick for a warning.
1551
+ *
1552
+ * No Ruby usage (internal function)
1553
+ *
1554
+ * @param severity information about the severity of the warning (ignored)
1555
+ * @param reason the reason for the warning
1556
+ * @param description description of the warning
1557
+ */
1558
+ void
1559
+ rm_warning_handler(const ExceptionType severity, const char *reason, const char *description)
1560
+ {
1561
+ ExceptionType dummy;
1562
+
1563
+ rb_warning("RMagick: %s: `%s'", reason, description);
1564
+ dummy = severity;
1565
+ dummy = dummy;
1566
+ }
1567
+
1568
+
1569
+ /**
1570
+ * Called from ImageMagick for a error.
1571
+ *
1572
+ * No Ruby usage (internal function)
1573
+ *
1574
+ * @param severity information about the severity of the error (ignored)
1575
+ * @param reason the reason for the error
1576
+ * @param description description of the error
1577
+ */
1578
+ void
1579
+ rm_error_handler(const ExceptionType severity, const char *reason, const char *description)
1580
+ {
1581
+ char msg[500];
1582
+ int len;
1583
+ ExceptionType dummy;
1584
+
1585
+ memset(msg, 0, sizeof(msg));
1586
+ #if defined(HAVE_SNPRINTF)
1587
+ len = snprintf(msg, sizeof(msg), "%s: `%s'", reason, description);
1588
+ #else
1589
+ len = sprintf(msg, "%.250s: `%.240s'", reason, description);
1590
+ #endif
1591
+ msg[len] = '\0';
1592
+
1593
+ rm_magick_error(msg, NULL);
1594
+ dummy = severity;
1595
+ dummy = dummy;
1596
+ }
1597
+
1598
+
1599
+ /**
1600
+ * Called from ImageMagick for a fatal error.
1601
+ *
1602
+ * No Ruby usage (internal function)
1603
+ *
1604
+ * @param severity information about the severity of the error
1605
+ * @param reason the reason for the error
1606
+ * @param description description of the error (ignored)
1607
+ * @throw FatalImageMagickError
1608
+ */
1609
+ void
1610
+ rm_fatal_error_handler(const ExceptionType severity, const char *reason, const char *description)
1611
+ {
1612
+ rb_raise(Class_FatalImageMagickError, GetLocaleExceptionMessage(severity, reason));
1613
+ description = description;
1614
+ }
1615
+
1616
+
1617
+ /**
1618
+ * Called when rm_check_exception determines that we need to either issue a
1619
+ * warning message or raise an exception. This function allocates a bunch of
1620
+ * stack so we don't call it unless we have to.
1621
+ *
1622
+ * No Ruby usage (internal function)
1623
+ *
1624
+ * @param exception information about the exception
1625
+ * @param imglist the images that caused the exception
1626
+ * @param retention retention strategy in case of an error (either RetainOnError
1627
+ * or DestroyOnError)
1628
+ */
1629
+ static void
1630
+ handle_exception(ExceptionInfo *exception, Image *imglist, ErrorRetention retention)
1631
+ {
1632
+
1633
+ char reason[500];
1634
+ char desc[500];
1635
+ char msg[sizeof(reason)+sizeof(desc)+20];
1636
+
1637
+ memset(msg, 0, sizeof(msg));
1638
+
1639
+
1640
+ // Handle simple warning
1641
+ if (exception->severity < ErrorException)
1642
+ {
1643
+ #if defined(HAVE_SNPRINTF)
1644
+ snprintf(msg, sizeof(msg)-1, "RMagick: %s%s%s",
1645
+ #else
1646
+ sprintf(msg, "RMagick: %.500s%s%.500s",
1647
+ #endif
1648
+ GetLocaleExceptionMessage(exception->severity, exception->reason),
1649
+ exception->description ? ": " : "",
1650
+ exception->description ? GetLocaleExceptionMessage(exception->severity, exception->description) : "");
1651
+ msg[sizeof(msg)-1] = '\0';
1652
+ rb_warning(msg);
1653
+
1654
+ // Caller deletes ExceptionInfo...
1655
+
1656
+ return;
1657
+ }
1658
+
1659
+ // Raise an exception. We're not coming back...
1660
+
1661
+
1662
+ // Newly-created images should be destroyed, images that are part
1663
+ // of image objects should be retained but split.
1664
+ if (imglist)
1665
+ {
1666
+ if (retention == DestroyOnError)
1667
+ {
1668
+ (void) DestroyImageList(imglist);
1669
+ imglist = NULL;
1670
+ }
1671
+ else
1672
+ {
1673
+ rm_split(imglist);
1674
+ }
1675
+ }
1676
+
1677
+
1678
+ // Clone the ExceptionInfo with all arguments on the stack.
1679
+ memset(reason, 0, sizeof(reason));
1680
+ memset(desc, 0, sizeof(desc));
1681
+
1682
+ if (exception->reason)
1683
+ {
1684
+ strncpy(reason, exception->reason, sizeof(reason)-1);
1685
+ reason[sizeof(reason)-1] = '\0';
1686
+ }
1687
+ if (exception->description)
1688
+ {
1689
+ strncpy(desc, exception->description, sizeof(desc)-1);
1690
+ desc[sizeof(desc)-1] = '\0';
1691
+ }
1692
+
1693
+
1694
+ #if defined(HAVE_SNPRINTF)
1695
+ snprintf(msg, sizeof(msg)-1, "%s%s%s",
1696
+ GetLocaleExceptionMessage(exception->severity, reason),
1697
+ desc[0] ? ": " : "",
1698
+ desc[0] ? GetLocaleExceptionMessage(exception->severity, desc) : "");
1699
+ #else
1700
+ sprintf(msg, "%.*s%s%.*s",
1701
+ sizeof(reason)-1, GetLocaleExceptionMessage(exception->severity, reason),
1702
+ desc[0] ? ": " : "",
1703
+ sizeof(desc)-1, desc[0] ? GetLocaleExceptionMessage(exception->severity, desc) : "");
1704
+ #endif
1705
+
1706
+ msg[sizeof(msg)-1] = '\0';
1707
+
1708
+ (void) DestroyExceptionInfo(exception);
1709
+ rm_magick_error(msg, NULL);
1710
+
1711
+ }
1712
+
1713
+
1714
+ /**
1715
+ * RMagick expected a result. If it got NULL instead raise an exception.
1716
+ *
1717
+ * No Ruby usage (internal function)
1718
+ *
1719
+ * @param image the expected result
1720
+ * @throw RuntimeError
1721
+ */
1722
+ void
1723
+ rm_ensure_result(Image *image)
1724
+ {
1725
+ if (!image)
1726
+ {
1727
+ rb_raise(rb_eRuntimeError, MagickPackageName " library function failed to return a result.");
1728
+ }
1729
+ }
1730
+