rmagick-windows 2.16.1

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