rmagick-windows 2.16.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }