rmagick 2.13.2 → 4.2.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rmagick might be problematic. Click here for more details.

Files changed (380) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +63 -0
  3. data/.editorconfig +17 -0
  4. data/.github/ISSUE_TEMPLATE.md +17 -0
  5. data/.github/workflows/ci.yml +107 -0
  6. data/.gitignore +25 -0
  7. data/.rspec +2 -0
  8. data/.rubocop.yml +37 -0
  9. data/.rubocop_todo.yml +449 -0
  10. data/.yardopts +5 -0
  11. data/CHANGELOG.md +1277 -0
  12. data/CODE_OF_CONDUCT.md +128 -0
  13. data/CONTRIBUTING.md +81 -0
  14. data/Gemfile +4 -0
  15. data/LICENSE +20 -0
  16. data/README.md +324 -0
  17. data/Rakefile +190 -0
  18. data/before_install_linux.sh +69 -0
  19. data/before_install_osx.sh +57 -0
  20. data/deprecated/RMagick.rb +6 -0
  21. data/ext/RMagick/extconf.rb +334 -333
  22. data/ext/RMagick/rmagick.c +129 -127
  23. data/ext/RMagick/rmagick.h +221 -320
  24. data/ext/RMagick/rmdraw.c +458 -767
  25. data/ext/RMagick/rmenum.c +305 -752
  26. data/ext/RMagick/rmfill.c +231 -199
  27. data/ext/RMagick/rmilist.c +437 -478
  28. data/ext/RMagick/rmimage.c +6130 -5342
  29. data/ext/RMagick/rminfo.c +695 -833
  30. data/ext/RMagick/rmkinfo.c +198 -0
  31. data/ext/RMagick/rmmain.c +752 -506
  32. data/ext/RMagick/rmmontage.c +94 -152
  33. data/ext/RMagick/rmpixel.c +619 -425
  34. data/ext/RMagick/rmstruct.c +206 -309
  35. data/ext/RMagick/rmutil.c +514 -344
  36. data/lib/rmagick/version.rb +5 -0
  37. data/lib/rmagick.rb +1 -0
  38. data/lib/rmagick_internal.rb +1922 -0
  39. data/lib/rvg/clippath.rb +35 -39
  40. data/lib/rvg/container.rb +123 -124
  41. data/lib/rvg/deep_equal.rb +45 -49
  42. data/lib/rvg/describable.rb +41 -47
  43. data/lib/rvg/embellishable.rb +380 -411
  44. data/lib/rvg/misc.rb +691 -711
  45. data/lib/rvg/paint.rb +43 -47
  46. data/lib/rvg/pathdata.rb +119 -125
  47. data/lib/rvg/rvg.rb +214 -213
  48. data/lib/rvg/stretchable.rb +153 -162
  49. data/lib/rvg/stylable.rb +111 -117
  50. data/lib/rvg/text.rb +169 -180
  51. data/lib/rvg/transformable.rb +121 -127
  52. data/lib/rvg/units.rb +58 -61
  53. data/rmagick.gemspec +36 -16
  54. metadata +188 -365
  55. data/ChangeLog +0 -773
  56. data/Doxyfile +0 -1514
  57. data/README-Mac-OSX.txt +0 -1
  58. data/README.html +0 -10
  59. data/build_tarball.rake +0 -215
  60. data/doc/comtasks.html +0 -287
  61. data/doc/constants.html +0 -1581
  62. data/doc/css/doc.css +0 -299
  63. data/doc/css/popup.css +0 -34
  64. data/doc/css/ref.css +0 -67
  65. data/doc/draw.html +0 -3269
  66. data/doc/ex/InitialCoords.rb +0 -23
  67. data/doc/ex/NewCoordSys.rb +0 -32
  68. data/doc/ex/OrigCoordSys.rb +0 -18
  69. data/doc/ex/PreserveAspectRatio.rb +0 -205
  70. data/doc/ex/RotateScale.rb +0 -37
  71. data/doc/ex/Skew.rb +0 -38
  72. data/doc/ex/Use01.rb +0 -16
  73. data/doc/ex/Use02.rb +0 -21
  74. data/doc/ex/Use03.rb +0 -16
  75. data/doc/ex/ViewBox.rb +0 -33
  76. data/doc/ex/adaptive_threshold.rb +0 -10
  77. data/doc/ex/add_noise.rb +0 -17
  78. data/doc/ex/affine.rb +0 -48
  79. data/doc/ex/affine_transform.rb +0 -20
  80. data/doc/ex/arc.rb +0 -49
  81. data/doc/ex/arcpath.rb +0 -33
  82. data/doc/ex/arcs01.rb +0 -28
  83. data/doc/ex/arcs02.rb +0 -61
  84. data/doc/ex/average.rb +0 -15
  85. data/doc/ex/axes.rb +0 -64
  86. data/doc/ex/baseline_shift01.rb +0 -18
  87. data/doc/ex/bilevel_channel.rb +0 -9
  88. data/doc/ex/blur_image.rb +0 -12
  89. data/doc/ex/border.rb +0 -10
  90. data/doc/ex/bounding_box.rb +0 -44
  91. data/doc/ex/cbezier1.rb +0 -42
  92. data/doc/ex/cbezier2.rb +0 -42
  93. data/doc/ex/cbezier3.rb +0 -42
  94. data/doc/ex/cbezier4.rb +0 -43
  95. data/doc/ex/cbezier5.rb +0 -43
  96. data/doc/ex/cbezier6.rb +0 -53
  97. data/doc/ex/channel.rb +0 -26
  98. data/doc/ex/charcoal.rb +0 -12
  99. data/doc/ex/chop.rb +0 -29
  100. data/doc/ex/circle.rb +0 -33
  101. data/doc/ex/circle01.rb +0 -17
  102. data/doc/ex/clip_path.rb +0 -60
  103. data/doc/ex/coalesce.rb +0 -60
  104. data/doc/ex/color_fill_to_border.rb +0 -29
  105. data/doc/ex/color_floodfill.rb +0 -28
  106. data/doc/ex/color_histogram.rb +0 -48
  107. data/doc/ex/color_reset.rb +0 -11
  108. data/doc/ex/colorize.rb +0 -16
  109. data/doc/ex/colors.rb +0 -64
  110. data/doc/ex/compose_mask.rb +0 -23
  111. data/doc/ex/composite.rb +0 -135
  112. data/doc/ex/composite_layers.rb +0 -53
  113. data/doc/ex/composite_tiled.rb +0 -23
  114. data/doc/ex/contrast.rb +0 -36
  115. data/doc/ex/crop.rb +0 -31
  116. data/doc/ex/crop_with_gravity.rb +0 -46
  117. data/doc/ex/cubic01.rb +0 -45
  118. data/doc/ex/cubic02.rb +0 -94
  119. data/doc/ex/cycle_colormap.rb +0 -21
  120. data/doc/ex/dissolve.rb +0 -13
  121. data/doc/ex/drawcomp.rb +0 -42
  122. data/doc/ex/drop_shadow.rb +0 -60
  123. data/doc/ex/edge.rb +0 -11
  124. data/doc/ex/ellipse.rb +0 -45
  125. data/doc/ex/ellipse01.rb +0 -22
  126. data/doc/ex/emboss.rb +0 -11
  127. data/doc/ex/enhance.rb +0 -28
  128. data/doc/ex/equalize.rb +0 -11
  129. data/doc/ex/evenodd.rb +0 -43
  130. data/doc/ex/fill_pattern.rb +0 -26
  131. data/doc/ex/flatten_images.rb +0 -36
  132. data/doc/ex/flip.rb +0 -11
  133. data/doc/ex/flop.rb +0 -11
  134. data/doc/ex/font_styles.rb +0 -34
  135. data/doc/ex/fonts.rb +0 -20
  136. data/doc/ex/frame.rb +0 -12
  137. data/doc/ex/gaussian_blur.rb +0 -11
  138. data/doc/ex/get_multiline_type_metrics.rb +0 -42
  139. data/doc/ex/get_pixels.rb +0 -48
  140. data/doc/ex/get_type_metrics.rb +0 -146
  141. data/doc/ex/gradientfill.rb +0 -27
  142. data/doc/ex/grav.rb +0 -46
  143. data/doc/ex/gravity.rb +0 -79
  144. data/doc/ex/group.rb +0 -26
  145. data/doc/ex/hatchfill.rb +0 -27
  146. data/doc/ex/image.rb +0 -46
  147. data/doc/ex/images/Apple.miff +0 -0
  148. data/doc/ex/images/Ballerina.jpg +0 -0
  149. data/doc/ex/images/Ballerina3.jpg +0 -0
  150. data/doc/ex/images/Button_0.gif +0 -0
  151. data/doc/ex/images/Button_1.gif +0 -0
  152. data/doc/ex/images/Button_2.gif +0 -0
  153. data/doc/ex/images/Button_3.gif +0 -0
  154. data/doc/ex/images/Button_4.gif +0 -0
  155. data/doc/ex/images/Button_5.gif +0 -0
  156. data/doc/ex/images/Button_6.gif +0 -0
  157. data/doc/ex/images/Button_7.gif +0 -0
  158. data/doc/ex/images/Button_8.gif +0 -0
  159. data/doc/ex/images/Button_9.gif +0 -0
  160. data/doc/ex/images/Button_A.gif +0 -0
  161. data/doc/ex/images/Button_B.gif +0 -0
  162. data/doc/ex/images/Button_C.gif +0 -0
  163. data/doc/ex/images/Button_D.gif +0 -0
  164. data/doc/ex/images/Button_E.gif +0 -0
  165. data/doc/ex/images/Button_F.gif +0 -0
  166. data/doc/ex/images/Button_G.gif +0 -0
  167. data/doc/ex/images/Button_H.gif +0 -0
  168. data/doc/ex/images/Button_I.gif +0 -0
  169. data/doc/ex/images/Button_J.gif +0 -0
  170. data/doc/ex/images/Button_K.gif +0 -0
  171. data/doc/ex/images/Button_L.gif +0 -0
  172. data/doc/ex/images/Button_M.gif +0 -0
  173. data/doc/ex/images/Button_N.gif +0 -0
  174. data/doc/ex/images/Button_O.gif +0 -0
  175. data/doc/ex/images/Button_P.gif +0 -0
  176. data/doc/ex/images/Button_Q.gif +0 -0
  177. data/doc/ex/images/Button_R.gif +0 -0
  178. data/doc/ex/images/Button_S.gif +0 -0
  179. data/doc/ex/images/Button_T.gif +0 -0
  180. data/doc/ex/images/Button_U.gif +0 -0
  181. data/doc/ex/images/Button_V.gif +0 -0
  182. data/doc/ex/images/Button_W.gif +0 -0
  183. data/doc/ex/images/Button_X.gif +0 -0
  184. data/doc/ex/images/Button_Y.gif +0 -0
  185. data/doc/ex/images/Button_Z.gif +0 -0
  186. data/doc/ex/images/Cheetah.jpg +0 -0
  187. data/doc/ex/images/Coffee.wmf +0 -0
  188. data/doc/ex/images/Flower_Hat.jpg +0 -0
  189. data/doc/ex/images/Gold_Statue.jpg +0 -0
  190. data/doc/ex/images/Hot_Air_Balloons.jpg +0 -0
  191. data/doc/ex/images/Hot_Air_Balloons_H.jpg +0 -0
  192. data/doc/ex/images/Leaf.miff +0 -0
  193. data/doc/ex/images/No.wmf +0 -0
  194. data/doc/ex/images/Polynesia.jpg +0 -0
  195. data/doc/ex/images/Red_Rocks.jpg +0 -0
  196. data/doc/ex/images/Rocks_On_Beach.miff +0 -0
  197. data/doc/ex/images/Shorts.jpg +0 -0
  198. data/doc/ex/images/Snake.wmf +0 -0
  199. data/doc/ex/images/Violin.jpg +0 -0
  200. data/doc/ex/images/Yellow_Rose.miff +0 -0
  201. data/doc/ex/images/big-duck.gif +0 -0
  202. data/doc/ex/images/duck.gif +0 -0
  203. data/doc/ex/images/duck0.gif +0 -0
  204. data/doc/ex/images/duck1.gif +0 -0
  205. data/doc/ex/images/duck10.gif +0 -0
  206. data/doc/ex/images/duck11.gif +0 -0
  207. data/doc/ex/images/duck12.gif +0 -0
  208. data/doc/ex/images/duck13.gif +0 -0
  209. data/doc/ex/images/duck14.gif +0 -0
  210. data/doc/ex/images/duck15.gif +0 -0
  211. data/doc/ex/images/duck2.gif +0 -0
  212. data/doc/ex/images/duck3.gif +0 -0
  213. data/doc/ex/images/duck4.gif +0 -0
  214. data/doc/ex/images/duck5.gif +0 -0
  215. data/doc/ex/images/duck6.gif +0 -0
  216. data/doc/ex/images/duck7.gif +0 -0
  217. data/doc/ex/images/duck8.gif +0 -0
  218. data/doc/ex/images/duck9.gif +0 -0
  219. data/doc/ex/images/graydient230x6.gif +0 -0
  220. data/doc/ex/images/logo400x83.gif +0 -0
  221. data/doc/ex/images/model.miff +0 -0
  222. data/doc/ex/images/notimplemented.gif +0 -0
  223. data/doc/ex/images/smile.miff +0 -0
  224. data/doc/ex/images/spin.gif +0 -0
  225. data/doc/ex/implode.rb +0 -34
  226. data/doc/ex/level.rb +0 -11
  227. data/doc/ex/level_colors.rb +0 -11
  228. data/doc/ex/line.rb +0 -42
  229. data/doc/ex/line01.rb +0 -23
  230. data/doc/ex/mask.rb +0 -36
  231. data/doc/ex/matte_fill_to_border.rb +0 -40
  232. data/doc/ex/matte_floodfill.rb +0 -33
  233. data/doc/ex/matte_replace.rb +0 -40
  234. data/doc/ex/median_filter.rb +0 -28
  235. data/doc/ex/modulate.rb +0 -11
  236. data/doc/ex/mono.rb +0 -23
  237. data/doc/ex/morph.rb +0 -26
  238. data/doc/ex/mosaic.rb +0 -35
  239. data/doc/ex/motion_blur.rb +0 -11
  240. data/doc/ex/negate.rb +0 -11
  241. data/doc/ex/negate_channel.rb +0 -9
  242. data/doc/ex/nested_rvg.rb +0 -21
  243. data/doc/ex/nonzero.rb +0 -43
  244. data/doc/ex/normalize.rb +0 -11
  245. data/doc/ex/oil_paint.rb +0 -11
  246. data/doc/ex/opacity.rb +0 -37
  247. data/doc/ex/ordered_dither.rb +0 -11
  248. data/doc/ex/path.rb +0 -64
  249. data/doc/ex/pattern1.rb +0 -25
  250. data/doc/ex/pattern2.rb +0 -26
  251. data/doc/ex/polaroid.rb +0 -28
  252. data/doc/ex/polygon.rb +0 -24
  253. data/doc/ex/polygon01.rb +0 -23
  254. data/doc/ex/polyline.rb +0 -23
  255. data/doc/ex/polyline01.rb +0 -23
  256. data/doc/ex/posterize.rb +0 -8
  257. data/doc/ex/preview.rb +0 -9
  258. data/doc/ex/qbezierpath.rb +0 -52
  259. data/doc/ex/quad01.rb +0 -36
  260. data/doc/ex/quantize-m.rb +0 -25
  261. data/doc/ex/radial_blur.rb +0 -9
  262. data/doc/ex/raise.rb +0 -8
  263. data/doc/ex/random_threshold_channel.rb +0 -13
  264. data/doc/ex/rect01.rb +0 -15
  265. data/doc/ex/rect02.rb +0 -22
  266. data/doc/ex/rectangle.rb +0 -35
  267. data/doc/ex/reduce_noise.rb +0 -28
  268. data/doc/ex/remap.rb +0 -12
  269. data/doc/ex/remap_images.rb +0 -21
  270. data/doc/ex/resize_to_fill.rb +0 -10
  271. data/doc/ex/resize_to_fit.rb +0 -10
  272. data/doc/ex/roll.rb +0 -9
  273. data/doc/ex/rotate.rb +0 -45
  274. data/doc/ex/rotate_f.rb +0 -14
  275. data/doc/ex/roundrect.rb +0 -34
  276. data/doc/ex/rubyname.rb +0 -30
  277. data/doc/ex/rvg_clippath.rb +0 -14
  278. data/doc/ex/rvg_linecap.rb +0 -43
  279. data/doc/ex/rvg_linejoin.rb +0 -41
  280. data/doc/ex/rvg_opacity.rb +0 -19
  281. data/doc/ex/rvg_pattern.rb +0 -26
  282. data/doc/ex/rvg_stroke_dasharray.rb +0 -12
  283. data/doc/ex/segment.rb +0 -11
  284. data/doc/ex/sepiatone.rb +0 -8
  285. data/doc/ex/shade.rb +0 -11
  286. data/doc/ex/shadow.rb +0 -31
  287. data/doc/ex/shave.rb +0 -15
  288. data/doc/ex/shear.rb +0 -10
  289. data/doc/ex/sketch.rb +0 -18
  290. data/doc/ex/skewx.rb +0 -52
  291. data/doc/ex/skewy.rb +0 -47
  292. data/doc/ex/smile.rb +0 -125
  293. data/doc/ex/solarize.rb +0 -11
  294. data/doc/ex/sparse_color.rb +0 -55
  295. data/doc/ex/splice.rb +0 -9
  296. data/doc/ex/spread.rb +0 -11
  297. data/doc/ex/stegano.rb +0 -55
  298. data/doc/ex/stroke_dasharray.rb +0 -43
  299. data/doc/ex/stroke_fill.rb +0 -11
  300. data/doc/ex/stroke_linecap.rb +0 -44
  301. data/doc/ex/stroke_linejoin.rb +0 -48
  302. data/doc/ex/stroke_width.rb +0 -49
  303. data/doc/ex/swirl.rb +0 -17
  304. data/doc/ex/text.rb +0 -37
  305. data/doc/ex/text01.rb +0 -17
  306. data/doc/ex/text_align.rb +0 -36
  307. data/doc/ex/text_antialias.rb +0 -38
  308. data/doc/ex/text_styles.rb +0 -21
  309. data/doc/ex/text_undercolor.rb +0 -28
  310. data/doc/ex/texture_fill_to_border.rb +0 -34
  311. data/doc/ex/texture_floodfill.rb +0 -32
  312. data/doc/ex/texturefill.rb +0 -25
  313. data/doc/ex/threshold.rb +0 -13
  314. data/doc/ex/to_blob.rb +0 -14
  315. data/doc/ex/translate.rb +0 -39
  316. data/doc/ex/transparent.rb +0 -38
  317. data/doc/ex/transpose.rb +0 -9
  318. data/doc/ex/transverse.rb +0 -9
  319. data/doc/ex/tref01.rb +0 -25
  320. data/doc/ex/triangle01.rb +0 -16
  321. data/doc/ex/trim.rb +0 -24
  322. data/doc/ex/tspan01.rb +0 -18
  323. data/doc/ex/tspan02.rb +0 -19
  324. data/doc/ex/tspan03.rb +0 -21
  325. data/doc/ex/unsharp_mask.rb +0 -28
  326. data/doc/ex/viewex.rb +0 -35
  327. data/doc/ex/vignette.rb +0 -12
  328. data/doc/ex/watermark.rb +0 -28
  329. data/doc/ex/wave.rb +0 -9
  330. data/doc/ex/wet_floor.rb +0 -59
  331. data/doc/ex/writing_mode01.rb +0 -27
  332. data/doc/ex/writing_mode02.rb +0 -26
  333. data/doc/ilist.html +0 -2056
  334. data/doc/image1.html +0 -4680
  335. data/doc/image2.html +0 -3665
  336. data/doc/image3.html +0 -4522
  337. data/doc/imageattrs.html +0 -1638
  338. data/doc/imusage.html +0 -514
  339. data/doc/index.html +0 -416
  340. data/doc/info.html +0 -1499
  341. data/doc/magick.html +0 -565
  342. data/doc/optequiv.html +0 -2435
  343. data/doc/rvg.html +0 -975
  344. data/doc/rvgclip.html +0 -248
  345. data/doc/rvggroup.html +0 -305
  346. data/doc/rvgimage.html +0 -289
  347. data/doc/rvgpattern.html +0 -475
  348. data/doc/rvgshape.html +0 -406
  349. data/doc/rvgstyle.html +0 -270
  350. data/doc/rvgtext.html +0 -465
  351. data/doc/rvgtspan.html +0 -238
  352. data/doc/rvgtut.html +0 -530
  353. data/doc/rvguse.html +0 -145
  354. data/doc/rvgxform.html +0 -294
  355. data/doc/scripts/doc.js +0 -22
  356. data/doc/scripts/stripeTables.js +0 -23
  357. data/doc/struct.html +0 -1339
  358. data/doc/usage.html +0 -1621
  359. data/examples/constitute.rb +0 -7
  360. data/examples/crop_with_gravity.rb +0 -46
  361. data/examples/demo.rb +0 -324
  362. data/examples/describe.rb +0 -44
  363. data/examples/find_similar_region.rb +0 -34
  364. data/examples/histogram.rb +0 -325
  365. data/examples/identify.rb +0 -187
  366. data/examples/image_opacity.rb +0 -29
  367. data/examples/import_export.rb +0 -31
  368. data/examples/pattern_fill.rb +0 -38
  369. data/examples/rotating_text.rb +0 -45
  370. data/examples/spinner.rb +0 -50
  371. data/examples/thumbnail.rb +0 -65
  372. data/examples/vignette.rb +0 -79
  373. data/ext/RMagick/MANIFEST +0 -358
  374. data/lib/RMagick.rb +0 -1962
  375. data/metaconfig +0 -7
  376. data/post-clean.rb +0 -12
  377. data/post-install.rb +0 -50
  378. data/post-setup.rb +0 -254
  379. data/setup.rb +0 -1585
  380. data/uninstall.rb +0 -76
@@ -16,7 +16,6 @@ static Image *clone_imagelist(Image *);
16
16
  static Image *images_from_imagelist(VALUE);
17
17
  static long imagelist_length(VALUE);
18
18
  static long check_imagelist_length(VALUE);
19
- static VALUE imagelist_scene_eq(VALUE, VALUE);
20
19
  static void imagelist_push(VALUE, VALUE);
21
20
  static VALUE ImageList_new(void);
22
21
 
@@ -26,17 +25,15 @@ static VALUE ImageList_new(void);
26
25
 
27
26
  /**
28
27
  * Repeatedly display the images in the images array to an XWindow screen. The
29
- * "delay" argument is the number of 1/100ths of a second (0 to 65535) to delay
28
+ * +delay+ argument is the number of 1/100ths of a second (0 to 65535) to delay
30
29
  * between images.
31
30
  *
32
- * Ruby usage:
33
- * - @verbatim ImageList#animate @endverbatim
34
- * - @verbatim ImageList#animate(delay) @endverbatim
31
+ * @overload animate
35
32
  *
36
- * @param argc number of input arguments
37
- * @param argv array of input arguments
38
- * @param self this object
39
- * @return self
33
+ * @overload animate(delay)
34
+ * @param delay [Numeric] the length of time between each image in an animation
35
+ *
36
+ * @return [Magick::ImageList] self
40
37
  */
41
38
 
42
39
  VALUE
@@ -44,8 +41,16 @@ ImageList_animate(int argc, VALUE *argv, VALUE self)
44
41
  {
45
42
  Image *images;
46
43
  Info *info;
47
- volatile VALUE info_obj;
44
+ VALUE info_obj;
45
+ unsigned int delay;
46
+ #if defined(IMAGEMAGICK_7)
47
+ ExceptionInfo *exception;
48
+ #endif
48
49
 
50
+ if (argc == 1)
51
+ {
52
+ delay = NUM2UINT(argv[0]);
53
+ }
49
54
  if (argc > 1)
50
55
  {
51
56
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc);
@@ -60,9 +65,7 @@ ImageList_animate(int argc, VALUE *argv, VALUE self)
60
65
  if (argc == 1)
61
66
  {
62
67
  Image *img;
63
- unsigned int delay;
64
68
 
65
- delay = NUM2UINT(argv[0]);
66
69
  for (img = images; img; img = GetNextImageInList(img))
67
70
  {
68
71
  img->delay = delay;
@@ -70,30 +73,36 @@ ImageList_animate(int argc, VALUE *argv, VALUE self)
70
73
  }
71
74
 
72
75
  Data_Get_Struct(info_obj, Info, info);
73
- (void) AnimateImages(info, images);
74
- rm_check_image_exception(images, RetainOnError);
76
+ #if defined(IMAGEMAGICK_7)
77
+ exception = AcquireExceptionInfo();
78
+ AnimateImages(info, images, exception);
75
79
  rm_split(images);
80
+ CHECK_EXCEPTION();
81
+ DestroyExceptionInfo(exception);
82
+ #else
83
+ AnimateImages(info, images);
84
+ rm_split(images);
85
+ rm_check_image_exception(images, RetainOnError);
86
+ #endif
87
+
88
+ RB_GC_GUARD(info_obj);
76
89
 
77
90
  return self;
78
91
  }
79
92
 
80
93
 
81
94
  /**
82
- * Append all the images by calling ImageAppend.
83
- *
84
- * Ruby usage:
85
- * - @verbatim ImageList#append(stack) @endverbatim
95
+ * Append all the images
86
96
  *
87
- * @param self this object
88
- * @param stack_arg the stack of images
89
- * @return a Frame object for the result
97
+ * @param stack_arg [Magick::ImageList] the stack of images
98
+ * @return [Magick::Image] a frame object for the result
90
99
  */
91
100
  VALUE
92
101
  ImageList_append(VALUE self, VALUE stack_arg)
93
102
  {
94
103
  Image *images, *new_image;
95
104
  unsigned int stack;
96
- ExceptionInfo exception;
105
+ ExceptionInfo *exception;
97
106
 
98
107
  // Convert the image array to an image sequence.
99
108
  images = images_from_imagelist(self);
@@ -102,106 +111,184 @@ ImageList_append(VALUE self, VALUE stack_arg)
102
111
  // otherwise left-to-right.
103
112
  stack = RTEST(stack_arg);
104
113
 
105
- GetExceptionInfo(&exception);
106
- new_image = AppendImages(images, stack, &exception);
114
+ exception = AcquireExceptionInfo();
115
+ new_image = AppendImages(images, stack, exception);
107
116
  rm_split(images);
108
- rm_check_exception(&exception, new_image, DestroyOnError);
109
- (void) DestroyExceptionInfo(&exception);
110
-
111
- rm_ensure_result(new_image);
117
+ rm_check_exception(exception, new_image, DestroyOnError);
118
+ DestroyExceptionInfo(exception);
112
119
 
113
120
  return rm_image_new(new_image);
114
121
  }
115
122
 
116
123
 
117
124
  /**
118
- * Average all images together by calling AverageImages.
119
- *
120
- * Ruby usage:
121
- * - @verbatim ImageList#average @endverbatim
125
+ * Average all images together
122
126
  *
123
- * @param self this object
124
- * @return a Frame object for the averaged image
127
+ * @return [Magick::Image] a frame object for the averaged image
125
128
  */
126
129
  VALUE
127
130
  ImageList_average(VALUE self)
128
131
  {
129
132
  Image *images, *new_image;
130
- ExceptionInfo exception;
133
+ ExceptionInfo *exception;
131
134
 
132
135
  // Convert the images array to an images sequence.
133
136
  images = images_from_imagelist(self);
134
137
 
135
- GetExceptionInfo(&exception);
136
- new_image = AverageImages(images, &exception);
137
- rm_split(images);
138
- rm_check_exception(&exception, new_image, DestroyOnError);
139
- (void) DestroyExceptionInfo(&exception);
138
+ exception = AcquireExceptionInfo();
139
+ new_image = EvaluateImages(images, MeanEvaluateOperator, exception);
140
140
 
141
- rm_ensure_result(new_image);
141
+ rm_split(images);
142
+ rm_check_exception(exception, new_image, DestroyOnError);
143
+ DestroyExceptionInfo(exception);
142
144
 
143
145
  return rm_image_new(new_image);
144
146
  }
145
147
 
146
148
 
147
149
  /**
148
- * Call CoalesceImages.
150
+ * Composites a set of images while respecting any page offsets and disposal methods.
149
151
  *
150
- * Ruby usage:
151
- * - @verbatim ImageList#coalesce @endverbatim
152
- *
153
- * Notes:
154
- * - Respects the delay, matte, and start_loop fields in each image.
152
+ * - Respects the delay, matte, and start_loop fields in each image.
155
153
  *
156
- * @param self this object
157
- * @return a new Image with the coalesced image sequence return stored in the
158
- * images array
154
+ * @return [Magick::ImageList] a new image with the coalesced image sequence return stored in the
155
+ * images array
159
156
  */
160
157
  VALUE
161
158
  ImageList_coalesce(VALUE self)
162
159
  {
163
160
  Image *images, *new_images;
164
- ExceptionInfo exception;
161
+ ExceptionInfo *exception;
165
162
 
166
163
  // Convert the image array to an image sequence.
167
164
  images = images_from_imagelist(self);
168
165
 
169
- GetExceptionInfo(&exception);
170
- new_images = CoalesceImages(images, &exception);
166
+ exception = AcquireExceptionInfo();
167
+ new_images = CoalesceImages(images, exception);
171
168
  rm_split(images);
172
- rm_check_exception(&exception, new_images, DestroyOnError);
173
- (void) DestroyExceptionInfo(&exception);
174
-
175
- rm_ensure_result(new_images);
169
+ rm_check_exception(exception, new_images, DestroyOnError);
170
+ DestroyExceptionInfo(exception);
176
171
 
177
172
  return rm_imagelist_from_images(new_images);
178
173
  }
179
174
 
180
175
 
181
176
  /**
182
- * Equivalent to convert's -layers composite option.
177
+ * Combines the images using the specified colorspace.
183
178
  *
184
- * Ruby usage:
185
- * - @verbatim ImageList#composite_layers(images) @endverbatim
186
- * - @verbatim ImageList#composite_layers(images,operator) @endverbatim
179
+ * @overload combine
187
180
  *
188
- * Notes:
189
- * - Default operator is OverCompositeOp
181
+ * @overload combine(colorspace)
182
+ * @param colorspace [Magick::ColorspaceType] the colorspace
190
183
  *
191
- * @param argc number of input arguments
192
- * @param argv array of input arguments
193
- * @param self this object
194
- * @return a new imagelist
195
- * @see mogrify.c in ImageMagick
184
+ * @return [Magick::Image] a new image
185
+ */
186
+ VALUE ImageList_combine(int argc, VALUE *argv, VALUE self)
187
+ {
188
+ #if defined(IMAGEMAGICK_6)
189
+ ChannelType channel;
190
+ ColorspaceType old_colorspace;
191
+ #endif
192
+ ColorspaceType colorspace;
193
+ long len;
194
+ Image *images, *new_image;
195
+ ExceptionInfo *exception;
196
+
197
+ len = check_imagelist_length(self);
198
+
199
+ switch (argc)
200
+ {
201
+ case 1:
202
+ VALUE_TO_ENUM(argv[0], colorspace, ColorspaceType);
203
+ break;
204
+ case 0:
205
+ colorspace = sRGBColorspace;
206
+ break;
207
+ default:
208
+ rb_raise(rb_eArgError, "wrong number of arguments (expected 1, got %d)", argc);
209
+ break;
210
+ }
211
+
212
+ #if defined(IMAGEMAGICK_7)
213
+ if (len > 5)
214
+ {
215
+ rb_raise(rb_eArgError, "invalid number of images in this image list");
216
+ }
217
+ if (len == 5 && colorspace != CMYKColorspace)
218
+ {
219
+ rb_raise(rb_eArgError, "invalid number of images in this image list");
220
+ }
221
+ #else
222
+ channel = RedChannel;
223
+ switch (len)
224
+ {
225
+ case 5:
226
+ if (colorspace == CMYKColorspace)
227
+ channel |= AlphaChannel;
228
+ else
229
+ rb_raise(rb_eArgError, "invalid number of images in this image list");
230
+ case 4:
231
+ if (colorspace == CMYKColorspace)
232
+ channel |= IndexChannel;
233
+ else
234
+ channel |= AlphaChannel;
235
+ case 3:
236
+ channel |= GreenChannel;
237
+ channel |= BlueChannel;
238
+ break;
239
+ case 2:
240
+ channel |= AlphaChannel;
241
+ break;
242
+ case 1:
243
+ break;
244
+ default:
245
+ rb_raise(rb_eArgError, "invalid number of images in this image list");
246
+ break;
247
+ }
248
+ #endif
249
+
250
+ images = images_from_imagelist(self);
251
+ exception = AcquireExceptionInfo();
252
+ #if defined(IMAGEMAGICK_6)
253
+ old_colorspace = images->colorspace;
254
+ SetImageColorspace(images, colorspace);
255
+ new_image = CombineImages(images, channel, exception);
256
+ #else
257
+ new_image = CombineImages(images, colorspace, exception);
258
+ #endif
259
+
260
+ rm_split(images);
261
+ #if defined(IMAGEMAGICK_6)
262
+ images->colorspace = old_colorspace;
263
+ #endif
264
+ rm_check_exception(exception, new_image, DestroyOnError);
265
+ DestroyExceptionInfo(exception);
266
+
267
+ return rm_image_new(new_image);
268
+ }
269
+
270
+
271
+ /**
272
+ * An image from source images is composited over an image from receiver's list until one list is finished.
273
+ *
274
+ * @overload composite_layers(images)
275
+ * @param images [Magick::ImageList] the source images
276
+ *
277
+ * @overload composite_layers(images, operator)
278
+ * - Default operator is {Magick::OverCompositeOp}
279
+ * @param images [Magick::ImageList] the source images
280
+ * @param operator [Magick::CompositeOperator] the operator
281
+ *
282
+ * @return [Magick::ImageList] a new imagelist
196
283
  */
197
284
  VALUE
198
285
  ImageList_composite_layers(int argc, VALUE *argv, VALUE self)
199
286
  {
200
- volatile VALUE source_images;
287
+ VALUE source_images;
201
288
  Image *dest, *source, *new_images;
202
289
  RectangleInfo geometry;
203
290
  CompositeOperator operator = OverCompositeOp;
204
- ExceptionInfo exception;
291
+ ExceptionInfo *exception;
205
292
 
206
293
  switch (argc)
207
294
  {
@@ -222,20 +309,22 @@ ImageList_composite_layers(int argc, VALUE *argv, VALUE self)
222
309
 
223
310
  source = images_from_imagelist(source_images);
224
311
 
225
- SetGeometry(new_images,&geometry);
226
- (void) ParseAbsoluteGeometry(new_images->geometry, &geometry);
312
+ SetGeometry(new_images, &geometry);
313
+ ParseAbsoluteGeometry(new_images->geometry, &geometry);
227
314
 
228
315
  geometry.width = source->page.width != 0 ? source->page.width : source->columns;
229
316
  geometry.height = source->page.height != 0 ? source->page.height : source->rows;
230
- GravityAdjustGeometry(new_images->page.width != 0 ? new_images->page.width : new_images->columns
231
- , new_images->page.height != 0 ? new_images->page.height : new_images->rows
232
- , new_images->gravity, &geometry);
317
+ GravityAdjustGeometry(new_images->page.width != 0 ? new_images->page.width : new_images->columns,
318
+ new_images->page.height != 0 ? new_images->page.height : new_images->rows,
319
+ new_images->gravity, &geometry);
233
320
 
234
- GetExceptionInfo(&exception);
235
- CompositeLayers(new_images, operator, source, geometry.x, geometry.y, &exception);
321
+ exception = AcquireExceptionInfo();
322
+ CompositeLayers(new_images, operator, source, geometry.x, geometry.y, exception);
236
323
  rm_split(source);
237
- rm_check_exception(&exception, new_images, DestroyOnError);
238
- (void) DestroyExceptionInfo(&exception);
324
+ rm_check_exception(exception, new_images, DestroyOnError);
325
+ DestroyExceptionInfo(exception);
326
+
327
+ RB_GC_GUARD(source_images);
239
328
 
240
329
  return rm_imagelist_from_images(new_images);
241
330
  }
@@ -245,26 +334,24 @@ ImageList_composite_layers(int argc, VALUE *argv, VALUE self)
245
334
  * Compare each image with the next in a sequence and returns the maximum
246
335
  * bounding region of any pixel differences it discovers.
247
336
  *
248
- * Ruby usage:
249
- * - @verbatim ImageList#deconstruct @endverbatim
250
- *
251
- * @param self this object
252
- * @return a new imagelist
337
+ * @return [Magick::ImageList] a new imagelist
253
338
  */
254
339
  VALUE
255
340
  ImageList_deconstruct(VALUE self)
256
341
  {
257
342
  Image *new_images, *images;
258
- ExceptionInfo exception;
343
+ ExceptionInfo *exception;
259
344
 
260
345
  images = images_from_imagelist(self);
261
- GetExceptionInfo(&exception);
262
- new_images = DeconstructImages(images, &exception);
346
+ exception = AcquireExceptionInfo();
347
+ #if defined(IMAGEMAGICK_7)
348
+ new_images = CompareImagesLayers(images, CompareAnyLayer, exception);
349
+ #else
350
+ new_images = DeconstructImages(images, exception);
351
+ #endif
263
352
  rm_split(images);
264
- rm_check_exception(&exception, new_images, DestroyOnError);
265
- (void) DestroyExceptionInfo(&exception);
266
-
267
- rm_ensure_result(new_images);
353
+ rm_check_exception(exception, new_images, DestroyOnError);
354
+ DestroyExceptionInfo(exception);
268
355
 
269
356
  return rm_imagelist_from_images(new_images);
270
357
  }
@@ -273,18 +360,17 @@ ImageList_deconstruct(VALUE self)
273
360
  /**
274
361
  * Display all the images to an X window screen.
275
362
  *
276
- * Ruby usage:
277
- * - @verbatim ImageList#display @endverbatim
278
- *
279
- * @param self this object
280
- * @return self
363
+ * @return [Magick::ImageList] self
281
364
  */
282
365
  VALUE
283
366
  ImageList_display(VALUE self)
284
367
  {
285
368
  Image *images;
286
369
  Info *info;
287
- volatile VALUE info_obj;
370
+ VALUE info_obj;
371
+ #if defined(IMAGEMAGICK_7)
372
+ ExceptionInfo *exception;
373
+ #endif
288
374
 
289
375
  // Create a new Info object to use with this call
290
376
  info_obj = rm_info_new();
@@ -292,10 +378,19 @@ ImageList_display(VALUE self)
292
378
 
293
379
  // Convert the images array to an images sequence.
294
380
  images = images_from_imagelist(self);
295
-
296
- (void) DisplayImages(info, images);
381
+ #if defined(IMAGEMAGICK_7)
382
+ exception = AcquireExceptionInfo();
383
+ DisplayImages(info, images, exception);
384
+ rm_split(images);
385
+ CHECK_EXCEPTION();
386
+ DestroyExceptionInfo(exception);
387
+ #else
388
+ DisplayImages(info, images);
297
389
  rm_split(images);
298
390
  rm_check_image_exception(images, RetainOnError);
391
+ #endif
392
+
393
+ RB_GC_GUARD(info_obj);
299
394
 
300
395
  return self;
301
396
  }
@@ -304,179 +399,46 @@ ImageList_display(VALUE self)
304
399
  /**
305
400
  * Merge all the images into a single image.
306
401
  *
307
- * Ruby usage:
308
- * - @verbatim ImageList#flatten_images @endverbatim
309
- *
310
- * Notes:
311
- * - Can't use "flatten" because that's an Array method
312
- *
313
- * @param self this object
314
- * @return the new image
402
+ * @return [Magick::ImageList] the new image
315
403
  */
316
404
  VALUE
317
405
  ImageList_flatten_images(VALUE self)
318
406
  {
319
407
  Image *images, *new_image;
320
- ExceptionInfo exception;
408
+ ExceptionInfo *exception;
321
409
 
322
410
  images = images_from_imagelist(self);
323
- GetExceptionInfo(&exception);
324
-
325
- #if defined(HAVE_ENUM_FLATTENLAYER)
326
- new_image = MergeImageLayers(images, FlattenLayer, &exception);
327
- #else
328
- new_image = FlattenImages(images, &exception);
329
- #endif
330
-
331
- rm_split(images);
332
- rm_check_exception(&exception, new_image, DestroyOnError);
333
- (void) DestroyExceptionInfo(&exception);
411
+ exception = AcquireExceptionInfo();
334
412
 
335
- rm_ensure_result(new_image);
413
+ new_image = MergeImageLayers(images, FlattenLayer, exception);
336
414
 
337
- return rm_image_new(new_image);
338
- }
339
-
340
-
341
- /**
342
- * Apply fx on the images.
343
- *
344
- * Ruby usage:
345
- * - @verbatim ImageList#fx(expression) @endverbatim
346
- * - @verbatim ImageList#fx(expression, channel) @endverbatim
347
- * - @verbatim ImageList#fx(expression, channel, ...) @endverbatim
348
- *
349
- * Notes:
350
- * - Default channel is AllChannels
351
- *
352
- * @param argc number of input arguments
353
- * @param argv array of input arguments
354
- * @param self this object
355
- * @return a new image
356
- */
357
- VALUE
358
- ImageList_fx(int argc, VALUE *argv, VALUE self)
359
- {
360
- Image *images, *new_image;
361
- char *expression;
362
- ChannelType channels;
363
- ExceptionInfo exception;
364
-
365
-
366
- channels = extract_channels(&argc, argv);
367
-
368
- // There must be exactly 1 remaining argument.
369
- if (argc == 0)
370
- {
371
- rb_raise(rb_eArgError, "wrong number of arguments (0 for 1 or more)");
372
- }
373
- else if (argc > 1)
374
- {
375
- raise_ChannelType_error(argv[argc-1]);
376
- }
377
-
378
- expression = StringValuePtr(argv[0]);
379
-
380
- images = images_from_imagelist(self);
381
- GetExceptionInfo(&exception);
382
- new_image = FxImageChannel(images, channels, expression, &exception);
383
415
  rm_split(images);
384
- rm_check_exception(&exception, new_image, DestroyOnError);
385
- (void) DestroyExceptionInfo(&exception);
386
-
387
- rm_ensure_result(new_image);
416
+ rm_check_exception(exception, new_image, DestroyOnError);
417
+ DestroyExceptionInfo(exception);
388
418
 
389
419
  return rm_image_new(new_image);
390
420
  }
391
421
 
392
422
 
393
423
  /**
394
- * Call MapImages.
395
- *
396
- * Ruby usage:
397
- * - @verbatim ImageList#map(reference) @endverbatim
398
- * - @verbatim ImageList#map(reference, dither) @endverbatim
399
- *
400
- * Notes:
401
- * - Default dither is false
402
- * - Sets \@scene to self.scene
403
- *
404
- * @param argc number of input arguments
405
- * @param argv array of input arguments
406
- * @param self this object
407
- * @return a new ImageList with mapped images.
408
- */
409
- VALUE
410
- ImageList_map(int argc, VALUE *argv, VALUE self)
411
- {
412
- Image *images, *new_images = NULL;
413
- Image *map;
414
- unsigned int dither = MagickFalse;
415
- volatile VALUE scene, new_imagelist, t;
416
- ExceptionInfo exception;
417
-
418
- #if defined(HAVE_REMAPIMAGES)
419
- rb_warning("ImageList#map is deprecated. Use ImageList#remap instead.");
420
- #endif
421
-
422
- switch (argc)
423
- {
424
- case 2:
425
- dither = RTEST(argv[1]);
426
- case 1:
427
- t = rm_cur_image(argv[0]);
428
- map = rm_check_destroyed(t);
429
- break;
430
- default:
431
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
432
- break;
433
- }
434
-
435
-
436
- // Convert image array to image sequence, clone image sequence.
437
- GetExceptionInfo(&exception);
438
-
439
- images = images_from_imagelist(self);
440
- new_images = CloneImageList(images, &exception);
441
- rm_split(images);
442
- rm_check_exception(&exception, new_images, DestroyOnError);
443
- (void) DestroyExceptionInfo(&exception);
444
-
445
- rm_ensure_result(new_images);
446
-
447
- // Call ImageMagick
448
- (void) MapImages(new_images, map, dither);
449
- rm_check_image_exception(new_images, DestroyOnError);
450
-
451
- // Set @scene in new ImageList object to same value as in self.
452
- new_imagelist = rm_imagelist_from_images(new_images);
453
- scene = rb_iv_get(self, "@scene");
454
- (void) imagelist_scene_eq(new_imagelist, scene);
455
-
456
- return new_imagelist;
457
- }
458
-
459
-
460
- /**
461
- * Call MontageImages.
462
- *
463
- * Ruby usage:
464
- * - @verbatim ImageList#montage <{parm block}> @endverbatim
424
+ * Tile one or more thumbnails across an image canvas.
465
425
  *
466
- * Notes:
467
- * - Creates Montage object, yields to block if present in Montage object's
468
- * scope.
426
+ * @overload montage
469
427
  *
470
- * @param self this object
471
- * @return a new image list
428
+ * @overload montage
429
+ * Creates {Magick::ImageList::Montage} object, yields to block
430
+ * if present in {Magick::ImageList::Montage} object's scope.
431
+ * @yield []
432
+ *
433
+ * @return [Magick::ImageList] a new image list
472
434
  */
473
435
  VALUE
474
436
  ImageList_montage(VALUE self)
475
437
  {
476
- volatile VALUE montage_obj;
438
+ VALUE montage_obj;
477
439
  Montage *montage;
478
440
  Image *new_images, *images;
479
- ExceptionInfo exception;
441
+ ExceptionInfo *exception;
480
442
 
481
443
  // Create a new instance of the Magick::Montage class
482
444
  montage_obj = rm_montage_new();
@@ -484,32 +446,41 @@ ImageList_montage(VALUE self)
484
446
  {
485
447
  // Run the block in the instance's context, allowing the app to modify the
486
448
  // object's attributes.
487
- (void) rb_obj_instance_eval(0, NULL, montage_obj);
449
+ if (rb_proc_arity(rb_block_proc()) == 0)
450
+ {
451
+ rb_obj_instance_eval(0, NULL, montage_obj);
452
+ }
453
+ else
454
+ {
455
+ rb_yield(montage_obj);
456
+ }
488
457
  }
489
458
 
490
459
  Data_Get_Struct(montage_obj, Montage, montage);
491
460
 
492
461
  images = images_from_imagelist(self);
493
462
 
494
- // If app specified a non-default composition operator, use it for all images.
495
- if (montage->compose != UndefinedCompositeOp)
463
+ for (Image *image = images; image; image = GetNextImageInList(image))
496
464
  {
497
- Image *i;
498
- for (i = images; i; i = GetNextImageInList(i))
465
+ if (montage->compose != UndefinedCompositeOp)
499
466
  {
500
- i->compose = montage->compose;
467
+ image->compose = montage->compose;
501
468
  }
469
+ image->background_color = montage->info->background_color;
470
+ image->border_color = montage->info->border_color;
471
+ image->matte_color = montage->info->matte_color;
472
+ image->gravity = montage->info->gravity;
502
473
  }
503
474
 
504
- GetExceptionInfo(&exception);
475
+ exception = AcquireExceptionInfo();
505
476
 
506
477
  // MontageImage can return more than one image.
507
- new_images = MontageImages(images, montage->info, &exception);
478
+ new_images = MontageImages(images, montage->info, exception);
508
479
  rm_split(images);
509
- rm_check_exception(&exception, new_images, DestroyOnError);
510
- (void) DestroyExceptionInfo(&exception);
480
+ rm_check_exception(exception, new_images, DestroyOnError);
481
+ DestroyExceptionInfo(exception);
511
482
 
512
- rm_ensure_result(new_images);
483
+ RB_GC_GUARD(montage_obj);
513
484
 
514
485
  return rm_imagelist_from_images(new_images);
515
486
  }
@@ -517,23 +488,17 @@ ImageList_montage(VALUE self)
517
488
 
518
489
  /**
519
490
  * Requires a minimum of two images. The first image is transformed into the
520
- * second by a number of intervening images as specified by "number_images".
521
- *
522
- * Ruby usage:
523
- * - @verbatim ImageList#morph(number_images) @endverbatim
524
- *
525
- * Notes:
526
- * - Sets \@scenes to 0
491
+ * second by a number of intervening images as specified by "nimages".
527
492
  *
528
- * @param self this object
529
- * @param nimages the number of images
530
- * @return a new image list with the images array set to the morph sequence.
493
+ * @note Sets +@scenes+ to 0
494
+ * @param nimages [Numeric] the number of images
495
+ * @return [Magick::ImageList] a new image list with the images array set to the morph sequence.
531
496
  */
532
497
  VALUE
533
498
  ImageList_morph(VALUE self, VALUE nimages)
534
499
  {
535
500
  Image *images, *new_images;
536
- ExceptionInfo exception;
501
+ ExceptionInfo *exception;
537
502
  long number_images;
538
503
 
539
504
 
@@ -544,14 +509,12 @@ ImageList_morph(VALUE self, VALUE nimages)
544
509
  rb_raise(rb_eArgError, "number of intervening images must be > 0");
545
510
  }
546
511
 
547
- GetExceptionInfo(&exception);
548
512
  images = images_from_imagelist(self);
549
- new_images = MorphImages(images, (unsigned long)number_images, &exception);
513
+ exception = AcquireExceptionInfo();
514
+ new_images = MorphImages(images, (unsigned long)number_images, exception);
550
515
  rm_split(images);
551
- rm_check_exception(&exception, new_images, DestroyOnError);
552
- (void) DestroyExceptionInfo(&exception);
553
-
554
- rm_ensure_result(new_images);
516
+ rm_check_exception(exception, new_images, DestroyOnError);
517
+ DestroyExceptionInfo(exception);
555
518
 
556
519
  return rm_imagelist_from_images(new_images);
557
520
  }
@@ -560,151 +523,130 @@ ImageList_morph(VALUE self, VALUE nimages)
560
523
  /**
561
524
  * Merge all the images into a single image.
562
525
  *
563
- * Ruby usage:
564
- * - @verbatim ImageList#mosaic @endverbatim
565
- *
566
- * @param self this object
567
- * @return the new image
526
+ * @return [Magick::Image] the new image
568
527
  */
569
528
  VALUE
570
529
  ImageList_mosaic(VALUE self)
571
530
  {
572
531
  Image *images, *new_image;
573
- ExceptionInfo exception;
532
+ ExceptionInfo *exception;
574
533
 
575
- GetExceptionInfo(&exception);
576
534
  images = images_from_imagelist(self);
577
535
 
578
- #if defined(HAVE_ENUM_MOSAICLAYER)
579
- new_image = MergeImageLayers(images, MosaicLayer, &exception);
580
- #else
581
- new_image = MosaicImages(images, &exception);
582
- #endif
536
+ exception = AcquireExceptionInfo();
537
+ new_image = MergeImageLayers(images, MosaicLayer, exception);
583
538
 
584
539
  rm_split(images);
585
- rm_check_exception(&exception, new_image, DestroyOnError);
586
- (void) DestroyExceptionInfo(&exception);
587
-
588
- rm_ensure_result(new_image);
540
+ rm_check_exception(exception, new_image, DestroyOnError);
541
+ DestroyExceptionInfo(exception);
589
542
 
590
543
  return rm_image_new(new_image);
591
544
  }
592
545
 
593
546
 
594
547
  /**
595
- * Equivalent to -layers option in ImageMagick 6.2.6.
596
- *
597
- * Ruby usage:
598
- * - @verbatim ImageList#optimize_layers(method) @endverbatim
548
+ * Optimizes or compares the images in the list.
549
+ * Equivalent to the -layers option in ImageMagick's mogrify command.
599
550
  *
600
- * @param self this object
601
- * @param method the method to use
602
- * @return a new imagelist
551
+ * @param method [Magick::LayerMethod] the method to use
552
+ * @return [Magick::ImageList] a new imagelist
603
553
  */
604
554
  VALUE
605
555
  ImageList_optimize_layers(VALUE self, VALUE method)
606
556
  {
607
557
  Image *images, *new_images, *new_images2;
608
- LAYERMETHODTYPE mthd;
609
- ExceptionInfo exception;
558
+ LayerMethod mthd;
559
+ ExceptionInfo *exception;
610
560
  QuantizeInfo quantize_info;
611
561
 
612
562
  new_images2 = NULL; // defeat "unused variable" message
613
563
 
614
- GetExceptionInfo(&exception);
615
- #if defined(HAVE_TYPE_IMAGELAYERMETHOD)
616
- VALUE_TO_ENUM(method, mthd, ImageLayerMethod);
617
- #else
618
- VALUE_TO_ENUM(method, mthd, MagickLayerMethod);
619
- #endif
564
+ VALUE_TO_ENUM(method, mthd, LayerMethod);
620
565
  images = images_from_imagelist(self);
621
566
 
567
+ exception = AcquireExceptionInfo();
622
568
  switch (mthd)
623
569
  {
624
570
  case CoalesceLayer:
625
- new_images = CoalesceImages(images, &exception);
571
+ new_images = CoalesceImages(images, exception);
626
572
  break;
627
573
  case DisposeLayer:
628
- new_images = DisposeImages(images, &exception);
574
+ new_images = DisposeImages(images, exception);
629
575
  break;
630
576
  case OptimizeTransLayer:
631
577
  new_images = clone_imagelist(images);
632
- OptimizeImageTransparency(new_images, &exception);
578
+ OptimizeImageTransparency(new_images, exception);
633
579
  break;
634
580
  case RemoveDupsLayer:
635
581
  new_images = clone_imagelist(images);
636
- RemoveDuplicateLayers(&new_images, &exception);
582
+ RemoveDuplicateLayers(&new_images, exception);
637
583
  break;
638
584
  case RemoveZeroLayer:
639
585
  new_images = clone_imagelist(images);
640
- RemoveZeroDelayLayers(&new_images, &exception);
586
+ RemoveZeroDelayLayers(&new_images, exception);
641
587
  break;
642
588
  case CompositeLayer:
643
589
  rm_split(images);
590
+ DestroyExceptionInfo(exception);
644
591
  rb_raise(rb_eNotImpError, "Magick::CompositeLayer is not supported. Use the composite_layers method instead.");
645
592
  break;
646
593
  // In 6.3.4-ish, OptimizeImageLayer replaced OptimizeLayer
647
594
  case OptimizeImageLayer:
648
- new_images = OptimizeImageLayers(images, &exception);
595
+ new_images = OptimizeImageLayers(images, exception);
649
596
  break;
650
597
  // and OptimizeLayer became a "General Purpose, GIF Animation Optimizer" (ref. mogrify.c)
651
598
  case OptimizeLayer:
652
- new_images = CoalesceImages(images, &exception);
599
+ new_images = CoalesceImages(images, exception);
653
600
  rm_split(images);
654
- rm_check_exception(&exception, new_images, DestroyOnError);
655
- new_images2 = OptimizeImageLayers(new_images, &exception);
601
+ rm_check_exception(exception, new_images, DestroyOnError);
602
+ new_images2 = OptimizeImageLayers(new_images, exception);
656
603
  DestroyImageList(new_images);
657
- rm_check_exception(&exception, new_images2, DestroyOnError);
604
+ rm_check_exception(exception, new_images2, DestroyOnError);
658
605
  new_images = new_images2;
659
- OptimizeImageTransparency(new_images, &exception);
660
- rm_check_exception(&exception, new_images, DestroyOnError);
606
+ OptimizeImageTransparency(new_images, exception);
607
+ rm_check_exception(exception, new_images, DestroyOnError);
661
608
  // mogrify supports -dither here. We don't.
662
- #if defined(HAVE_REMAPIMAGE)
663
609
  GetQuantizeInfo(&quantize_info);
664
- (void) RemapImages(&quantize_info, new_images, NULL);
610
+ #if defined(IMAGEMAGICK_7)
611
+ RemapImages(&quantize_info, new_images, NULL, exception);
665
612
  #else
666
- (void) MapImages(new_images, NULL, 0);
613
+ RemapImages(&quantize_info, new_images, NULL);
667
614
  #endif
668
615
  break;
669
616
  case OptimizePlusLayer:
670
- new_images = OptimizePlusImageLayers(images, &exception);
617
+ new_images = OptimizePlusImageLayers(images, exception);
671
618
  break;
672
619
  case CompareAnyLayer:
673
620
  case CompareClearLayer:
674
621
  case CompareOverlayLayer:
675
- new_images = CompareImageLayers(images, mthd, &exception);
622
+ #if defined(IMAGEMAGICK_7)
623
+ new_images = CompareImagesLayers(images, mthd, exception);
624
+ #else
625
+ new_images = CompareImageLayers(images, mthd, exception);
626
+ #endif
676
627
  break;
677
- #if defined(HAVE_ENUM_MOSAICLAYER)
678
628
  case MosaicLayer:
679
- new_images = MergeImageLayers(images, mthd, &exception);
629
+ new_images = MergeImageLayers(images, mthd, exception);
680
630
  break;
681
- #endif
682
- #if defined(HAVE_ENUM_FLATTENLAYER)
683
631
  case FlattenLayer:
684
- new_images = MergeImageLayers(images, mthd, &exception);
632
+ new_images = MergeImageLayers(images, mthd, exception);
685
633
  break;
686
- #endif
687
- #if defined(HAVE_ENUM_MERGELAYER)
688
634
  case MergeLayer:
689
- new_images = MergeImageLayers(images, mthd, &exception);
635
+ new_images = MergeImageLayers(images, mthd, exception);
690
636
  break;
691
- #endif
692
- #if defined(HAVE_ENUM_TRIMBOUNDSLAYER)
693
637
  case TrimBoundsLayer:
694
- new_images = MergeImageLayers(images, mthd, &exception);
638
+ new_images = MergeImageLayers(images, mthd, exception);
695
639
  break;
696
- #endif
697
640
  default:
698
641
  rm_split(images);
642
+ DestroyExceptionInfo(exception);
699
643
  rb_raise(rb_eArgError, "undefined layer method");
700
644
  break;
701
645
  }
702
646
 
703
647
  rm_split(images);
704
- rm_check_exception(&exception, new_images, DestroyOnError);
705
- (void) DestroyExceptionInfo(&exception);
706
-
707
- rm_ensure_result(new_images);
648
+ rm_check_exception(exception, new_images, DestroyOnError);
649
+ DestroyExceptionInfo(exception);
708
650
 
709
651
  return rm_imagelist_from_images(new_images);
710
652
  }
@@ -742,23 +684,24 @@ ImageList_new(void)
742
684
  VALUE
743
685
  rm_imagelist_from_images(Image *images)
744
686
  {
745
- volatile VALUE new_imagelist;
746
- Image *image;
687
+ VALUE new_imagelist;
747
688
 
748
- if (!images)
749
- {
750
- rb_bug("rm_imagelist_from_images called with NULL argument");
751
- }
689
+ rm_ensure_result(images);
752
690
 
753
691
  new_imagelist = ImageList_new();
754
692
 
755
693
  while (images)
756
694
  {
695
+ Image *image;
696
+
757
697
  image = RemoveFirstImageFromList(&images);
758
698
  imagelist_push(new_imagelist, rm_image_new(image));
759
699
  }
760
700
 
761
- (void) rb_iv_set(new_imagelist, "@scene", INT2FIX(0));
701
+ rb_iv_set(new_imagelist, "@scene", INT2FIX(0));
702
+
703
+ RB_GC_GUARD(new_imagelist);
704
+
762
705
  return new_imagelist;
763
706
  }
764
707
 
@@ -778,7 +721,7 @@ images_from_imagelist(VALUE imagelist)
778
721
  {
779
722
  long x, len;
780
723
  Image *head = NULL;
781
- volatile VALUE images, t;
724
+ VALUE images, t;
782
725
 
783
726
  len = check_imagelist_length(imagelist);
784
727
 
@@ -789,28 +732,21 @@ images_from_imagelist(VALUE imagelist)
789
732
 
790
733
  t = rb_ary_entry(images, x);
791
734
  image = rm_check_destroyed(t);
735
+ // avoid a loop in this linked imagelist, issue #202
736
+ if (head == image || GetPreviousImageInList(image) != NULL)
737
+ {
738
+ image = rm_clone_image(image);
739
+
740
+ // Wrap raw ImageMagick object by Ruby object to destroy using Ruby's GC.
741
+ rm_image_new(image);
742
+ }
792
743
  AppendImageToList(&head, image);
793
744
  }
794
745
 
795
- return head;
796
- }
746
+ RB_GC_GUARD(images);
747
+ RB_GC_GUARD(t);
797
748
 
798
-
799
- /**
800
- * \@scene attribute writer.
801
- *
802
- * No Ruby usage (internal function)
803
- *
804
- * @param imagelist the imagelist
805
- * @param scene the scene
806
- * @return the scene
807
- */
808
- static VALUE
809
- imagelist_scene_eq(VALUE imagelist, VALUE scene)
810
- {
811
- rb_check_frozen(imagelist);
812
- (void) rb_iv_set(imagelist, "@scene", scene);
813
- return scene;
749
+ return head;
814
750
  }
815
751
 
816
752
 
@@ -825,7 +761,14 @@ imagelist_scene_eq(VALUE imagelist, VALUE scene)
825
761
  static long
826
762
  imagelist_length(VALUE imagelist)
827
763
  {
828
- volatile VALUE images = rb_iv_get(imagelist, "@images");
764
+ VALUE images = rb_iv_get(imagelist, "@images");
765
+ if (!RB_TYPE_P(images, T_ARRAY))
766
+ {
767
+ rb_raise(Class_ImageMagickError, "@images is not of type Array");
768
+ }
769
+
770
+ RB_GC_GUARD(images);
771
+
829
772
  return RARRAY_LEN(images);
830
773
  }
831
774
 
@@ -865,7 +808,7 @@ static void
865
808
  imagelist_push(VALUE imagelist, VALUE image)
866
809
  {
867
810
  rb_check_frozen(imagelist);
868
- (void) rb_funcall(imagelist, rm_ID_push, 1, image);
811
+ rb_funcall(imagelist, rm_ID_push, 1, image);
869
812
  }
870
813
 
871
814
 
@@ -880,48 +823,39 @@ imagelist_push(VALUE imagelist, VALUE image)
880
823
  static Image *
881
824
  clone_imagelist(Image *images)
882
825
  {
883
- Image *new_imagelist = NULL, *image, *clone;
884
- ExceptionInfo exception;
826
+ Image *new_imagelist = NULL, *image;
827
+ ExceptionInfo *exception;
885
828
 
886
- GetExceptionInfo(&exception);
829
+ exception = AcquireExceptionInfo();
887
830
 
888
831
  image = GetFirstImageInList(images);
889
832
  while (image)
890
833
  {
891
- clone = CloneImage(image, 0, 0, MagickTrue, &exception);
892
- rm_check_exception(&exception, new_imagelist, DestroyOnError);
834
+ Image *clone;
835
+
836
+ clone = CloneImage(image, 0, 0, MagickTrue, exception);
837
+ rm_check_exception(exception, new_imagelist, DestroyOnError);
893
838
  AppendImageToList(&new_imagelist, clone);
894
839
  image = GetNextImageInList(image);
895
840
  }
896
841
 
897
- (void) DestroyExceptionInfo(&exception);
842
+ DestroyExceptionInfo(exception);
898
843
  return new_imagelist;
899
844
  }
900
845
 
901
846
 
902
847
  /**
903
- * Call QuantizeImages.
904
- *
905
- * Ruby usage:
906
- * - @verbatim ImageList#quantize @endverbatim
907
- * - @verbatim ImageList#quantize(number_colors) @endverbatim
908
- * - @verbatim ImageList#quantize(number_colors, colorspace) @endverbatim
909
- * - @verbatim ImageList#quantize(number_colors, colorspace, dither) @endverbatim
910
- * - @verbatim ImageList#quantize(number_colors, colorspace, dither, tree_depth) @endverbatim
911
- * - @verbatim ImageList#quantize(number_colors, colorspace, dither, tree_depth, measure_error) @endverbatim
912
- *
913
- * Notes:
914
- * - Default number_colors is 256
915
- * - Default coorspace is Magick::RGBColorsapce
916
- * - Default dither is true
917
- * - Default tree_depth is 0
918
- * - Default measure_error is false
919
- * - Sets \@scene to the same value as self.scene
920
- *
921
- * @param argc number of input arguments
922
- * @param argv array of input arguments
923
- * @param self this object
924
- * @return a new ImageList with quantized images
848
+ * Analyzes the colors within a set of reference images and chooses a fixed number of colors to represent the set.
849
+ * The goal of the algorithm is to minimize the difference between the input and output images while minimizing the processing time.
850
+ *
851
+ * @overload quantize(number_colors = 256, colorspace = Magick::RGBColorsapce, dither = true, tree_depth = 0, measure_error = false)
852
+ * @param number_colors [Numeric] the maximum number of colors to use in the output images.
853
+ * @param colorspace [Magick::ColorspaceType] the colorspace to quantize in.
854
+ * @param dither [Magick::DitherMethod, Boolean] a DitherMethod value or true if you want apply dither.
855
+ * @param tree_depth [Numeric] specify the tree depth to use while quantizing.
856
+ * @param measure_error [Boolean] calculate quantization errors when quantizing the image.
857
+ * @return [Magick::ImageList] a new ImageList with quantized images
858
+ * @note Sets +@scene+ to the same value as +self.scene+
925
859
  */
926
860
  VALUE
927
861
  ImageList_quantize(int argc, VALUE *argv, VALUE self)
@@ -929,8 +863,8 @@ ImageList_quantize(int argc, VALUE *argv, VALUE self)
929
863
  Image *images, *new_images;
930
864
  Image *new_image;
931
865
  QuantizeInfo quantize_info;
932
- ExceptionInfo exception;
933
- volatile VALUE new_imagelist, scene;
866
+ ExceptionInfo *exception;
867
+ VALUE new_imagelist, scene;
934
868
 
935
869
  GetQuantizeInfo(&quantize_info);
936
870
 
@@ -941,14 +875,25 @@ ImageList_quantize(int argc, VALUE *argv, VALUE self)
941
875
  case 4:
942
876
  quantize_info.tree_depth = (unsigned long)NUM2INT(argv[3]);
943
877
  case 3:
944
- #if defined(HAVE_TYPE_DITHERMETHOD) && defined(HAVE_ENUM_NODITHERMETHOD)
878
+ #if defined(IMAGEMAGICK_7)
945
879
  if (rb_obj_is_kind_of(argv[2], Class_DitherMethod))
946
880
  {
947
881
  VALUE_TO_ENUM(argv[2], quantize_info.dither_method, DitherMethod);
948
- quantize_info.dither = quantize_info.dither_method != NoDitherMethod;
882
+ }
883
+ else
884
+ {
885
+ quantize_info.dither_method = RTEST(argv[2]) ? UndefinedDitherMethod : NoDitherMethod;
949
886
  }
950
887
  #else
951
- quantize_info.dither = (MagickBooleanType) RTEST(argv[2]);
888
+ if (rb_obj_is_kind_of(argv[2], Class_DitherMethod))
889
+ {
890
+ VALUE_TO_ENUM(argv[2], quantize_info.dither_method, DitherMethod);
891
+ quantize_info.dither = quantize_info.dither_method != NoDitherMethod;
892
+ }
893
+ else
894
+ {
895
+ quantize_info.dither = (MagickBooleanType) RTEST(argv[2]);
896
+ }
952
897
  #endif
953
898
  case 2:
954
899
  VALUE_TO_ENUM(argv[1], quantize_info.colorspace, ColorspaceType);
@@ -963,18 +908,21 @@ ImageList_quantize(int argc, VALUE *argv, VALUE self)
963
908
 
964
909
 
965
910
  // Convert image array to image sequence, clone image sequence.
966
- GetExceptionInfo(&exception);
967
911
  images = images_from_imagelist(self);
968
- new_images = CloneImageList(images, &exception);
912
+ exception = AcquireExceptionInfo();
913
+ new_images = CloneImageList(images, exception);
969
914
  rm_split(images);
970
- rm_check_exception(&exception, new_images, DestroyOnError);
971
- (void) DestroyExceptionInfo(&exception);
915
+ rm_check_exception(exception, new_images, DestroyOnError);
972
916
 
973
917
  rm_ensure_result(new_images);
974
918
 
975
-
976
- (void) QuantizeImages(&quantize_info, new_images);
977
- rm_check_exception(&exception, new_images, DestroyOnError);
919
+ #if defined(IMAGEMAGICK_7)
920
+ QuantizeImages(&quantize_info, new_images, exception);
921
+ #else
922
+ QuantizeImages(&quantize_info, new_images);
923
+ #endif
924
+ rm_check_exception(exception, new_images, DestroyOnError);
925
+ DestroyExceptionInfo(exception);
978
926
 
979
927
  // Create new ImageList object, convert mapped image sequence to images,
980
928
  // append to images array.
@@ -986,42 +934,39 @@ ImageList_quantize(int argc, VALUE *argv, VALUE self)
986
934
 
987
935
  // Set @scene in new ImageList object to same value as in self.
988
936
  scene = rb_iv_get(self, "@scene");
989
- (void) rb_iv_set(new_imagelist, "@scene", scene);
937
+ rb_iv_set(new_imagelist, "@scene", scene);
938
+
939
+ RB_GC_GUARD(new_imagelist);
940
+ RB_GC_GUARD(scene);
990
941
 
991
942
  return new_imagelist;
992
943
  }
993
944
 
994
945
 
995
946
  /**
996
- * Call RemapImages.
997
- *
998
- * Ruby usage:
999
- * - @verbatim ImageList#remap @endverbatim
1000
- * - @verbatim ImageList#remap(remap_image) @endverbatim
1001
- * - @verbatim ImageList#remap(remap_image, dither_method) @endverbatim
1002
- *
1003
- * Notes:
1004
- * - Default remap_image is nil
1005
- * - Default dither_method is RiemersmaDitherMethod
1006
- * - Modifies images in-place.
1007
- *
1008
- * @param argc number of input arguments
1009
- * @param argv array of input arguments
1010
- * @param self this object
1011
- * @see Image_remap
947
+ * Reduce the colors used in the image list to the set of colors in +remap_image+.
948
+ *
949
+ * @overload remap(remap_image = nil, dither_method = Magick::RiemersmaDitherMethod)
950
+ * @param remap_image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
951
+ * imagelist, uses the current image.
952
+ * @param dither_method [Magick::DitherMethod] a DitherMethod value.
953
+ * @return [Magick::ImageList] self
954
+ * @note Modifies images in-place.
1012
955
  */
1013
956
  VALUE
1014
957
  ImageList_remap(int argc, VALUE *argv, VALUE self)
1015
958
  {
1016
- #if defined(HAVE_REMAPIMAGES) || defined(HAVE_AFFINITYIMAGES)
1017
959
  Image *images, *remap_image = NULL;
1018
960
  QuantizeInfo quantize_info;
1019
-
961
+ #if defined(IMAGEMAGICK_7)
962
+ ExceptionInfo *exception;
963
+ #endif
1020
964
 
1021
965
  if (argc > 0 && argv[0] != Qnil)
1022
966
  {
1023
- volatile VALUE t = rm_cur_image(argv[0]);
967
+ VALUE t = rm_cur_image(argv[0]);
1024
968
  remap_image = rm_check_destroyed(t);
969
+ RB_GC_GUARD(t);
1025
970
  }
1026
971
 
1027
972
  GetQuantizeInfo(&quantize_info);
@@ -1029,7 +974,9 @@ ImageList_remap(int argc, VALUE *argv, VALUE self)
1029
974
  if (argc > 1)
1030
975
  {
1031
976
  VALUE_TO_ENUM(argv[1], quantize_info.dither_method, DitherMethod);
977
+ #if defined(IMAGEMAGICK_6)
1032
978
  quantize_info.dither = MagickTrue;
979
+ #endif
1033
980
  }
1034
981
  if (argc > 2)
1035
982
  {
@@ -1038,48 +985,43 @@ ImageList_remap(int argc, VALUE *argv, VALUE self)
1038
985
 
1039
986
  images = images_from_imagelist(self);
1040
987
 
1041
- #if defined(HAVE_REMAPIMAGE)
1042
- (void) RemapImages(&quantize_info, images, remap_image);
988
+ #if defined(IMAGEMAGICK_7)
989
+ exception = AcquireExceptionInfo();
990
+ RemapImages(&quantize_info, images, remap_image, exception);
991
+ rm_split(images);
992
+ CHECK_EXCEPTION();
993
+ DestroyExceptionInfo(exception);
1043
994
  #else
1044
- (void) AffinityImages(&quantize_info, images, remap_image);
1045
- #endif
1046
- rm_check_image_exception(images, RetainOnError);
995
+ RemapImages(&quantize_info, images, remap_image);
1047
996
  rm_split(images);
997
+ rm_check_image_exception(images, RetainOnError);
998
+ #endif
1048
999
 
1049
1000
  return self;
1050
- #else
1051
- self = self;
1052
- argc = argc;
1053
- argv = argv;
1054
- rm_not_implemented();
1055
- return(VALUE)0;
1056
- #endif
1057
1001
  }
1058
1002
 
1059
1003
 
1060
1004
  /**
1061
1005
  * Return the imagelist as a blob (a String).
1062
1006
  *
1063
- * Ruby usage:
1064
- * - @verbatim ImageList#to_blob @endverbatim
1007
+ * @overload to_blob
1065
1008
  *
1066
- * Notes:
1067
- * - Runs an info parm block if present - the user can specify the image
1068
- * format and depth
1009
+ * @overload to_blob
1010
+ * Runs an info parm block if present - the user can specify the image format and depth
1011
+ * @yield []
1069
1012
  *
1070
- * @param self this object
1071
- * @return the blob
1013
+ * @return [String] the blob
1072
1014
  */
1073
1015
  VALUE
1074
1016
  ImageList_to_blob(VALUE self)
1075
1017
  {
1076
1018
  Image *images, *image;
1077
1019
  Info *info;
1078
- volatile VALUE info_obj;
1079
- volatile VALUE blob_str;
1020
+ VALUE info_obj;
1021
+ VALUE blob_str;
1080
1022
  void *blob = NULL;
1081
1023
  size_t length = 0;
1082
- ExceptionInfo exception;
1024
+ ExceptionInfo *exception;
1083
1025
 
1084
1026
  info_obj = rm_info_new();
1085
1027
  Data_Get_Struct(info_obj, Info, info);
@@ -1087,16 +1029,16 @@ ImageList_to_blob(VALUE self)
1087
1029
  // Convert the images array to an images sequence.
1088
1030
  images = images_from_imagelist(self);
1089
1031
 
1090
- GetExceptionInfo(&exception);
1091
- (void) SetImageInfo(info, MagickTrue, &exception);
1092
- rm_check_exception(&exception, images, RetainOnError);
1032
+ exception = AcquireExceptionInfo();
1033
+ SetImageInfo(info, MagickTrue, exception);
1034
+ rm_check_exception(exception, images, RetainOnError);
1093
1035
 
1094
1036
  if (*info->magick != '\0')
1095
1037
  {
1096
1038
  Image *img;
1097
1039
  for (img = images; img; img = GetNextImageInList(img))
1098
1040
  {
1099
- strncpy(img->magick, info->magick, sizeof(info->magick)-1);
1041
+ strlcpy(img->magick, info->magick, sizeof(img->magick));
1100
1042
  }
1101
1043
  }
1102
1044
 
@@ -1109,16 +1051,16 @@ ImageList_to_blob(VALUE self)
1109
1051
  // can happen is that there's only one image or the format
1110
1052
  // doesn't support multi-image files.
1111
1053
  info->adjoin = MagickTrue;
1112
- blob = ImagesToBlob(info, images, &length, &exception);
1113
- if (blob && exception.severity >= ErrorException)
1054
+ blob = ImagesToBlob(info, images, &length, exception);
1055
+ if (blob && exception->severity >= ErrorException)
1114
1056
  {
1115
1057
  magick_free((void*)blob);
1116
1058
  blob = NULL;
1117
1059
  length = 0;
1118
1060
  }
1119
1061
  rm_split(images);
1120
- CHECK_EXCEPTION()
1121
- (void) DestroyExceptionInfo(&exception);
1062
+ CHECK_EXCEPTION();
1063
+ DestroyExceptionInfo(exception);
1122
1064
 
1123
1065
 
1124
1066
  if (length == 0 || !blob)
@@ -1129,6 +1071,9 @@ ImageList_to_blob(VALUE self)
1129
1071
  blob_str = rb_str_new(blob, (long)length);
1130
1072
  magick_free((void*)blob);
1131
1073
 
1074
+ RB_GC_GUARD(info_obj);
1075
+ RB_GC_GUARD(blob_str);
1076
+
1132
1077
  return blob_str;
1133
1078
  }
1134
1079
 
@@ -1139,12 +1084,7 @@ ImageList_to_blob(VALUE self)
1139
1084
  * the images will be written as a single multi-image file. Otherwise each image
1140
1085
  * will be written to a separate file.
1141
1086
  *
1142
- * Ruby usage:
1143
- * - @verbatim ImageList#write(file) @endverbatim
1144
- *
1145
- * @param self this object
1146
- * @param file the file
1147
- * @return self
1087
+ * @param file [File, String] the file
1148
1088
  */
1149
1089
  VALUE
1150
1090
  ImageList_write(VALUE self, VALUE file)
@@ -1152,9 +1092,9 @@ ImageList_write(VALUE self, VALUE file)
1152
1092
  Image *images, *img;
1153
1093
  Info *info;
1154
1094
  const MagickInfo *m;
1155
- volatile VALUE info_obj;
1095
+ VALUE info_obj;
1156
1096
  unsigned long scene;
1157
- ExceptionInfo exception;
1097
+ ExceptionInfo *exception;
1158
1098
 
1159
1099
  info_obj = rm_info_new();
1160
1100
  Data_Get_Struct(info_obj, Info, info);
@@ -1162,11 +1102,16 @@ ImageList_write(VALUE self, VALUE file)
1162
1102
 
1163
1103
  if (TYPE(file) == T_FILE)
1164
1104
  {
1165
- OpenFile *fptr;
1105
+ rb_io_t *fptr;
1166
1106
 
1167
1107
  // Ensure file is open - raise error if not
1168
1108
  GetOpenFile(file, fptr);
1169
- SetImageInfoFile(info, GetReadFile(fptr));
1109
+ #if defined(_WIN32)
1110
+ add_format_prefix(info, fptr->pathv);
1111
+ SetImageInfoFile(info, NULL);
1112
+ #else
1113
+ SetImageInfoFile(info, rb_io_stdio_file(fptr));
1114
+ #endif
1170
1115
  }
1171
1116
  else
1172
1117
  {
@@ -1182,20 +1127,22 @@ ImageList_write(VALUE self, VALUE file)
1182
1127
  for (scene = 0, img = images; img; img = GetNextImageInList(img))
1183
1128
  {
1184
1129
  img->scene = scene++;
1185
- strcpy(img->filename, info->filename);
1130
+ strlcpy(img->filename, info->filename, sizeof(img->filename));
1186
1131
  }
1187
1132
 
1188
1133
  // Find out if the format supports multi-images files.
1189
- GetExceptionInfo(&exception);
1190
- (void) SetImageInfo(info, MagickTrue, &exception);
1191
- rm_check_exception(&exception, images, RetainOnError);
1192
-
1193
- m = GetMagickInfo(info->magick, &exception);
1194
- rm_check_exception(&exception, images, RetainOnError);
1195
- (void) DestroyExceptionInfo(&exception);
1134
+ exception = AcquireExceptionInfo();
1135
+ SetImageInfo(info, MagickTrue, exception);
1136
+ rm_check_exception(exception, images, RetainOnError);
1137
+
1138
+ m = GetMagickInfo(info->magick, exception);
1139
+ rm_check_exception(exception, images, RetainOnError);
1140
+ #if defined(IMAGEMAGICK_6)
1141
+ DestroyExceptionInfo(exception);
1142
+ #endif
1196
1143
 
1197
1144
  // Tell WriteImage if we want a multi-images file.
1198
- if (imagelist_length(self) > 1L && m->adjoin)
1145
+ if (imagelist_length(self) > 1L && GetMagickAdjoin(m))
1199
1146
  {
1200
1147
  info->adjoin = MagickTrue;
1201
1148
  }
@@ -1203,15 +1150,27 @@ ImageList_write(VALUE self, VALUE file)
1203
1150
  for (img = images; img; img = GetNextImageInList(img))
1204
1151
  {
1205
1152
  rm_sync_image_options(img, info);
1206
- (void) WriteImage(info, img);
1153
+ #if defined(IMAGEMAGICK_7)
1154
+ WriteImage(info, img, exception);
1155
+ rm_check_exception(exception, img, RetainOnError);
1156
+ #else
1157
+ WriteImage(info, img);
1207
1158
  // images will be split before raising an exception
1208
1159
  rm_check_image_exception(images, RetainOnError);
1160
+ #endif
1209
1161
  if (info->adjoin)
1210
1162
  {
1211
1163
  break;
1212
1164
  }
1213
1165
  }
1214
1166
 
1167
+ #if defined(IMAGEMAGICK_7)
1168
+ DestroyExceptionInfo(exception);
1169
+ #endif
1170
+
1215
1171
  rm_split(images);
1172
+
1173
+ RB_GC_GUARD(info_obj);
1174
+
1216
1175
  return self;
1217
1176
  }