rmagick 3.1.0 → 3.2.0

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

Potentially problematic release.


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

Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.appveyor.yml +4 -4
  3. data/.circleci/config.yml +1 -1
  4. data/.gitignore +1 -0
  5. data/.rubocop_todo.yml +6 -0
  6. data/.travis.yml +26 -8
  7. data/CHANGELOG.md +104 -0
  8. data/before_install_linux.sh +19 -10
  9. data/benchmarks/memory/README.md +50 -0
  10. data/benchmarks/memory/image_new.rb +8 -0
  11. data/benchmarks/memory/rmagick.gnuplot +16 -0
  12. data/doc/ex/coalesce.rb +2 -2
  13. data/doc/ex/drawcomp.rb +3 -3
  14. data/doc/ex/get_pixels.rb +1 -1
  15. data/doc/ex/images/Coffee.png +0 -0
  16. data/doc/ex/images/No.png +0 -0
  17. data/doc/ex/images/Snake.png +0 -0
  18. data/doc/ex/implode.rb +2 -2
  19. data/doc/ex/mask.rb +1 -1
  20. data/doc/ex/matte_fill_to_border.rb +1 -1
  21. data/doc/ex/matte_floodfill.rb +1 -1
  22. data/doc/ex/matte_replace.rb +1 -1
  23. data/doc/ex/stegano.rb +1 -1
  24. data/examples/constitute.rb +1 -1
  25. data/examples/crop_with_gravity.rb +1 -1
  26. data/examples/demo.rb +4 -4
  27. data/examples/find_similar_region.rb +1 -1
  28. data/examples/histogram.rb +3 -3
  29. data/examples/identify.rb +46 -46
  30. data/examples/image_opacity.rb +2 -2
  31. data/examples/vignette.rb +3 -3
  32. data/ext/RMagick/extconf.rb +19 -15
  33. data/ext/RMagick/rmagick.c +1 -2
  34. data/ext/RMagick/rmagick.h +59 -30
  35. data/ext/RMagick/rmdraw.c +62 -274
  36. data/ext/RMagick/rmenum.c +121 -665
  37. data/ext/RMagick/rmfill.c +7 -7
  38. data/ext/RMagick/rmilist.c +91 -7
  39. data/ext/RMagick/rmimage.c +568 -379
  40. data/ext/RMagick/rminfo.c +152 -110
  41. data/ext/RMagick/rmkinfo.c +17 -1
  42. data/ext/RMagick/rmmain.c +75 -74
  43. data/ext/RMagick/rmmontage.c +33 -33
  44. data/ext/RMagick/rmpixel.c +75 -14
  45. data/ext/RMagick/rmstruct.c +5 -5
  46. data/ext/RMagick/rmutil.c +3 -13
  47. data/lib/obsolete.rb +66 -0
  48. data/lib/rmagick/version.rb +1 -1
  49. data/lib/rmagick_internal.rb +54 -41
  50. data/spec/rmagick/image/composite_spec.rb +5 -76
  51. data/spec/rmagick/image/properties_spec.rb +1 -1
  52. data/test/Draw.rb +52 -115
  53. data/test/Enum.rb +153 -1
  54. data/test/Fill.rb +1 -1
  55. data/test/Image1.rb +97 -43
  56. data/test/Image2.rb +140 -36
  57. data/test/Image3.rb +110 -120
  58. data/test/ImageList1.rb +46 -11
  59. data/test/ImageList2.rb +11 -21
  60. data/test/Image_attributes.rb +81 -127
  61. data/test/Import_Export.rb +2 -2
  62. data/test/Info.rb +5 -1
  63. data/test/KernelInfo.rb +67 -0
  64. data/test/Magick.rb +17 -35
  65. data/test/Pixel.rb +193 -24
  66. data/test/PolaroidOptions.rb +1 -1
  67. data/test/Preview.rb +3 -35
  68. data/test/Struct.rb +45 -0
  69. data/test/appearance/Montage.rb +26 -0
  70. data/test/appearance/appearance_assertion.rb +13 -0
  71. data/test/appearance/expected/montage_border_color.jpg +0 -0
  72. data/test/lib/Obsolete.rb +30 -0
  73. data/test/lib/internal/Draw.rb +823 -0
  74. data/test/lib/internal/Geometry.rb +98 -0
  75. data/test/lib/internal/Magick.rb +40 -0
  76. data/test/test_all_basic.rb +16 -17
  77. metadata +27 -5
  78. data/doc/ex/images/Coffee.wmf +0 -0
  79. data/doc/ex/images/No.wmf +0 -0
  80. data/doc/ex/images/Snake.wmf +0 -0
@@ -150,7 +150,7 @@ point_fill(
150
150
  CHECK_EXCEPTION()
151
151
  }
152
152
 
153
- DestroyExceptionInfo(exception);
153
+ (void) DestroyExceptionInfo(exception);
154
154
  }
155
155
 
156
156
  /**
@@ -228,9 +228,9 @@ vertical_fill(
228
228
  }
229
229
  }
230
230
 
231
- DestroyExceptionInfo(exception);
231
+ (void) DestroyExceptionInfo(exception);
232
232
 
233
- xfree((void *)master);
233
+ xfree((void *) master);
234
234
  }
235
235
 
236
236
  /**
@@ -305,9 +305,9 @@ horizontal_fill(
305
305
  }
306
306
  }
307
307
 
308
- DestroyExceptionInfo(exception);
308
+ (void) DestroyExceptionInfo(exception);
309
309
 
310
- xfree((void *)master);
310
+ xfree((void *) master);
311
311
  }
312
312
 
313
313
  /**
@@ -398,7 +398,7 @@ v_diagonal_fill(
398
398
  CHECK_EXCEPTION()
399
399
  }
400
400
 
401
- DestroyExceptionInfo(exception);
401
+ (void) DestroyExceptionInfo(exception);
402
402
  }
403
403
 
404
404
  /**
@@ -491,7 +491,7 @@ h_diagonal_fill(
491
491
  CHECK_EXCEPTION()
492
492
  }
493
493
 
494
- DestroyExceptionInfo(exception);
494
+ (void) DestroyExceptionInfo(exception);
495
495
  }
496
496
 
497
497
  /**
@@ -184,6 +184,88 @@ ImageList_coalesce(VALUE self)
184
184
  }
185
185
 
186
186
 
187
+ /**
188
+ * Combines the images using the specified colorspace.
189
+ *
190
+ * Ruby usage:
191
+ * - @verbatim new_image = ImageList#combine @endverbatim
192
+ * - @verbatim new_image = ImageList#combine(colorspace) @endverbatim
193
+ *
194
+ * Notes:
195
+ * - Calls CombineImages.
196
+ *
197
+ * @param argc number of input arguments
198
+ * @param argv array of input arguments
199
+ * @param self this object
200
+ * @return a new image
201
+ */
202
+ VALUE ImageList_combine(int argc, VALUE *argv, VALUE self)
203
+ {
204
+ ChannelType channel;
205
+ ColorspaceType colorspace, old_colorspace;
206
+ long len;
207
+ Image *images, *new_image;
208
+ ExceptionInfo *exception;
209
+
210
+ len = check_imagelist_length(self);
211
+
212
+ switch (argc)
213
+ {
214
+ case 1:
215
+ VALUE_TO_ENUM(argv[0], colorspace, ColorspaceType);
216
+ break;
217
+ case 0:
218
+ colorspace = sRGBColorspace;
219
+ break;
220
+ default:
221
+ rb_raise(rb_eArgError, "wrong number of arguments (expected 1, got %d)", argc);
222
+ break;
223
+ }
224
+
225
+ channel = RedChannel;
226
+ switch (len)
227
+ {
228
+ case 5:
229
+ if (colorspace == CMYKColorspace)
230
+ channel |= AlphaChannel;
231
+ else
232
+ rb_raise(rb_eArgError, "invalid number of images in this image list");
233
+ case 4:
234
+ if (colorspace == CMYKColorspace)
235
+ channel |= IndexChannel;
236
+ else
237
+ channel |= AlphaChannel;
238
+ case 3:
239
+ channel |= GreenChannel;
240
+ channel |= BlueChannel;
241
+ break;
242
+ case 2:
243
+ channel |= AlphaChannel;
244
+ break;
245
+ case 1:
246
+ break;
247
+ default:
248
+ rb_raise(rb_eArgError, "invalid number of images in this image list");
249
+ break;
250
+ }
251
+
252
+ images = images_from_imagelist(self);
253
+ old_colorspace = images->colorspace;
254
+ SetImageColorspace(images, colorspace);
255
+
256
+ exception = AcquireExceptionInfo();
257
+ new_image = CombineImages(images, channel, exception);
258
+ rm_split(images);
259
+ images->colorspace = old_colorspace;
260
+ rm_check_exception(exception, new_image, DestroyOnError);
261
+ (void) DestroyExceptionInfo(exception);
262
+
263
+ rm_ensure_result(new_image);
264
+
265
+ return rm_image_new(new_image);
266
+ }
267
+
268
+
187
269
  /**
188
270
  * Equivalent to convert's -layers composite option.
189
271
  *
@@ -504,14 +586,16 @@ ImageList_montage(VALUE self)
504
586
 
505
587
  images = images_from_imagelist(self);
506
588
 
507
- // If app specified a non-default composition operator, use it for all images.
508
- if (montage->compose != UndefinedCompositeOp)
589
+ for (Image *image = images; image; image = GetNextImageInList(image))
509
590
  {
510
- Image *i;
511
- for (i = images; i; i = GetNextImageInList(i))
591
+ if (montage->compose != UndefinedCompositeOp)
512
592
  {
513
- i->compose = montage->compose;
593
+ image->compose = montage->compose;
514
594
  }
595
+ image->background_color = montage->info->background_color;
596
+ image->border_color = montage->info->border_color;
597
+ image->matte_color = montage->info->matte_color;
598
+ image->gravity = montage->info->gravity;
515
599
  }
516
600
 
517
601
  exception = AcquireExceptionInfo();
@@ -616,13 +700,13 @@ VALUE
616
700
  ImageList_optimize_layers(VALUE self, VALUE method)
617
701
  {
618
702
  Image *images, *new_images, *new_images2;
619
- ImageLayerMethod mthd;
703
+ LayerMethod mthd;
620
704
  ExceptionInfo *exception;
621
705
  QuantizeInfo quantize_info;
622
706
 
623
707
  new_images2 = NULL; // defeat "unused variable" message
624
708
 
625
- VALUE_TO_ENUM(method, mthd, ImageLayerMethod);
709
+ VALUE_TO_ENUM(method, mthd, LayerMethod);
626
710
  images = images_from_imagelist(self);
627
711
 
628
712
  exception = AcquireExceptionInfo();
@@ -41,6 +41,64 @@ static void call_trace_proc(Image *, const char *);
41
41
  static const char *BlackPointCompensationKey = "PROFILE:black-point-compensation";
42
42
 
43
43
 
44
+ /**
45
+ * Converts the opacity value to alpha and raises a warning.
46
+ *
47
+ * No Ruby usage (internal function)
48
+ *
49
+ * @opacity an opacity value
50
+ */
51
+ static Quantum
52
+ get_alpha_from_opacity(VALUE opacity)
53
+ {
54
+ VALUE method = rb_id2str(rb_frame_this_func());
55
+ rb_warning("Image#%"PRIsVALUE" requires a named argument for 'alpha' and now expects an alpha value instead of an opacity value.", method);
56
+
57
+ return QuantumRange - APP2QUANTUM(opacity);
58
+ }
59
+
60
+ /**
61
+ * Returns the alpha value from the hash.
62
+ *
63
+ * No Ruby usage (internal function)
64
+ *
65
+ * @hash the hash
66
+ */
67
+ static Quantum
68
+ get_alpha_from_hash(VALUE hash)
69
+ {
70
+ if (FIX2ULONG(rb_hash_size(hash)) != 1)
71
+ {
72
+ rb_raise(rb_eArgError, "wrong number of arguments");
73
+ }
74
+
75
+ VALUE alpha = rb_hash_aref(hash, ID2SYM(rb_intern("alpha")));
76
+ if (NIL_P(alpha))
77
+ {
78
+ rb_raise(rb_eArgError, "missing keyword: alpha");
79
+ }
80
+
81
+ return APP2QUANTUM(alpha);
82
+ }
83
+
84
+ /**
85
+ * Checks if opacity_or_alpha is a named argument called alpha and returns the alpha value or
86
+ * converts the unnamed opacity value to alpha.
87
+ *
88
+ * No Ruby usage (internal function)
89
+ *
90
+ * @opacity_or_alpha an opacity or a named alpha value
91
+ */
92
+ static Quantum
93
+ get_named_alpha_value(VALUE opacity_or_alpha)
94
+ {
95
+ if (TYPE(opacity_or_alpha) != T_HASH)
96
+ {
97
+ return get_alpha_from_opacity(opacity_or_alpha);
98
+ }
99
+
100
+ return get_alpha_from_hash(opacity_or_alpha);
101
+ }
44
102
 
45
103
 
46
104
  /**
@@ -371,8 +429,7 @@ Image_adaptive_threshold(int argc, VALUE *argv, VALUE self)
371
429
  VALUE
372
430
  Image_add_compose_mask(VALUE self, VALUE mask)
373
431
  {
374
- Image *image;
375
- Image *mask_image = NULL;
432
+ Image *image, *mask_image = NULL;
376
433
 
377
434
  image = rm_check_frozen(self);
378
435
  mask_image = rm_check_destroyed(mask);
@@ -521,7 +578,6 @@ Image_add_profile(VALUE self, VALUE name)
521
578
  profile_image = ReadImage(info, exception);
522
579
  (void) DestroyImageInfo(info);
523
580
  rm_check_exception(exception, profile_image, DestroyOnError);
524
- (void) DestroyExceptionInfo(exception);
525
581
  rm_ensure_result(profile_image);
526
582
 
527
583
  ResetImageProfileIterator(profile_image);
@@ -531,9 +587,8 @@ Image_add_profile(VALUE self, VALUE name)
531
587
  profile = GetImageProfile(profile_image, profile_name);
532
588
  if (profile)
533
589
  {
534
- (void)ProfileImage(image, profile_name, GetStringInfoDatum(profile)
535
- , GetStringInfoLength(profile), MagickFalse);
536
- if (image->exception.severity >= ErrorException)
590
+ (void) ProfileImage(image, profile_name, GetStringInfoDatum(profile), GetStringInfoLength(profile), MagickFalse);
591
+ if (rm_should_raise_exception(&image->exception, RetainExceptionRetention))
537
592
  {
538
593
  break;
539
594
  }
@@ -542,9 +597,9 @@ Image_add_profile(VALUE self, VALUE name)
542
597
  }
543
598
 
544
599
  (void) DestroyImage(profile_image);
600
+ (void) DestroyExceptionInfo(exception);
545
601
  rm_check_image_exception(image, RetainOnError);
546
602
 
547
-
548
603
  return self;
549
604
  }
550
605
 
@@ -573,7 +628,7 @@ VALUE
573
628
  Image_alpha(int argc, VALUE *argv, VALUE self)
574
629
  {
575
630
  Image *image;
576
- AlphaChannelType alpha;
631
+ AlphaChannelOption alpha;
577
632
 
578
633
 
579
634
  // For backward compatibility, make alpha() act like alpha?
@@ -588,7 +643,7 @@ Image_alpha(int argc, VALUE *argv, VALUE self)
588
643
 
589
644
 
590
645
  image = rm_check_frozen(self);
591
- VALUE_TO_ENUM(argv[0], alpha, AlphaChannelType);
646
+ VALUE_TO_ENUM(argv[0], alpha, AlphaChannelOption);
592
647
 
593
648
  (void) SetImageAlphaChannel(image, alpha);
594
649
  rm_check_image_exception(image, RetainOnError);
@@ -1041,14 +1096,14 @@ Image_background_color(VALUE self)
1041
1096
  *
1042
1097
  * @param self this object
1043
1098
  * @param color the color
1044
- * @return self
1099
+ * @return color
1045
1100
  */
1046
1101
  VALUE
1047
1102
  Image_background_color_eq(VALUE self, VALUE color)
1048
1103
  {
1049
1104
  Image *image = rm_check_frozen(self);
1050
1105
  Color_to_PixelColor(&image->background_color, color);
1051
- return self;
1106
+ return color;
1052
1107
  }
1053
1108
 
1054
1109
 
@@ -1120,7 +1175,9 @@ Image_base_rows(VALUE self)
1120
1175
  VALUE
1121
1176
  Image_bias(VALUE self)
1122
1177
  {
1123
- Image *image = rm_check_destroyed(self);
1178
+ Image *image;
1179
+
1180
+ image = rm_check_destroyed(self);
1124
1181
  return rb_float_new(image->bias);
1125
1182
  }
1126
1183
 
@@ -1133,7 +1190,7 @@ Image_bias(VALUE self)
1133
1190
  *
1134
1191
  * @param self this object
1135
1192
  * @param pct the bias
1136
- * @return self
1193
+ * @return pct
1137
1194
  */
1138
1195
  VALUE
1139
1196
  Image_bias_eq(VALUE self, VALUE pct)
@@ -1142,10 +1199,10 @@ Image_bias_eq(VALUE self, VALUE pct)
1142
1199
  double bias;
1143
1200
 
1144
1201
  image = rm_check_frozen(self);
1145
- bias = rm_percentage(pct,1.0);
1146
- image->bias = bias * QuantumRange;
1202
+ bias = rm_percentage(pct, 1.0) * QuantumRange;
1203
+ image->bias = bias;
1147
1204
 
1148
- return self;
1205
+ return pct;
1149
1206
  }
1150
1207
 
1151
1208
  /**
@@ -1234,7 +1291,7 @@ Image_black_point_compensation(VALUE self)
1234
1291
  *
1235
1292
  * @param self this object
1236
1293
  * @param arg the compensation
1237
- * @return self
1294
+ * @return arg
1238
1295
  */
1239
1296
  VALUE
1240
1297
  Image_black_point_compensation_eq(VALUE self, VALUE arg)
@@ -1247,7 +1304,7 @@ Image_black_point_compensation_eq(VALUE self, VALUE arg)
1247
1304
  value = RTEST(arg) ? "true" : "false";
1248
1305
  (void) rm_set_property(image, BlackPointCompensationKey, value);
1249
1306
 
1250
- return self;
1307
+ return arg;
1251
1308
  }
1252
1309
 
1253
1310
 
@@ -1255,10 +1312,10 @@ Image_black_point_compensation_eq(VALUE self, VALUE arg)
1255
1312
  * Call BlackThresholdImage.
1256
1313
  *
1257
1314
  * Ruby usage:
1258
- * - @verbatim Image#black_threshold(red_channel) @endverbatim
1259
- * - @verbatim Image#black_threshold(red_channel, green_channel) @endverbatim
1260
- * - @verbatim Image#black_threshold(red_channel, green_channel, blue_channel) @endverbatim
1261
- * - @verbatim Image#black_threshold(red_channel, green_channel, blue_channel, opacity_channel) @endverbatim
1315
+ * - @verbatim Image#black_threshold(red) @endverbatim
1316
+ * - @verbatim Image#black_threshold(red, green) @endverbatim
1317
+ * - @verbatim Image#black_threshold(red, green, blue) @endverbatim
1318
+ * - @verbatim Image#black_threshold(red, green, blue, alpha: alpha) @endverbatim
1262
1319
  *
1263
1320
  * @param argc number of input arguments
1264
1321
  * @param argv array of input arguments
@@ -1410,10 +1467,7 @@ get_offsets_from_gravity(GravityType gravity, Image *image, Image *mark
1410
1467
  static VALUE
1411
1468
  check_for_long_value(VALUE obj)
1412
1469
  {
1413
- long t;
1414
- t = NUM2LONG(obj);
1415
- t = t; // placate gcc
1416
- return(VALUE)0;
1470
+ return LONG2NUM(NUM2LONG(obj));
1417
1471
  }
1418
1472
 
1419
1473
 
@@ -1702,8 +1756,51 @@ Image_blue_shift(int argc, VALUE *argv, VALUE self)
1702
1756
  }
1703
1757
 
1704
1758
 
1759
+ /**
1760
+ * Get the blur attribute.
1761
+ *
1762
+ * Ruby usage:
1763
+ * - @verbatim Image#blur @endverbatim
1764
+ *
1765
+ * @param self this object
1766
+ * @return the blur
1767
+ * @deprecated This method has been deprecated.
1768
+ */
1769
+ VALUE
1770
+ Image_blur(VALUE self)
1771
+ {
1772
+ Image *image;
1773
+
1774
+ rb_warning("Image#blur is deprecated");
1775
+ (void) rm_check_destroyed(self);
1776
+ Data_Get_Struct(self, Image, image);
1777
+ return C_dbl_to_R_dbl(image->blur);
1778
+ }
1779
+
1780
+
1781
+ /**
1782
+ * Set the blur attribute.
1783
+ *
1784
+ * Ruby usage:
1785
+ * - @verbatim Image#blur= @endverbatim
1786
+ *
1787
+ * @param self this object
1788
+ * @param value the blur
1789
+ * @return value
1790
+ * @deprecated This method has been deprecated.
1791
+ */
1792
+ VALUE
1793
+ Image_blur_eq(VALUE self, VALUE value)
1794
+ {
1795
+ Image *image;
1705
1796
 
1706
- DEF_ATTR_ACCESSOR(Image, blur, dbl)
1797
+ rb_warning("Image#blur= is deprecated");
1798
+ (void) rm_check_destroyed(self);
1799
+ rb_check_frozen(self);
1800
+ Data_Get_Struct(self, Image, image);
1801
+ image->blur = R_dbl_to_C_dbl(value);
1802
+ return value;
1803
+ }
1707
1804
 
1708
1805
 
1709
1806
  /**
@@ -1911,14 +2008,14 @@ Image_border_color(VALUE self)
1911
2008
  *
1912
2009
  * @param self this object
1913
2010
  * @param color the color
1914
- * @return self
2011
+ * @return color
1915
2012
  */
1916
2013
  VALUE
1917
2014
  Image_border_color_eq(VALUE self, VALUE color)
1918
2015
  {
1919
2016
  Image *image = rm_check_frozen(self);
1920
2017
  Color_to_PixelColor(&image->border_color, color);
1921
- return self;
2018
+ return color;
1922
2019
  }
1923
2020
 
1924
2021
 
@@ -1973,15 +2070,13 @@ Image_bounding_box(VALUE self)
1973
2070
  * @return a new image
1974
2071
  */
1975
2072
  VALUE
1976
- Image_capture(int argc, VALUE *argv, VALUE self)
2073
+ Image_capture(int argc, VALUE *argv, VALUE self ATTRIBUTE_UNUSED)
1977
2074
  {
1978
- Image *image;
2075
+ Image *new_image;
1979
2076
  ImageInfo *image_info;
1980
2077
  VALUE info_obj;
1981
2078
  XImportInfo ximage_info;
1982
2079
 
1983
- self = self; // Suppress "never referenced" message from icc
1984
-
1985
2080
  XGetImportInfo(&ximage_info);
1986
2081
  switch (argc)
1987
2082
  {
@@ -2011,15 +2106,15 @@ Image_capture(int argc, VALUE *argv, VALUE self)
2011
2106
  Data_Get_Struct(info_obj, Info, image_info);
2012
2107
 
2013
2108
  // If an error occurs, IM will call our error handler and we raise an exception.
2014
- image = XImportImage(image_info, &ximage_info);
2015
- rm_check_image_exception(image, DestroyOnError);
2016
- rm_ensure_result(image);
2109
+ new_image = XImportImage(image_info, &ximage_info);
2110
+ rm_check_image_exception(new_image, DestroyOnError);
2111
+ rm_ensure_result(new_image);
2017
2112
 
2018
- rm_set_user_artifact(image, image_info);
2113
+ rm_set_user_artifact(new_image, image_info);
2019
2114
 
2020
2115
  RB_GC_GUARD(info_obj);
2021
2116
 
2022
- return rm_image_new(image);
2117
+ return rm_image_new(new_image);
2023
2118
  }
2024
2119
 
2025
2120
 
@@ -2050,7 +2145,6 @@ Image_change_geometry(VALUE self, VALUE geom_arg)
2050
2145
  memset(&rect, 0, sizeof(rect));
2051
2146
 
2052
2147
  SetGeometry(image, &rect);
2053
- rm_check_image_exception(image, RetainOnError);
2054
2148
  flags = ParseMetaGeometry(geometry, &rect.x,&rect.y, &rect.width,&rect.height);
2055
2149
  if (flags == NoValue)
2056
2150
  {
@@ -2084,7 +2178,6 @@ Image_changed_q(VALUE self)
2084
2178
  {
2085
2179
  Image *image = rm_check_destroyed(self);
2086
2180
  VALUE okay = IsTaintImage(image) ? Qtrue : Qfalse;
2087
- rm_check_image_exception(image, RetainOnError);
2088
2181
  return okay;
2089
2182
  }
2090
2183
 
@@ -2417,14 +2510,14 @@ Image_chromaticity(VALUE self)
2417
2510
  *
2418
2511
  * @param self this object
2419
2512
  * @param chroma the chromaticity
2420
- * @return self
2513
+ * @return chroma
2421
2514
  */
2422
2515
  VALUE
2423
2516
  Image_chromaticity_eq(VALUE self, VALUE chroma)
2424
2517
  {
2425
2518
  Image *image = rm_check_frozen(self);
2426
2519
  Export_ChromaticityInfo(&image->chromaticity, chroma);
2427
- return self;
2520
+ return chroma;
2428
2521
  }
2429
2522
 
2430
2523
 
@@ -2629,7 +2722,6 @@ set_profile(VALUE self, const char *name, VALUE profile)
2629
2722
  profile_image = BlobToImage(info, profile_blob, (size_t)profile_length, exception);
2630
2723
  (void) DestroyImageInfo(info);
2631
2724
  CHECK_EXCEPTION()
2632
- (void) DestroyExceptionInfo(exception);
2633
2725
 
2634
2726
  ResetImageProfileIterator(profile_image);
2635
2727
  profile_name = GetNextImageProfile(profile_image);
@@ -2639,7 +2731,7 @@ set_profile(VALUE self, const char *name, VALUE profile)
2639
2731
  if (rm_strcasecmp("8bim", profile_name) == 0 && rm_strcasecmp("iptc", name) == 0)
2640
2732
  {
2641
2733
  (void) ProfileImage(image, name, profile_blob, profile_length, MagickFalse);
2642
- if (image->exception.severity >= ErrorException)
2734
+ if (rm_should_raise_exception(&image->exception, RetainExceptionRetention))
2643
2735
  {
2644
2736
  break;
2645
2737
  }
@@ -2650,7 +2742,7 @@ set_profile(VALUE self, const char *name, VALUE profile)
2650
2742
  if (profile_data)
2651
2743
  {
2652
2744
  (void) ProfileImage(image, name, GetStringInfoDatum(profile_data), GetStringInfoLength(profile_data), MagickFalse);
2653
- if (image->exception.severity >= ErrorException)
2745
+ if (rm_should_raise_exception(&image->exception, RetainExceptionRetention))
2654
2746
  {
2655
2747
  break;
2656
2748
  }
@@ -2660,6 +2752,7 @@ set_profile(VALUE self, const char *name, VALUE profile)
2660
2752
  }
2661
2753
 
2662
2754
  (void) DestroyImage(profile_image);
2755
+ (void) DestroyExceptionInfo(exception);
2663
2756
  rm_check_image_exception(image, RetainOnError);
2664
2757
 
2665
2758
  return self;
@@ -2710,7 +2803,7 @@ Image_color_profile(VALUE self)
2710
2803
  *
2711
2804
  * @param self this object
2712
2805
  * @param profile the profile to set, as a Ruby string
2713
- * @return self
2806
+ * @return profile
2714
2807
  */
2715
2808
  VALUE
2716
2809
  Image_color_profile_eq(VALUE self, VALUE profile)
@@ -2720,7 +2813,7 @@ Image_color_profile_eq(VALUE self, VALUE profile)
2720
2813
  {
2721
2814
  (void) set_profile(self, "ICC", profile);
2722
2815
  }
2723
- return self;
2816
+ return profile;
2724
2817
  }
2725
2818
 
2726
2819
 
@@ -2806,9 +2899,9 @@ Image_color_flood_fill( VALUE self, VALUE target_color, VALUE fill_color
2806
2899
 
2807
2900
  (void) FloodfillPaintImage(new_image, DefaultChannels, draw_info, &target_mpp, x, y, invert);
2808
2901
 
2809
- // No need to check for error
2810
-
2811
2902
  (void) DestroyDrawInfo(draw_info);
2903
+ rm_check_image_exception(new_image, DestroyOnError);
2904
+
2812
2905
  return rm_image_new(new_image);
2813
2906
  }
2814
2907
 
@@ -2993,7 +3086,7 @@ Image_colorspace(VALUE self)
2993
3086
  Image *image;
2994
3087
 
2995
3088
  image = rm_check_destroyed(self);
2996
- return ColorspaceType_new(image->colorspace);
3089
+ return ColorspaceType_find(image->colorspace);
2997
3090
  }
2998
3091
 
2999
3092
 
@@ -3005,7 +3098,7 @@ Image_colorspace(VALUE self)
3005
3098
  *
3006
3099
  * @param self this object
3007
3100
  * @param colorspace the colorspace
3008
- * @return self
3101
+ * @return colorspace
3009
3102
  * @see Magick::colorSpace in Magick++'s Magick::colorSpace
3010
3103
  */
3011
3104
  VALUE
@@ -3018,7 +3111,7 @@ Image_colorspace_eq(VALUE self, VALUE colorspace)
3018
3111
  VALUE_TO_ENUM(colorspace, new_cs, ColorspaceType);
3019
3112
  (void) TransformImageColorspace(image, new_cs);
3020
3113
 
3021
- return self;
3114
+ return colorspace;
3022
3115
  }
3023
3116
 
3024
3117
 
@@ -3052,14 +3145,15 @@ DEF_ATTR_READER(Image, columns, int)
3052
3145
  * @param argv array of input arguments
3053
3146
  * @param self this object
3054
3147
  * @return a new image
3148
+ * @deprecated This method has been deprecated. Please use ImageList_combine.
3055
3149
  */
3056
- VALUE Image_combine(int argc, VALUE *argv, VALUE self)
3150
+ VALUE Image_combine(int argc, VALUE *argv, VALUE self ATTRIBUTE_UNUSED)
3057
3151
  {
3058
3152
  ChannelType channel = 0;
3059
3153
  Image *image, *images = NULL, *new_image;
3060
3154
  ExceptionInfo *exception;
3061
3155
 
3062
- self = self; // defeat "unreferenced argument" message
3156
+ rb_warning("Image#combine is deprecated; use ImageList#combine.");
3063
3157
 
3064
3158
  switch (argc)
3065
3159
  {
@@ -3172,12 +3266,7 @@ Image_compare_channel(int argc, VALUE *argv, VALUE self)
3172
3266
  VALUE_TO_ENUM(argv[1], metric_type, MetricType);
3173
3267
 
3174
3268
  exception = AcquireExceptionInfo();
3175
- difference_image = CompareImageChannels(image
3176
- , r_image
3177
- , channels
3178
- , metric_type
3179
- , &distortion
3180
- , exception);
3269
+ difference_image = CompareImageChannels(image, r_image, channels, metric_type, &distortion, exception);
3181
3270
  rm_check_exception(exception, difference_image, DestroyOnError);
3182
3271
 
3183
3272
  (void) DestroyExceptionInfo(exception);
@@ -3208,7 +3297,7 @@ VALUE
3208
3297
  Image_compose(VALUE self)
3209
3298
  {
3210
3299
  Image *image = rm_check_destroyed(self);
3211
- return CompositeOperator_new(image->compose);
3300
+ return CompositeOperator_find(image->compose);
3212
3301
  }
3213
3302
 
3214
3303
 
@@ -3220,14 +3309,14 @@ Image_compose(VALUE self)
3220
3309
  *
3221
3310
  * @param self this object
3222
3311
  * @param compose_arg the composite operator
3223
- * @return self
3312
+ * @return compose_arg
3224
3313
  */
3225
3314
  VALUE
3226
3315
  Image_compose_eq(VALUE self, VALUE compose_arg)
3227
3316
  {
3228
3317
  Image *image = rm_check_frozen(self);
3229
3318
  VALUE_TO_ENUM(compose_arg, image->compose, CompositeOperator);
3230
- return self;
3319
+ return compose_arg;
3231
3320
  }
3232
3321
 
3233
3322
  /**
@@ -3616,10 +3705,10 @@ Image_composite_mathematics(int argc, VALUE *argv, VALUE self)
3616
3705
 
3617
3706
  // Call composite(False, gravity, x_off, y_off, MathematicsCompositeOp, DefaultChannels)
3618
3707
  args[0] = argv[0];
3619
- args[1] = GravityType_new(gravity);
3708
+ args[1] = GravityType_find(gravity);
3620
3709
  args[2] = LONG2FIX(x_off);
3621
3710
  args[3] = LONG2FIX(y_off);
3622
- args[4] = CompositeOperator_new(MathematicsCompositeOp);
3711
+ args[4] = CompositeOperator_find(MathematicsCompositeOp);
3623
3712
 
3624
3713
  return composite(False, 5, args, self, DefaultChannels);
3625
3714
  }
@@ -3768,7 +3857,7 @@ VALUE
3768
3857
  Image_compression(VALUE self)
3769
3858
  {
3770
3859
  Image *image = rm_check_destroyed(self);
3771
- return CompressionType_new(image->compression);
3860
+ return CompressionType_find(image->compression);
3772
3861
  }
3773
3862
 
3774
3863
  /**
@@ -3779,14 +3868,14 @@ Image_compression(VALUE self)
3779
3868
  *
3780
3869
  * @param self this object
3781
3870
  * @param compression the compression
3782
- * @return self
3871
+ * @return compression
3783
3872
  */
3784
3873
  VALUE
3785
3874
  Image_compression_eq(VALUE self, VALUE compression)
3786
3875
  {
3787
3876
  Image *image = rm_check_frozen(self);
3788
3877
  VALUE_TO_ENUM(compression, image->compression, CompressionType);
3789
- return self;
3878
+ return compression;
3790
3879
  }
3791
3880
 
3792
3881
  /**
@@ -3804,9 +3893,10 @@ Image_compression_eq(VALUE self, VALUE compression)
3804
3893
  VALUE
3805
3894
  Image_compress_colormap_bang(VALUE self)
3806
3895
  {
3896
+ Image *image;
3807
3897
  MagickBooleanType okay;
3808
3898
 
3809
- Image *image = rm_check_frozen(self);
3899
+ image = rm_check_frozen(self);
3810
3900
  okay = CompressImageColormap(image);
3811
3901
  rm_check_image_exception(image, RetainOnError);
3812
3902
  if (!okay)
@@ -3842,10 +3932,10 @@ Image_compress_colormap_bang(VALUE self)
3842
3932
  * @throw TypeError
3843
3933
  */
3844
3934
  VALUE
3845
- Image_constitute(VALUE class, VALUE width_arg, VALUE height_arg
3935
+ Image_constitute(VALUE class ATTRIBUTE_UNUSED, VALUE width_arg, VALUE height_arg
3846
3936
  , VALUE map_arg, VALUE pixels_arg)
3847
3937
  {
3848
- Image *image;
3938
+ Image *new_image;
3849
3939
  VALUE pixel, pixel0;
3850
3940
  unsigned long width, height;
3851
3941
  long x, npixels;
@@ -3859,12 +3949,11 @@ Image_constitute(VALUE class, VALUE width_arg, VALUE height_arg
3859
3949
  } pixels;
3860
3950
  VALUE pixel_class;
3861
3951
  StorageType stg_type;
3952
+ ExceptionInfo *exception;
3862
3953
 
3863
- class = class; // Suppress "never referenced" message from icc
3864
-
3865
- // rb_Array converts objects that are not Arrays to Arrays if possible,
3866
- // and raises TypeError if it can't.
3867
- pixels_arg = rb_Array(pixels_arg);
3954
+ // rb_Array converts objects that are not Arrays to Arrays if possible,
3955
+ // and raises TypeError if it can't.
3956
+ pixels_arg = rb_Array(pixels_arg);
3868
3957
 
3869
3958
  width = NUM2ULONG(width_arg);
3870
3959
  height = NUM2ULONG(height_arg);
@@ -3933,28 +4022,40 @@ Image_constitute(VALUE class, VALUE width_arg, VALUE height_arg
3933
4022
  }
3934
4023
 
3935
4024
  // This is based on ConstituteImage in IM 5.5.7
3936
- image = rm_acquire_image((ImageInfo *) NULL);
3937
- if (!image)
4025
+ new_image = rm_acquire_image((ImageInfo *) NULL);
4026
+ if (!new_image)
3938
4027
  {
3939
4028
  xfree(pixels.v);
3940
4029
  rb_raise(rb_eNoMemError, "not enough memory to continue.");
3941
4030
  }
3942
4031
 
3943
- SetImageExtent(image, width, height);
3944
- rm_check_image_exception(image, DestroyOnError);
4032
+ SetImageExtent(new_image, width, height);
4033
+ exception = &new_image->exception;
4034
+ if (rm_should_raise_exception(exception, RetainExceptionRetention))
4035
+ {
4036
+ xfree(pixels.v);
4037
+ (void) DestroyImage(new_image);
4038
+ rm_raise_exception(exception);
4039
+ }
3945
4040
 
3946
- (void) SetImageBackgroundColor(image);
3947
- rm_check_image_exception(image, DestroyOnError);
4041
+ (void) SetImageBackgroundColor(new_image);
4042
+ exception = &new_image->exception;
4043
+ if (rm_should_raise_exception(exception, RetainExceptionRetention))
4044
+ {
4045
+ xfree(pixels.v);
4046
+ (void) DestroyImage(new_image);
4047
+ rm_raise_exception(exception);
4048
+ }
3948
4049
 
3949
- (void) ImportImagePixels(image, 0, 0, width, height, map, stg_type, (const void *)pixels.v);
4050
+ (void) ImportImagePixels(new_image, 0, 0, width, height, map, stg_type, (const void *)pixels.v);
3950
4051
  xfree(pixels.v);
3951
- rm_check_image_exception(image, DestroyOnError);
4052
+ rm_check_image_exception(new_image, DestroyOnError);
3952
4053
 
3953
4054
  RB_GC_GUARD(pixel);
3954
4055
  RB_GC_GUARD(pixel0);
3955
4056
  RB_GC_GUARD(pixel_class);
3956
4057
 
3957
- return rm_image_new(image);
4058
+ return rm_image_new(new_image);
3958
4059
  }
3959
4060
 
3960
4061
  /**
@@ -4124,12 +4225,14 @@ Image_contrast_stretch_channel(int argc, VALUE *argv, VALUE self)
4124
4225
  VALUE
4125
4226
  Image_morphology(VALUE self, VALUE method_v, VALUE iterations, VALUE kernel_v)
4126
4227
  {
4127
- static VALUE default_channels_const = 0;
4228
+ static VALUE default_channels_const = 0;
4128
4229
 
4129
- if(!default_channels_const)
4130
- default_channels_const = rb_const_get(Module_Magick, rb_intern("DefaultChannels"));
4230
+ if(!default_channels_const)
4231
+ {
4232
+ default_channels_const = rb_const_get(Module_Magick, rb_intern("DefaultChannels"));
4233
+ }
4131
4234
 
4132
- return Image_morphology_channel(self, default_channels_const, method_v, iterations, kernel_v);
4235
+ return Image_morphology_channel(self, default_channels_const, method_v, iterations, kernel_v);
4133
4236
  }
4134
4237
 
4135
4238
  /** Apply a user supplied kernel to the image channel according to the given mophology method.
@@ -4150,33 +4253,38 @@ Image_morphology(VALUE self, VALUE method_v, VALUE iterations, VALUE kernel_v)
4150
4253
  VALUE
4151
4254
  Image_morphology_channel(VALUE self, VALUE channel_v, VALUE method_v, VALUE iterations, VALUE kernel_v)
4152
4255
  {
4153
- Image *image, *new_image;
4154
- ExceptionInfo *exception;
4155
- MorphologyMethod method;
4156
- ChannelType channel;
4157
- KernelInfo *kernel;
4256
+ Image *image, *new_image;
4257
+ ExceptionInfo *exception;
4258
+ MorphologyMethod method;
4259
+ ChannelType channel;
4260
+ KernelInfo *kernel;
4158
4261
 
4159
- VALUE_TO_ENUM(method_v, method, MorphologyMethod);
4160
- VALUE_TO_ENUM(channel_v, channel, ChannelType);
4161
- Check_Type(iterations, T_FIXNUM);
4262
+ image = rm_check_destroyed(self);
4162
4263
 
4163
- if (TYPE(kernel_v) == T_STRING)
4164
- kernel_v = rb_class_new_instance(1, &kernel_v, Class_KernelInfo);
4264
+ VALUE_TO_ENUM(method_v, method, MorphologyMethod);
4265
+ VALUE_TO_ENUM(channel_v, channel, ChannelType);
4266
+ Check_Type(iterations, T_FIXNUM);
4165
4267
 
4166
- if (!rb_obj_is_kind_of(kernel_v, Class_KernelInfo))
4167
- rb_raise(rb_eArgError, "expected String or Magick::KernelInfo");
4268
+ if (TYPE(kernel_v) == T_STRING)
4269
+ {
4270
+ kernel_v = rb_class_new_instance(1, &kernel_v, Class_KernelInfo);
4271
+ }
4168
4272
 
4169
- Data_Get_Struct(kernel_v, KernelInfo, kernel);
4273
+ if (!rb_obj_is_kind_of(kernel_v, Class_KernelInfo))
4274
+ {
4275
+ rb_raise(rb_eArgError, "expected String or Magick::KernelInfo");
4276
+ }
4170
4277
 
4171
- image = rm_check_destroyed(self);
4172
- exception = AcquireExceptionInfo();
4278
+ Data_Get_Struct(kernel_v, KernelInfo, kernel);
4173
4279
 
4174
- new_image = MorphologyImageChannel(image, channel, method, NUM2LONG(iterations), kernel, exception);
4175
- rm_check_exception(exception, new_image, DestroyOnError);
4176
- DestroyExceptionInfo(exception);
4280
+ exception = AcquireExceptionInfo();
4177
4281
 
4178
- rm_ensure_result(new_image);
4179
- return rm_image_new(new_image);
4282
+ new_image = MorphologyImageChannel(image, channel, method, NUM2LONG(iterations), kernel, exception);
4283
+ rm_check_exception(exception, new_image, DestroyOnError);
4284
+ (void) DestroyExceptionInfo(exception);
4285
+
4286
+ rm_ensure_result(new_image);
4287
+ return rm_image_new(new_image);
4180
4288
  }
4181
4289
 
4182
4290
  /**
@@ -4194,13 +4302,19 @@ VALUE
4194
4302
  Image_convolve(VALUE self, VALUE order_arg, VALUE kernel_arg)
4195
4303
  {
4196
4304
  Image *image, *new_image;
4197
- double *kernel;
4198
- unsigned int x, order;
4305
+ int order;
4199
4306
  ExceptionInfo *exception;
4307
+ double *kernel;
4308
+ unsigned int x;
4200
4309
 
4201
4310
  image = rm_check_destroyed(self);
4202
4311
 
4203
- order = NUM2UINT(order_arg);
4312
+ order = NUM2INT(order_arg);
4313
+
4314
+ if (order <= 0)
4315
+ {
4316
+ rb_raise(rb_eArgError, "order must be non-zero and positive");
4317
+ }
4204
4318
 
4205
4319
  kernel_arg = rb_Array(kernel_arg);
4206
4320
  rm_check_ary_len(kernel_arg, (long)(order*order));
@@ -4224,7 +4338,7 @@ Image_convolve(VALUE self, VALUE order_arg, VALUE kernel_arg)
4224
4338
 
4225
4339
  exception = AcquireExceptionInfo();
4226
4340
 
4227
- new_image = ConvolveImage((const Image *)image, order, (double *)kernel, exception);
4341
+ new_image = ConvolveImage(image, order, kernel, exception);
4228
4342
  xfree((void *)kernel);
4229
4343
  rm_check_exception(exception, new_image, DestroyOnError);
4230
4344
 
@@ -4253,11 +4367,12 @@ VALUE
4253
4367
  Image_convolve_channel(int argc, VALUE *argv, VALUE self)
4254
4368
  {
4255
4369
  Image *image, *new_image;
4256
- double *kernel;
4257
4370
  VALUE ary;
4258
- unsigned int x, order;
4371
+ int order;
4259
4372
  ChannelType channels;
4260
4373
  ExceptionInfo *exception;
4374
+ double *kernel;
4375
+ unsigned int x;
4261
4376
 
4262
4377
  image = rm_check_destroyed(self);
4263
4378
 
@@ -4273,7 +4388,12 @@ Image_convolve_channel(int argc, VALUE *argv, VALUE self)
4273
4388
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or more)", argc);
4274
4389
  }
4275
4390
 
4276
- order = NUM2UINT(argv[0]);
4391
+ order = NUM2INT(argv[0]);
4392
+ if (order <= 0)
4393
+ {
4394
+ rb_raise(rb_eArgError, "order must be non-zero and positive");
4395
+ }
4396
+
4277
4397
  ary = argv[1];
4278
4398
 
4279
4399
  rm_check_ary_len(ary, (long)(order*order));
@@ -4420,7 +4540,7 @@ Image_cycle_colormap(VALUE self, VALUE amount)
4420
4540
  new_image = rm_clone_image(image);
4421
4541
 
4422
4542
  (void) CycleColormapImage(new_image, amt);
4423
- // No need to check for an error
4543
+ rm_check_image_exception(new_image, DestroyOnError);
4424
4544
 
4425
4545
  return rm_image_new(new_image);
4426
4546
  }
@@ -4465,7 +4585,7 @@ Image_density(VALUE self)
4465
4585
  *
4466
4586
  * @param self this object
4467
4587
  * @param density_arg The density String or Geometry
4468
- * @return self
4588
+ * @return density_arg
4469
4589
  */
4470
4590
  VALUE
4471
4591
  Image_density_eq(VALUE self, VALUE density_arg)
@@ -4519,7 +4639,7 @@ Image_density_eq(VALUE self, VALUE density_arg)
4519
4639
  RB_GC_GUARD(x_val);
4520
4640
  RB_GC_GUARD(y_val);
4521
4641
 
4522
- return self;
4642
+ return density_arg;
4523
4643
  }
4524
4644
 
4525
4645
 
@@ -4551,11 +4671,11 @@ Image_decipher(VALUE self, VALUE passphrase)
4551
4671
  rm_check_exception(exception, new_image, DestroyOnError);
4552
4672
  if (!okay)
4553
4673
  {
4554
- new_image = DestroyImage(new_image);
4674
+ (void) DestroyImage(new_image);
4555
4675
  rb_raise(rb_eRuntimeError, "DecipherImage failed for unknown reason.");
4556
4676
  }
4557
4677
 
4558
- DestroyExceptionInfo(exception);
4678
+ (void) DestroyExceptionInfo(exception);
4559
4679
 
4560
4680
  return rm_image_new(new_image);
4561
4681
  }
@@ -4625,7 +4745,9 @@ DEF_ATTR_ACCESSOR(Image, delay, ulong)
4625
4745
  VALUE
4626
4746
  Image_delete_compose_mask(VALUE self)
4627
4747
  {
4628
- Image *image = rm_check_frozen(self);
4748
+ Image *image;
4749
+
4750
+ image = rm_check_frozen(self);
4629
4751
 
4630
4752
  // Store a clone of the mask image
4631
4753
  (void) SetImageMask(image, NULL);
@@ -4650,7 +4772,6 @@ Image_delete_profile(VALUE self, VALUE name)
4650
4772
  {
4651
4773
  Image *image = rm_check_frozen(self);
4652
4774
  (void) DeleteImageProfile(image, StringValuePtr(name));
4653
- rm_check_image_exception(image, RetainOnError);
4654
4775
 
4655
4776
  return self;
4656
4777
  }
@@ -4841,7 +4962,7 @@ Image_difference(VALUE self, VALUE other)
4841
4962
  image2 = rm_check_destroyed(other);
4842
4963
 
4843
4964
  (void) IsImagesEqual(image, image2);
4844
- // No need to check for error
4965
+ rm_check_image_exception(image, RetainOnError);
4845
4966
 
4846
4967
  mean = rb_float_new(image->error.mean_error_per_pixel);
4847
4968
  nmean = rb_float_new(image->error.normalized_mean_error);
@@ -5085,7 +5206,7 @@ VALUE
5085
5206
  Image_dispose(VALUE self)
5086
5207
  {
5087
5208
  Image *image = rm_check_destroyed(self);
5088
- return DisposeType_new(image->dispose);
5209
+ return DisposeType_find(image->dispose);
5089
5210
  }
5090
5211
 
5091
5212
 
@@ -5097,14 +5218,14 @@ Image_dispose(VALUE self)
5097
5218
  *
5098
5219
  * @param self this object
5099
5220
  * @param dispose the dispose
5100
- * @return self
5221
+ * @return dispose
5101
5222
  */
5102
5223
  VALUE
5103
5224
  Image_dispose_eq(VALUE self, VALUE dispose)
5104
5225
  {
5105
5226
  Image *image = rm_check_frozen(self);
5106
5227
  VALUE_TO_ENUM(dispose, image->dispose, DisposeType);
5107
- return self;
5228
+ return dispose;
5108
5229
  }
5109
5230
 
5110
5231
 
@@ -5206,7 +5327,7 @@ Image_distort(int argc, VALUE *argv, VALUE self)
5206
5327
  Image *image, *new_image;
5207
5328
  VALUE pts;
5208
5329
  unsigned long n, npoints;
5209
- DistortImageMethod distortion_method;
5330
+ DistortMethod distortion_method;
5210
5331
  double *points;
5211
5332
  MagickBooleanType bestfit = MagickFalse;
5212
5333
  ExceptionInfo *exception;
@@ -5221,7 +5342,7 @@ Image_distort(int argc, VALUE *argv, VALUE self)
5221
5342
  case 2:
5222
5343
  // Ensure pts is an array
5223
5344
  pts = rb_Array(argv[1]);
5224
- VALUE_TO_ENUM(argv[0], distortion_method, DistortImageMethod);
5345
+ VALUE_TO_ENUM(argv[0], distortion_method, DistortMethod);
5225
5346
  break;
5226
5347
  default:
5227
5348
  rb_raise(rb_eArgError, "wrong number of arguments (expected 2 or 3, got %d)", argc);
@@ -5299,8 +5420,7 @@ Image_distortion_channel(int argc, VALUE *argv, VALUE self)
5299
5420
  reconstruct = rm_check_destroyed(rec);
5300
5421
  VALUE_TO_ENUM(argv[1], metric, MetricType);
5301
5422
  exception = AcquireExceptionInfo();
5302
- (void) GetImageChannelDistortion(image, reconstruct, channels
5303
- , metric, &distortion, exception);
5423
+ (void) GetImageChannelDistortion(image, reconstruct, channels, metric, &distortion, exception);
5304
5424
  CHECK_EXCEPTION()
5305
5425
 
5306
5426
  (void) DestroyExceptionInfo(exception);
@@ -5326,7 +5446,7 @@ Image_distortion_channel(int argc, VALUE *argv, VALUE self)
5326
5446
  * @return a string representing the dumped image
5327
5447
  */
5328
5448
  VALUE
5329
- Image__dump(VALUE self, VALUE depth)
5449
+ Image__dump(VALUE self, VALUE depth ATTRIBUTE_UNUSED)
5330
5450
  {
5331
5451
  Image *image;
5332
5452
  ImageInfo *info;
@@ -5336,8 +5456,6 @@ Image__dump(VALUE self, VALUE depth)
5336
5456
  VALUE str;
5337
5457
  ExceptionInfo *exception;
5338
5458
 
5339
- depth = depth; // Suppress "never referenced" message from icc
5340
-
5341
5459
  image = rm_check_destroyed(self);
5342
5460
 
5343
5461
  info = CloneImageInfo(NULL);
@@ -5613,7 +5731,7 @@ Image_encipher(VALUE self, VALUE passphrase)
5613
5731
  rm_check_exception(exception, new_image, DestroyOnError);
5614
5732
  if (!okay)
5615
5733
  {
5616
- new_image = DestroyImage(new_image);
5734
+ (void) DestroyImage(new_image);
5617
5735
  rb_raise(rb_eRuntimeError, "EncipherImage failed for unknown reason.");
5618
5736
  }
5619
5737
 
@@ -5637,7 +5755,7 @@ VALUE
5637
5755
  Image_endian(VALUE self)
5638
5756
  {
5639
5757
  Image *image = rm_check_destroyed(self);
5640
- return EndianType_new(image->endian);
5758
+ return EndianType_find(image->endian);
5641
5759
  }
5642
5760
 
5643
5761
 
@@ -5649,14 +5767,14 @@ Image_endian(VALUE self)
5649
5767
  *
5650
5768
  * @param self this object
5651
5769
  * @param type the endian type
5652
- * @return self
5770
+ * @return type
5653
5771
  */
5654
5772
  VALUE
5655
5773
  Image_endian_eq(VALUE self, VALUE type)
5656
5774
  {
5657
5775
  Image *image = rm_check_frozen(self);
5658
5776
  VALUE_TO_ENUM(type, image->endian, EndianType);
5659
- return self;
5777
+ return type;
5660
5778
  }
5661
5779
 
5662
5780
  /**
@@ -5774,7 +5892,9 @@ Image_equalize_channel(int argc, VALUE *argv, VALUE self)
5774
5892
  VALUE
5775
5893
  Image_erase_bang(VALUE self)
5776
5894
  {
5777
- Image *image = rm_check_frozen(self);
5895
+ Image *image;
5896
+
5897
+ image = rm_check_frozen(self);
5778
5898
 
5779
5899
  (void) SetImageBackgroundColor(image);
5780
5900
  rm_check_image_exception(image, RetainOnError);
@@ -6215,14 +6335,14 @@ Image_extract_info(VALUE self)
6215
6335
  *
6216
6336
  * @param self this object
6217
6337
  * @param rect extract_info
6218
- * @return self
6338
+ * @return rect
6219
6339
  */
6220
6340
  VALUE
6221
6341
  Image_extract_info_eq(VALUE self, VALUE rect)
6222
6342
  {
6223
6343
  Image *image = rm_check_frozen(self);
6224
6344
  Export_RectangleInfo(&image->extract_info, rect);
6225
- return self;
6345
+ return rect;
6226
6346
  }
6227
6347
 
6228
6348
 
@@ -6267,7 +6387,7 @@ VALUE
6267
6387
  Image_filter(VALUE self)
6268
6388
  {
6269
6389
  Image *image = rm_check_destroyed(self);
6270
- return FilterTypes_new(image->filter);
6390
+ return FilterType_find(image->filter);
6271
6391
  }
6272
6392
 
6273
6393
 
@@ -6279,14 +6399,14 @@ Image_filter(VALUE self)
6279
6399
  *
6280
6400
  * @param self this object
6281
6401
  * @param filter the filter
6282
- * @return self
6402
+ * @return filter
6283
6403
  */
6284
6404
  VALUE
6285
6405
  Image_filter_eq(VALUE self, VALUE filter)
6286
6406
  {
6287
6407
  Image *image = rm_check_frozen(self);
6288
- VALUE_TO_ENUM(filter, image->filter, FilterTypes);
6289
- return self;
6408
+ VALUE_TO_ENUM(filter, image->filter, FilterType);
6409
+ return filter;
6290
6410
  }
6291
6411
 
6292
6412
 
@@ -6525,7 +6645,7 @@ Image_format(VALUE self)
6525
6645
  *
6526
6646
  * @param self this object
6527
6647
  * @param magick the encoding format
6528
- * @return self
6648
+ * @return magick
6529
6649
  */
6530
6650
  VALUE
6531
6651
  Image_format_eq(VALUE self, VALUE magick)
@@ -6552,7 +6672,7 @@ Image_format_eq(VALUE self, VALUE magick)
6552
6672
 
6553
6673
 
6554
6674
  strncpy(image->magick, m->name, MaxTextExtent-1);
6555
- return self;
6675
+ return magick;
6556
6676
  }
6557
6677
 
6558
6678
 
@@ -6654,7 +6774,7 @@ Image_frame(int argc, VALUE *argv, VALUE self)
6654
6774
  * @return an array of new images
6655
6775
  */
6656
6776
  VALUE
6657
- Image_from_blob(VALUE class, VALUE blob_arg)
6777
+ Image_from_blob(VALUE class ATTRIBUTE_UNUSED, VALUE blob_arg)
6658
6778
  {
6659
6779
  Image *images;
6660
6780
  Info *info;
@@ -6663,9 +6783,6 @@ Image_from_blob(VALUE class, VALUE blob_arg)
6663
6783
  void *blob;
6664
6784
  long length;
6665
6785
 
6666
- class = class; // defeat gcc message
6667
- blob_arg = blob_arg; // defeat gcc message
6668
-
6669
6786
  blob = (void *) rm_str2cstr(blob_arg, &length);
6670
6787
 
6671
6788
  // Get a new Info object - run the parm block if supplied
@@ -6709,7 +6826,6 @@ Image_function_channel(int argc, VALUE *argv, VALUE self)
6709
6826
  Image *image, *new_image;
6710
6827
  MagickFunction function;
6711
6828
  unsigned long n, nparms;
6712
- volatile double *parameters;
6713
6829
  double *parms;
6714
6830
  ChannelType channels;
6715
6831
  ExceptionInfo *exception;
@@ -6749,7 +6865,7 @@ Image_function_channel(int argc, VALUE *argv, VALUE self)
6749
6865
  }
6750
6866
 
6751
6867
  nparms = argc;
6752
- parameters = parms = ALLOC_N(double, nparms);
6868
+ parms = ALLOC_N(double, nparms);
6753
6869
 
6754
6870
  for (n = 0; n < nparms; n++)
6755
6871
  {
@@ -6798,7 +6914,7 @@ DEF_ATTR_READER(Image, fuzz, dbl)
6798
6914
  *
6799
6915
  * @param self this object
6800
6916
  * @param fuzz the fuzz
6801
- * @return self
6917
+ * @return fuzz
6802
6918
  * @see Info_fuzz_eq
6803
6919
  */
6804
6920
  VALUE
@@ -6806,7 +6922,7 @@ Image_fuzz_eq(VALUE self, VALUE fuzz)
6806
6922
  {
6807
6923
  Image *image = rm_check_frozen(self);
6808
6924
  image->fuzz = rm_fuzz_to_dbl(fuzz);
6809
- return self;
6925
+ return fuzz;
6810
6926
  }
6811
6927
 
6812
6928
 
@@ -6902,7 +7018,7 @@ Image_gamma_channel(int argc, VALUE *argv, VALUE self)
6902
7018
  gamma = NUM2DBL(argv[0]);
6903
7019
  new_image = rm_clone_image(image);
6904
7020
 
6905
- (void)GammaImageChannel(new_image, channels, gamma);
7021
+ (void) GammaImageChannel(new_image, channels, gamma);
6906
7022
  rm_check_image_exception(new_image, DestroyOnError);
6907
7023
 
6908
7024
  return rm_image_new(new_image);
@@ -6932,7 +7048,6 @@ Image_gamma_correct(int argc, VALUE *argv, VALUE self)
6932
7048
  {
6933
7049
  Image *image, *new_image;
6934
7050
  double red_gamma, green_gamma, blue_gamma;
6935
- char gamma_arg[50];
6936
7051
 
6937
7052
  image = rm_check_destroyed(self);
6938
7053
  switch (argc)
@@ -6957,11 +7072,19 @@ Image_gamma_correct(int argc, VALUE *argv, VALUE self)
6957
7072
  break;
6958
7073
  }
6959
7074
 
6960
- sprintf(gamma_arg, "%f,%f,%f", red_gamma, green_gamma, blue_gamma);
6961
-
6962
7075
  new_image = rm_clone_image(image);
6963
7076
 
6964
- (void) GammaImage(new_image, gamma_arg);
7077
+ if ((red_gamma == green_gamma) && (green_gamma == blue_gamma))
7078
+ {
7079
+ (void) GammaImageChannel(new_image, (ChannelType) (RedChannel | GreenChannel | BlueChannel), red_gamma);
7080
+ }
7081
+ else
7082
+ {
7083
+ (void) GammaImageChannel(new_image, RedChannel, red_gamma);
7084
+ (void) GammaImageChannel(new_image, GreenChannel, green_gamma);
7085
+ (void) GammaImageChannel(new_image, BlueChannel, blue_gamma);
7086
+ }
7087
+
6965
7088
  rm_check_image_exception(new_image, DestroyOnError);
6966
7089
 
6967
7090
  return rm_image_new(new_image);
@@ -7066,12 +7189,10 @@ DEF_ATTR_READER(Image, geometry, str)
7066
7189
  *
7067
7190
  * @param self this object
7068
7191
  * @param geometry the geometry
7069
- * @return self
7192
+ * @return geometry
7070
7193
  */
7071
7194
  VALUE
7072
- Image_geometry_eq(
7073
- VALUE self,
7074
- VALUE geometry)
7195
+ Image_geometry_eq(VALUE self, VALUE geometry)
7075
7196
  {
7076
7197
  Image *image;
7077
7198
  VALUE geom_str;
@@ -7097,7 +7218,7 @@ Image_geometry_eq(
7097
7218
 
7098
7219
  RB_GC_GUARD(geom_str);
7099
7220
 
7100
- return self;
7221
+ return geometry;
7101
7222
  }
7102
7223
 
7103
7224
 
@@ -7125,12 +7246,12 @@ VALUE
7125
7246
  Image_get_pixels(VALUE self, VALUE x_arg, VALUE y_arg, VALUE cols_arg, VALUE rows_arg)
7126
7247
  {
7127
7248
  Image *image;
7128
- const PixelPacket *pixels;
7129
7249
  ExceptionInfo *exception;
7130
7250
  long x, y;
7131
7251
  unsigned long columns, rows;
7132
7252
  long size, n;
7133
7253
  VALUE pixel_ary;
7254
+ const PixelPacket *pixels;
7134
7255
 
7135
7256
  image = rm_check_destroyed(self);
7136
7257
  x = NUM2LONG(x_arg);
@@ -7675,7 +7796,7 @@ VALUE
7675
7796
  Image_interlace(VALUE self)
7676
7797
  {
7677
7798
  Image *image = rm_check_destroyed(self);
7678
- return InterlaceType_new(image->interlace);
7799
+ return InterlaceType_find(image->interlace);
7679
7800
  }
7680
7801
 
7681
7802
 
@@ -7687,14 +7808,14 @@ Image_interlace(VALUE self)
7687
7808
  *
7688
7809
  * @param self this object
7689
7810
  * @param interlace the interlace
7690
- * @return self
7811
+ * @return interlace
7691
7812
  */
7692
7813
  VALUE
7693
7814
  Image_interlace_eq(VALUE self, VALUE interlace)
7694
7815
  {
7695
7816
  Image *image = rm_check_frozen(self);
7696
7817
  VALUE_TO_ENUM(interlace, image->interlace, InterlaceType);
7697
- return self;
7818
+ return interlace;
7698
7819
  }
7699
7820
 
7700
7821
 
@@ -7715,7 +7836,6 @@ Image_iptc_profile(VALUE self)
7715
7836
 
7716
7837
  image = rm_check_destroyed(self);
7717
7838
  profile = GetImageProfile(image, "iptc");
7718
- rm_check_image_exception(image, RetainOnError);
7719
7839
  if (!profile)
7720
7840
  {
7721
7841
  return Qnil;
@@ -7738,7 +7858,7 @@ Image_iptc_profile(VALUE self)
7738
7858
  *
7739
7859
  * @param self
7740
7860
  * @param profile the IPTC profile (as a string)
7741
- * @return self
7861
+ * @return profile
7742
7862
  */
7743
7863
  VALUE
7744
7864
  Image_iptc_profile_eq(VALUE self, VALUE profile)
@@ -7748,7 +7868,7 @@ Image_iptc_profile_eq(VALUE self, VALUE profile)
7748
7868
  {
7749
7869
  (void) set_profile(self, "iptc", profile);
7750
7870
  }
7751
- return self;
7871
+ return profile;
7752
7872
  }
7753
7873
 
7754
7874
 
@@ -7907,7 +8027,6 @@ Image_level_colors(int argc, VALUE *argv, VALUE self)
7907
8027
  Image *image, *new_image;
7908
8028
  MagickPixel black_color, white_color;
7909
8029
  ChannelType channels;
7910
- ExceptionInfo *exception;
7911
8030
  MagickBooleanType invert = MagickTrue;
7912
8031
  MagickBooleanType status;
7913
8032
 
@@ -8012,8 +8131,8 @@ Image_levelize_channel(int argc, VALUE *argv, VALUE self)
8012
8131
 
8013
8132
  new_image = rm_clone_image(image);
8014
8133
  status = LevelizeImageChannel(new_image, channels, black_point, white_point, gamma);
8015
-
8016
8134
  rm_check_image_exception(new_image, DestroyOnError);
8135
+
8017
8136
  if (!status)
8018
8137
  {
8019
8138
  rb_raise(rb_eRuntimeError, "LevelizeImageChannel failed for unknown reason.");
@@ -8124,7 +8243,7 @@ Image_liquid_rescale(int argc, VALUE *argv, VALUE self)
8124
8243
  * @see Image__dump
8125
8244
  */
8126
8245
  VALUE
8127
- Image__load(VALUE class, VALUE str)
8246
+ Image__load(VALUE class ATTRIBUTE_UNUSED, VALUE str)
8128
8247
  {
8129
8248
  Image *image;
8130
8249
  ImageInfo *info;
@@ -8133,8 +8252,6 @@ Image__load(VALUE class, VALUE str)
8133
8252
  char *blob;
8134
8253
  long length;
8135
8254
 
8136
- class = class; // Suppress "never referenced" message from icc
8137
-
8138
8255
  blob = rm_str2cstr(str, &length);
8139
8256
 
8140
8257
  // Must be as least as big as the 1st 4 fields in DumpedImage
@@ -8442,73 +8559,24 @@ get_image_mask(Image *image)
8442
8559
  return mask ? rm_image_new(mask) : Qnil;
8443
8560
  }
8444
8561
 
8445
-
8446
- /**
8447
- * Set the image mask.
8448
- *
8449
- * Ruby usage:
8450
- * - @verbatim Image#mask= @endverbatim
8451
- *
8452
- * @param self this object
8453
- * @param mask the mask to use
8454
- * @return copy of the current clip-mask or nil
8455
- * @deprecated This method has been deprecated. Please use Image_mask(mask-image).
8456
- * @see Image_mask(mask-image)
8457
- * @see get_image_mask
8458
- */
8459
- VALUE
8460
- Image_mask_eq(VALUE self, VALUE mask)
8461
- {
8462
- VALUE v[1];
8463
- v[0] = mask;
8464
- rb_warning("Image#mask= is deprecated; use Image#mask.");
8465
- return Image_mask(1, v, self);
8466
- }
8467
-
8468
-
8469
8562
  /**
8470
- * Associate a clip mask with the image.
8563
+ * Sets the image's clip mask, or removes it when mask is nil.
8471
8564
  *
8472
- * Ruby usage:
8473
- * - @verbatim Image#mask @endverbatim
8474
- * - @verbatim Image#mask(mask-image) @endverbatim
8475
- *
8476
- * Notes:
8477
- * - Omit the argument to get a copy of the current clip mask.
8478
- * - Pass "nil" for the mask-image to remove the current clip mask.
8479
- * - If the clip mask is not the same size as the target image, resizes the
8480
- * clip mask to match the target.
8481
- * - Distinguish from Image#clip_mask=
8565
+ * No Ruby usage (internal function)
8482
8566
  *
8483
- * @param argc number of input arguments
8484
- * @param argv array of input arguments
8485
- * @param self this object
8567
+ * @param image the image
8568
+ * @param mask the mask
8486
8569
  * @return copy of the current clip-mask or nil
8487
- * @see get_image_mask
8488
8570
  */
8489
- VALUE
8490
- Image_mask(int argc, VALUE *argv, VALUE self)
8571
+ static VALUE
8572
+ set_image_mask(Image *image, VALUE mask)
8491
8573
  {
8492
- VALUE mask;
8493
- Image *image, *mask_image, *resized_image;
8574
+ Image *mask_image, *resized_image;
8494
8575
  Image *clip_mask;
8495
8576
  long x, y;
8496
8577
  PixelPacket *q;
8497
8578
  ExceptionInfo *exception;
8498
8579
 
8499
- image = rm_check_destroyed(self);
8500
- if (argc == 0)
8501
- {
8502
- return get_image_mask(image);
8503
- }
8504
- if (argc > 1)
8505
- {
8506
- rb_raise(rb_eArgError, "wrong number of arguments (expected 0 or 1, got %d)", argc);
8507
- }
8508
-
8509
- rb_check_frozen(self);
8510
- mask = argv[0];
8511
-
8512
8580
  if (mask != Qnil)
8513
8581
  {
8514
8582
  mask = rm_cur_image(mask);
@@ -8580,6 +8648,73 @@ Image_mask(int argc, VALUE *argv, VALUE self)
8580
8648
  }
8581
8649
 
8582
8650
 
8651
+ /**
8652
+ * Set the image mask.
8653
+ *
8654
+ * Ruby usage:
8655
+ * - @verbatim Image#mask= @endverbatim
8656
+ *
8657
+ * @param self this object
8658
+ * @param mask the mask to use
8659
+ * @return copy of the current clip-mask or nil
8660
+ * @deprecated This method has been deprecated. Please use Image_mask(mask-image).
8661
+ * @see Image_mask(mask-image)
8662
+ * @see get_image_mask
8663
+ */
8664
+ VALUE
8665
+ Image_mask_eq(VALUE self, VALUE mask)
8666
+ {
8667
+ VALUE v[1];
8668
+ v[0] = mask;
8669
+ rb_warning("Image#mask= is deprecated; use Image#mask.");
8670
+ return Image_mask(1, v, self);
8671
+ }
8672
+
8673
+
8674
+ /**
8675
+ * Associate a clip mask with the image.
8676
+ *
8677
+ * Ruby usage:
8678
+ * - @verbatim Image#mask @endverbatim
8679
+ * - @verbatim Image#mask(mask-image) @endverbatim
8680
+ *
8681
+ * Notes:
8682
+ * - Omit the argument to get a copy of the current clip mask.
8683
+ * - Pass "nil" for the mask-image to remove the current clip mask.
8684
+ * - If the clip mask is not the same size as the target image, resizes the
8685
+ * clip mask to match the target.
8686
+ * - Distinguish from Image#clip_mask=
8687
+ *
8688
+ * @param argc number of input arguments
8689
+ * @param argv array of input arguments
8690
+ * @param self this object
8691
+ * @return copy of the current clip-mask or nil
8692
+ * @see get_image_mask
8693
+ */
8694
+ VALUE
8695
+ Image_mask(int argc, VALUE *argv, VALUE self)
8696
+ {
8697
+ VALUE mask;
8698
+ Image *image;
8699
+
8700
+ image = rm_check_destroyed(self);
8701
+ if (argc == 0)
8702
+ {
8703
+ return get_image_mask(image);
8704
+ }
8705
+ if (argc > 1)
8706
+ {
8707
+ rb_raise(rb_eArgError, "wrong number of arguments (expected 0 or 1, got %d)", argc);
8708
+ }
8709
+
8710
+ rb_check_frozen(self);
8711
+ mask = argv[0];
8712
+
8713
+ // Always return a copy of the mask!
8714
+ return set_image_mask(image, mask);
8715
+ }
8716
+
8717
+
8583
8718
  /**
8584
8719
  * Get matte attribute.
8585
8720
  *
@@ -8660,14 +8795,14 @@ Image_matte_color(VALUE self)
8660
8795
  *
8661
8796
  * @param self this object
8662
8797
  * @param color the matte color
8663
- * @return self
8798
+ * @return color
8664
8799
  */
8665
8800
  VALUE
8666
8801
  Image_matte_color_eq(VALUE self, VALUE color)
8667
8802
  {
8668
8803
  Image *image = rm_check_frozen(self);
8669
8804
  Color_to_PixelColor(&image->matte_color, color);
8670
- return self;
8805
+ return color;
8671
8806
  }
8672
8807
 
8673
8808
 
@@ -8675,41 +8810,56 @@ Image_matte_color_eq(VALUE self, VALUE color)
8675
8810
  * Call MatteFloodFillImage.
8676
8811
  *
8677
8812
  * Ruby usage:
8678
- * - @verbatim Image#matte_flood_fill(color, opacity, x, y, method_obj) @endverbatim
8813
+ * - @verbatim Image#matte_flood_fill(color x, y, method_obj, alpha: alpha) @endverbatim
8679
8814
  *
8680
8815
  * @param self this object
8681
8816
  * @param color the color
8682
- * @param opacity the opacity
8817
+ * @param alpha the alpha
8683
8818
  * @param x_obj x position
8684
8819
  * @param y_obj y position
8685
8820
  * @param method_obj which method to call: FloodfillMethod or FillToBorderMethod
8686
8821
  * @return a new image
8687
8822
  */
8688
8823
  VALUE
8689
- Image_matte_flood_fill(VALUE self, VALUE color, VALUE opacity, VALUE x_obj, VALUE y_obj, VALUE method_obj)
8824
+ Image_matte_flood_fill(int argc, VALUE *argv, VALUE self)
8690
8825
  {
8691
8826
  Image *image, *new_image;
8692
8827
  PixelColor target;
8693
- Quantum op;
8828
+ Quantum alpha;
8694
8829
  long x, y;
8695
8830
  PaintMethod method;
8696
8831
  DrawInfo *draw_info;
8697
8832
  MagickPixel target_mpp;
8698
8833
  MagickBooleanType invert;
8834
+ int start_index;
8699
8835
 
8700
8836
  image = rm_check_destroyed(self);
8701
- Color_to_PixelColor(&target, color);
8702
8837
 
8703
- op = APP2QUANTUM(opacity);
8838
+ if (argc != 5)
8839
+ {
8840
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 5)", argc);
8841
+ }
8704
8842
 
8705
- VALUE_TO_ENUM(method_obj, method, PaintMethod);
8843
+ if (TYPE(argv[4]) == T_HASH)
8844
+ {
8845
+ alpha = get_alpha_from_hash(argv[4]);
8846
+ start_index = 1;
8847
+ }
8848
+ else
8849
+ {
8850
+ alpha = get_alpha_from_opacity(argv[1]);
8851
+ start_index = 2;
8852
+ }
8853
+
8854
+ Color_to_PixelColor(&target, argv[0]);
8855
+ VALUE_TO_ENUM(argv[start_index + 2], method, PaintMethod);
8706
8856
  if (!(method == FloodfillMethod || method == FillToBorderMethod))
8707
8857
  {
8708
8858
  rb_raise(rb_eArgError, "paint method_obj must be FloodfillMethod or "
8709
8859
  "FillToBorderMethod (%d given)", method);
8710
8860
  }
8711
- x = NUM2LONG(x_obj);
8712
- y = NUM2LONG(y_obj);
8861
+ x = NUM2LONG(argv[start_index]);
8862
+ y = NUM2LONG(argv[start_index + 1]);
8713
8863
  if ((unsigned long)x > image->columns || (unsigned long)y > image->rows)
8714
8864
  {
8715
8865
  rb_raise(rb_eArgError, "target out of range. %ldx%ld given, image is %lux%lu"
@@ -8725,7 +8875,7 @@ Image_matte_flood_fill(VALUE self, VALUE color, VALUE opacity, VALUE x_obj, VALU
8725
8875
  {
8726
8876
  rb_raise(rb_eNoMemError, "not enough memory to continue");
8727
8877
  }
8728
- draw_info->fill.opacity = op;
8878
+ draw_info->fill.opacity = QuantumRange - alpha;
8729
8879
 
8730
8880
  if (method == FillToBorderMethod)
8731
8881
  {
@@ -8956,7 +9106,7 @@ Image_modulate(int argc, VALUE *argv, VALUE self)
8956
9106
  *
8957
9107
  * @param self this object
8958
9108
  * @param monitor the progress monitor
8959
- * @return self
9109
+ * @return monitor
8960
9110
  */
8961
9111
  VALUE
8962
9112
  Image_monitor_eq(VALUE self, VALUE monitor)
@@ -8972,7 +9122,7 @@ Image_monitor_eq(VALUE self, VALUE monitor)
8972
9122
  (void) SetImageProgressMonitor(image, rm_progress_monitor, (void *)monitor);
8973
9123
  }
8974
9124
 
8975
- return self;
9125
+ return monitor;
8976
9126
  }
8977
9127
 
8978
9128
 
@@ -9179,7 +9329,7 @@ Image_negate_channel(int argc, VALUE *argv, VALUE self)
9179
9329
 
9180
9330
  new_image = rm_clone_image(image);
9181
9331
 
9182
- (void)NegateImageChannel(new_image, channels, grayscale);
9332
+ (void) NegateImageChannel(new_image, channels, grayscale);
9183
9333
  rm_check_image_exception(new_image, DestroyOnError);
9184
9334
 
9185
9335
  return rm_image_new(new_image);
@@ -9588,7 +9738,6 @@ Image_opaque_channel(int argc, VALUE *argv, VALUE self)
9588
9738
 
9589
9739
  okay = OpaquePaintImageChannel(new_image, channels, &target_pp, &fill_pp, invert);
9590
9740
 
9591
- // Restore saved fuzz value
9592
9741
  new_image->fuzz = keep;
9593
9742
  rm_check_image_exception(new_image, DestroyOnError);
9594
9743
 
@@ -9683,7 +9832,6 @@ Image_ordered_dither(int argc, VALUE *argv, VALUE self)
9683
9832
 
9684
9833
  exception = AcquireExceptionInfo();
9685
9834
 
9686
- // ImageMagick >= 6.2.9
9687
9835
  (void) OrderedPosterizeImage(new_image, threshold_map, exception);
9688
9836
  rm_check_exception(exception, new_image, DestroyOnError);
9689
9837
 
@@ -9706,7 +9854,7 @@ VALUE
9706
9854
  Image_orientation(VALUE self)
9707
9855
  {
9708
9856
  Image *image = rm_check_destroyed(self);
9709
- return OrientationType_new(image->orientation);
9857
+ return OrientationType_find(image->orientation);
9710
9858
  }
9711
9859
 
9712
9860
 
@@ -9718,14 +9866,14 @@ Image_orientation(VALUE self)
9718
9866
  *
9719
9867
  * @param self this object
9720
9868
  * @param orientation the orientation
9721
- * @return self
9869
+ * @return orientation
9722
9870
  */
9723
9871
  VALUE
9724
9872
  Image_orientation_eq(VALUE self, VALUE orientation)
9725
9873
  {
9726
9874
  Image *image = rm_check_frozen(self);
9727
9875
  VALUE_TO_ENUM(orientation, image->orientation, OrientationType);
9728
- return self;
9876
+ return orientation;
9729
9877
  }
9730
9878
 
9731
9879
 
@@ -9754,14 +9902,14 @@ Image_page(VALUE self)
9754
9902
  *
9755
9903
  * @param self this object
9756
9904
  * @param rect the page rectangle
9757
- * @return self
9905
+ * @return rect
9758
9906
  */
9759
9907
  VALUE
9760
9908
  Image_page_eq(VALUE self, VALUE rect)
9761
9909
  {
9762
9910
  Image *image = rm_check_frozen(self);
9763
9911
  Export_RectangleInfo(&image->page, rect);
9764
- return self;
9912
+ return rect;
9765
9913
  }
9766
9914
 
9767
9915
 
@@ -9770,12 +9918,12 @@ Image_page_eq(VALUE self, VALUE rect)
9770
9918
  *
9771
9919
  * Ruby usage:
9772
9920
  * - @verbatim Image#paint_transparent(target) @endverbatim
9773
- * - @verbatim Image#paint_transparent(target, opacity) @endverbatim
9774
- * - @verbatim Image#paint_transparent(target, opacity, invert) @endverbatim
9775
- * - @verbatim Image#paint_transparent(target, opacity, invert, fuzz) @endverbatim
9921
+ * - @verbatim Image#paint_transparent(target, alpha: alpha) @endverbatim
9922
+ * - @verbatim Image#paint_transparent(target, invert, alpha: alpha) @endverbatim
9923
+ * - @verbatim Image#paint_transparent(target, invert, fuzz, alpha: alpha) @endverbatim
9776
9924
  *
9777
9925
  * Notes:
9778
- * - Default opacity is TransparentOpacity
9926
+ * - Default alpha is TransparentAlpha
9779
9927
  * - Default invert is false
9780
9928
  * - Default fuzz is the image's fuzz (see Image_fuzz_eq)
9781
9929
  *
@@ -9789,23 +9937,45 @@ Image_paint_transparent(int argc, VALUE *argv, VALUE self)
9789
9937
  {
9790
9938
  Image *image, *new_image;
9791
9939
  MagickPixel color;
9792
- Quantum opacity = TransparentOpacity;
9940
+ Quantum alpha = TransparentAlpha;
9793
9941
  double keep, fuzz;
9794
- MagickBooleanType okay, invert = MagickFalse;
9942
+ MagickBooleanType okay, invert;
9795
9943
 
9796
9944
  image = rm_check_destroyed(self);
9797
9945
 
9798
9946
  // Default fuzz value is image's fuzz attribute.
9799
9947
  fuzz = image->fuzz;
9948
+ invert = MagickFalse;
9800
9949
 
9801
9950
  switch (argc)
9802
9951
  {
9803
9952
  case 4:
9804
- fuzz = NUM2DBL(argv[3]);
9953
+ if (TYPE(argv[argc - 1]) == T_HASH)
9954
+ {
9955
+ fuzz = NUM2DBL(argv[2]);
9956
+ }
9957
+ else
9958
+ {
9959
+ fuzz = NUM2DBL(argv[3]);
9960
+ }
9805
9961
  case 3:
9806
- invert = RTEST(argv[2]);
9962
+ if (TYPE(argv[argc - 1]) == T_HASH)
9963
+ {
9964
+ invert = RTEST(argv[1]);
9965
+ }
9966
+ else
9967
+ {
9968
+ invert = RTEST(argv[2]);
9969
+ }
9807
9970
  case 2:
9808
- opacity = APP2QUANTUM(argv[1]);
9971
+ if (TYPE(argv[argc - 1]) == T_HASH)
9972
+ {
9973
+ alpha = get_alpha_from_hash(argv[argc - 1]);
9974
+ }
9975
+ else
9976
+ {
9977
+ alpha = get_alpha_from_opacity(argv[1]);
9978
+ }
9809
9979
  case 1:
9810
9980
  Color_to_MagickPixel(image, &color, argv[0]);
9811
9981
  break;
@@ -9820,7 +9990,7 @@ Image_paint_transparent(int argc, VALUE *argv, VALUE self)
9820
9990
  keep = new_image->fuzz;
9821
9991
  new_image->fuzz = fuzz;
9822
9992
 
9823
- okay = TransparentPaintImage(new_image, (const MagickPixel *)&color, opacity, invert);
9993
+ okay = TransparentPaintImage(new_image, (const MagickPixel *)&color, QuantumRange - alpha, invert);
9824
9994
  new_image->fuzz = keep;
9825
9995
 
9826
9996
  // Is it possible for TransparentPaintImage to silently fail?
@@ -9894,11 +10064,12 @@ Image_pixel_color(int argc, VALUE *argv, VALUE self)
9894
10064
  {
9895
10065
  Image *image;
9896
10066
  PixelColor new_color;
9897
- PixelPacket old_color, *pixel;
10067
+ PixelPacket old_color;
9898
10068
  ExceptionInfo *exception;
9899
10069
  long x, y;
9900
10070
  unsigned int set = False;
9901
10071
  MagickBooleanType okay;
10072
+ PixelPacket *pixel;
9902
10073
 
9903
10074
  memset(&old_color, 0, sizeof(old_color));
9904
10075
 
@@ -9951,8 +10122,6 @@ Image_pixel_color(int argc, VALUE *argv, VALUE self)
9951
10122
  return Pixel_from_PixelColor(&image->background_color);
9952
10123
  }
9953
10124
 
9954
- // Set the color of a pixel. Return previous color.
9955
- // Convert to DirectClass
9956
10125
  if (image->storage_class == PseudoClass)
9957
10126
  {
9958
10127
  okay = SetImageStorageClass(image, DirectClass);
@@ -9963,7 +10132,6 @@ Image_pixel_color(int argc, VALUE *argv, VALUE self)
9963
10132
  }
9964
10133
  }
9965
10134
 
9966
-
9967
10135
  exception = AcquireExceptionInfo();
9968
10136
 
9969
10137
  pixel = GetAuthenticPixels(image, x, y, 1, 1, exception);
@@ -9976,11 +10144,11 @@ Image_pixel_color(int argc, VALUE *argv, VALUE self)
9976
10144
  {
9977
10145
  old_color.opacity = OpaqueOpacity;
9978
10146
  }
9979
- }
9980
- *pixel = new_color;
10147
+ *pixel = new_color;
9981
10148
 
9982
- SyncAuthenticPixels(image, exception);
9983
- CHECK_EXCEPTION()
10149
+ SyncAuthenticPixels(image, exception);
10150
+ CHECK_EXCEPTION()
10151
+ }
9984
10152
 
9985
10153
  (void) DestroyExceptionInfo(exception);
9986
10154
 
@@ -10003,7 +10171,7 @@ VALUE
10003
10171
  Image_pixel_interpolation_method(VALUE self)
10004
10172
  {
10005
10173
  Image *image = rm_check_destroyed(self);
10006
- return InterpolatePixelMethod_new(image->interpolate);
10174
+ return PixelInterpolateMethod_find(image->interpolate);
10007
10175
  }
10008
10176
 
10009
10177
 
@@ -10015,7 +10183,7 @@ Image_pixel_interpolation_method(VALUE self)
10015
10183
  *
10016
10184
  * @param self this object
10017
10185
  * @param method the interpolate field
10018
- * @return self
10186
+ * @return method
10019
10187
  * @see Image_pixel_interpolation_method
10020
10188
  * @see Image.interpolate_pixel_color
10021
10189
  */
@@ -10023,8 +10191,8 @@ VALUE
10023
10191
  Image_pixel_interpolation_method_eq(VALUE self, VALUE method)
10024
10192
  {
10025
10193
  Image *image = rm_check_frozen(self);
10026
- VALUE_TO_ENUM(method, image->interpolate, InterpolatePixelMethod);
10027
- return self;
10194
+ VALUE_TO_ENUM(method, image->interpolate, PixelInterpolateMethod);
10195
+ return method;
10028
10196
  }
10029
10197
 
10030
10198
 
@@ -10230,8 +10398,6 @@ Image_quantum_depth(VALUE self)
10230
10398
  image = rm_check_destroyed(self);
10231
10399
  quantum_depth = GetImageQuantumDepth(image, MagickFalse);
10232
10400
 
10233
- rm_check_image_exception(image, RetainOnError);
10234
-
10235
10401
  return ULONG2NUM(quantum_depth);
10236
10402
  }
10237
10403
 
@@ -10729,7 +10895,7 @@ file_arg_rescue(VALUE arg)
10729
10895
  * @see array_from_images
10730
10896
  */
10731
10897
  static VALUE
10732
- rd_image(VALUE class, VALUE file, reader_t reader)
10898
+ rd_image(VALUE class ATTRIBUTE_UNUSED, VALUE file, reader_t reader)
10733
10899
  {
10734
10900
  char *filename;
10735
10901
  long filename_l;
@@ -10738,8 +10904,6 @@ rd_image(VALUE class, VALUE file, reader_t reader)
10738
10904
  Image *images;
10739
10905
  ExceptionInfo *exception;
10740
10906
 
10741
- class = class; // defeat gcc message
10742
-
10743
10907
  // Create a new Info structure for this read/ping
10744
10908
  info_obj = rm_info_new();
10745
10909
  Data_Get_Struct(info_obj, Info, info);
@@ -10826,11 +10990,10 @@ Image_recolor(VALUE self, VALUE color_matrix)
10826
10990
 
10827
10991
  order = (unsigned long)sqrt((double)(len + 1.0));
10828
10992
 
10829
- // RecolorImage sets the ExceptionInfo and returns a NULL image if an error occurs.
10830
10993
  kernel_info = AcquireKernelInfo(NULL);
10831
10994
  if (kernel_info == (KernelInfo *) NULL)
10832
10995
  {
10833
- xfree((void *)matrix);
10996
+ xfree((void *) matrix);
10834
10997
  return Qnil;
10835
10998
  }
10836
10999
  kernel_info->width = order;
@@ -10840,8 +11003,8 @@ Image_recolor(VALUE self, VALUE color_matrix)
10840
11003
  exception = AcquireExceptionInfo();
10841
11004
  new_image = ColorMatrixImage(image, kernel_info, exception);
10842
11005
  kernel_info->values = (double *) NULL;
10843
- kernel_info = DestroyKernelInfo(kernel_info);
10844
- xfree((void *)matrix);
11006
+ (void) DestroyKernelInfo(kernel_info);
11007
+ xfree((void *) matrix);
10845
11008
 
10846
11009
  rm_check_exception(exception, new_image, DestroyOnError);
10847
11010
  (void) DestroyExceptionInfo(exception);
@@ -10867,7 +11030,7 @@ Image_recolor(VALUE self, VALUE color_matrix)
10867
11030
  * @see array_from_images
10868
11031
  */
10869
11032
  VALUE
10870
- Image_read_inline(VALUE self, VALUE content)
11033
+ Image_read_inline(VALUE self ATTRIBUTE_UNUSED, VALUE content)
10871
11034
  {
10872
11035
  VALUE info_obj;
10873
11036
  Image *images;
@@ -10878,8 +11041,6 @@ Image_read_inline(VALUE self, VALUE content)
10878
11041
  size_t blob_l;
10879
11042
  ExceptionInfo *exception;
10880
11043
 
10881
- self = self; // defeat gcc message
10882
-
10883
11044
  image_data = rm_str2cstr(content, &image_data_l);
10884
11045
 
10885
11046
  // Search for a comma. If found, we'll set the start of the
@@ -10970,11 +11131,12 @@ Image_reduce_noise(VALUE self, VALUE radius)
10970
11131
  {
10971
11132
  Image *image, *new_image;
10972
11133
  ExceptionInfo *exception;
11134
+ size_t radius_size = NUM2SIZET(radius);
10973
11135
 
10974
11136
  image = rm_check_destroyed(self);
10975
11137
 
10976
11138
  exception = AcquireExceptionInfo();
10977
- new_image = StatisticImage(image, NonpeakStatistic, (size_t)radius, (size_t)radius, exception);
11139
+ new_image = StatisticImage(image, NonpeakStatistic, radius_size, radius_size, exception);
10978
11140
  rm_check_exception(exception, new_image, DestroyOnError);
10979
11141
 
10980
11142
  (void) DestroyExceptionInfo(exception);
@@ -11047,7 +11209,7 @@ VALUE
11047
11209
  Image_rendering_intent(VALUE self)
11048
11210
  {
11049
11211
  Image *image = rm_check_destroyed(self);
11050
- return RenderingIntent_new(image->rendering_intent);
11212
+ return RenderingIntent_find(image->rendering_intent);
11051
11213
  }
11052
11214
 
11053
11215
 
@@ -11059,14 +11221,14 @@ Image_rendering_intent(VALUE self)
11059
11221
  *
11060
11222
  * @param self this object
11061
11223
  * @param ri the rendering intent
11062
- * @return self
11224
+ * @return ri
11063
11225
  */
11064
11226
  VALUE
11065
11227
  Image_rendering_intent_eq(VALUE self, VALUE ri)
11066
11228
  {
11067
11229
  Image *image = rm_check_frozen(self);
11068
11230
  VALUE_TO_ENUM(ri, image->rendering_intent, RenderingIntent);
11069
- return self;
11231
+ return ri;
11070
11232
  }
11071
11233
 
11072
11234
 
@@ -11088,7 +11250,7 @@ static VALUE
11088
11250
  resample(int bang, int argc, VALUE *argv, VALUE self)
11089
11251
  {
11090
11252
  Image *image, *new_image;
11091
- FilterTypes filter;
11253
+ FilterType filter;
11092
11254
  double x_resolution, y_resolution, blur;
11093
11255
  double width, height;
11094
11256
  ExceptionInfo *exception;
@@ -11106,7 +11268,7 @@ resample(int bang, int argc, VALUE *argv, VALUE self)
11106
11268
  case 4:
11107
11269
  blur = NUM2DBL(argv[3]);
11108
11270
  case 3:
11109
- VALUE_TO_ENUM(argv[2], filter, FilterTypes);
11271
+ VALUE_TO_ENUM(argv[2], filter, FilterType);
11110
11272
  case 2:
11111
11273
  y_resolution = NUM2DBL(argv[1]);
11112
11274
  if (y_resolution < 0.0)
@@ -11235,7 +11397,7 @@ resize(int bang, int argc, VALUE *argv, VALUE self)
11235
11397
  {
11236
11398
  Image *image, *new_image;
11237
11399
  double scale_arg;
11238
- FilterTypes filter;
11400
+ FilterType filter;
11239
11401
  unsigned long rows, columns;
11240
11402
  double blur, drows, dcols;
11241
11403
  ExceptionInfo *exception;
@@ -11253,7 +11415,7 @@ resize(int bang, int argc, VALUE *argv, VALUE self)
11253
11415
  case 4:
11254
11416
  blur = NUM2DBL(argv[3]);
11255
11417
  case 3:
11256
- VALUE_TO_ENUM(argv[2], filter, FilterTypes);
11418
+ VALUE_TO_ENUM(argv[2], filter, FilterType);
11257
11419
  case 2:
11258
11420
  rows = NUM2ULONG(argv[1]);
11259
11421
  columns = NUM2ULONG(argv[0]);
@@ -11941,7 +12103,8 @@ Image_segment(int argc, VALUE *argv, VALUE self)
11941
12103
  *
11942
12104
  * @param self this object
11943
12105
  * @param opacity_arg the opacity
11944
- * @return self
12106
+ * @return opacity_arg
12107
+ * @deprecated This method has been deprecated. Please use Image_alpha.
11945
12108
  */
11946
12109
  VALUE
11947
12110
  Image_opacity_eq(VALUE self, VALUE opacity_arg)
@@ -11949,11 +12112,13 @@ Image_opacity_eq(VALUE self, VALUE opacity_arg)
11949
12112
  Image *image;
11950
12113
  Quantum opacity;
11951
12114
 
12115
+ rb_warning("Image#opacity is deprecated; use Image#alpha");
12116
+
11952
12117
  image = rm_check_frozen(self);
11953
12118
  opacity = APP2QUANTUM(opacity_arg);
11954
12119
  (void) SetImageOpacity(image, opacity);
11955
12120
  rm_check_image_exception(image, RetainOnError);
11956
- return self;
12121
+ return opacity_arg;
11957
12122
  }
11958
12123
 
11959
12124
 
@@ -11975,10 +12140,8 @@ VALUE
11975
12140
  Image_properties(VALUE self)
11976
12141
  {
11977
12142
  Image *image;
11978
- VALUE attr_hash;
11979
- VALUE ary;
11980
- char *property;
11981
- const char *value;
12143
+ VALUE attr_hash, ary;
12144
+ const char *property, *value;
11982
12145
 
11983
12146
  image = rm_check_destroyed(self);
11984
12147
 
@@ -12083,7 +12246,7 @@ Image_shade(int argc, VALUE *argv, VALUE self)
12083
12246
 
12084
12247
 
12085
12248
  /**
12086
- * Call ShadowImage. X- and y-offsets are the pixel offset. Opacity is either a
12249
+ * Call ShadowImage. X- and y-offsets are the pixel offset. Alpha is either a
12087
12250
  * number between 0 and 1 or a string "NN%". Sigma is the std. dev. of the
12088
12251
  * Gaussian, in pixels.
12089
12252
  *
@@ -12092,14 +12255,14 @@ Image_shade(int argc, VALUE *argv, VALUE self)
12092
12255
  * - @verbatim Image#shadow(x_offset) @endverbatim
12093
12256
  * - @verbatim Image#shadow(x_offset, y_offset) @endverbatim
12094
12257
  * - @verbatim Image#shadow(x_offset, y_offset, sigma) @endverbatim
12095
- * - @verbatim Image#shadow(x_offset, y_offset, sigma, opacity) @endverbatim
12258
+ * - @verbatim Image#shadow(x_offset, y_offset, sigma, alpha) @endverbatim
12096
12259
  *
12097
12260
  * Notes:
12098
12261
  * - Default x_offset is 4
12099
12262
  * - Default y_offset is 4
12100
12263
  * - Default sigma is 4.0
12101
- * - Default opacity is 1.0
12102
- * - The defaults are taken from the mogrify.c source, except for opacity,
12264
+ * - Default alpha is 1.0
12265
+ * - The defaults are taken from the mogrify.c source, except for alpha,
12103
12266
  * which has no default.
12104
12267
  * - Introduced in ImageMagick 6.1.7
12105
12268
  *
@@ -12112,7 +12275,7 @@ VALUE
12112
12275
  Image_shadow(int argc, VALUE *argv, VALUE self)
12113
12276
  {
12114
12277
  Image *image, *new_image;
12115
- double opacity = 100.0;
12278
+ double alpha = 100.0;
12116
12279
  double sigma = 4.0;
12117
12280
  long x_offset = 4L;
12118
12281
  long y_offset = 4L;
@@ -12122,14 +12285,14 @@ Image_shadow(int argc, VALUE *argv, VALUE self)
12122
12285
  switch (argc)
12123
12286
  {
12124
12287
  case 4:
12125
- opacity = rm_percentage(argv[3],1.0); // Clamp to 1.0 < x <= 100.0
12126
- if (fabs(opacity) < 0.01)
12288
+ alpha = rm_percentage(argv[3],1.0); // Clamp to 1.0 < x <= 100.0
12289
+ if (fabs(alpha) < 0.01)
12127
12290
  {
12128
- rb_warning("shadow will be transparent - opacity %g very small", opacity);
12291
+ rb_warning("shadow will be transparent - alpha %g very small", alpha);
12129
12292
  }
12130
- opacity = FMIN(opacity, 1.0);
12131
- opacity = FMAX(opacity, 0.01);
12132
- opacity *= 100.0;
12293
+ alpha = FMIN(alpha, 1.0);
12294
+ alpha = FMAX(alpha, 0.01);
12295
+ alpha *= 100.0;
12133
12296
  case 3:
12134
12297
  sigma = NUM2DBL(argv[2]);
12135
12298
  case 2:
@@ -12144,7 +12307,7 @@ Image_shadow(int argc, VALUE *argv, VALUE self)
12144
12307
  }
12145
12308
 
12146
12309
  exception = AcquireExceptionInfo();
12147
- new_image = ShadowImage(image, opacity, sigma, x_offset, y_offset, exception);
12310
+ new_image = ShadowImage(image, alpha, sigma, x_offset, y_offset, exception);
12148
12311
  rm_check_exception(exception, new_image, DestroyOnError);
12149
12312
 
12150
12313
  (void) DestroyExceptionInfo(exception);
@@ -12388,8 +12551,8 @@ Image_signature(VALUE self)
12388
12551
  image = rm_check_destroyed(self);
12389
12552
 
12390
12553
  (void) SignatureImage(image);
12391
- signature = rm_get_property(image, "signature");
12392
12554
  rm_check_image_exception(image, RetainOnError);
12555
+ signature = rm_get_property(image, "signature");
12393
12556
  if (!signature)
12394
12557
  {
12395
12558
  return Qnil;
@@ -12645,7 +12808,7 @@ Image_sparse_color(int argc, VALUE *argv, VALUE self)
12645
12808
  }
12646
12809
  else
12647
12810
  {
12648
- xfree((void *)args);
12811
+ xfree((void *) args);
12649
12812
  rb_raise(rb_eTypeError, "type mismatch: %s and %s given", rb_class2name(CLASS_OF(elem1)), rb_class2name(CLASS_OF(elem2)));
12650
12813
  }
12651
12814
  Color_to_MagickPixel(NULL, &pp, argv[n++]);
@@ -12673,8 +12836,8 @@ Image_sparse_color(int argc, VALUE *argv, VALUE self)
12673
12836
 
12674
12837
  exception = AcquireExceptionInfo();
12675
12838
  new_image = SparseColorImage(image, channels, method, nargs, args, exception);
12676
- xfree(args);
12677
- CHECK_EXCEPTION();
12839
+ xfree((void *) args);
12840
+ rm_check_exception(exception, new_image, DestroyOnError);
12678
12841
  (void) DestroyExceptionInfo(exception);
12679
12842
  rm_ensure_result(new_image);
12680
12843
 
@@ -12893,7 +13056,7 @@ VALUE
12893
13056
  Image_class_type(VALUE self)
12894
13057
  {
12895
13058
  Image *image = rm_check_destroyed(self);
12896
- return ClassType_new(image->storage_class);
13059
+ return ClassType_find(image->storage_class);
12897
13060
  }
12898
13061
 
12899
13062
 
@@ -12908,7 +13071,7 @@ Image_class_type(VALUE self)
12908
13071
  *
12909
13072
  * @param self this object
12910
13073
  * @param new_class_type the storage class
12911
- * @return self
13074
+ * @return new_class_type
12912
13075
  */
12913
13076
  VALUE
12914
13077
  Image_class_type_eq(VALUE self, VALUE new_class_type)
@@ -12921,6 +13084,11 @@ Image_class_type_eq(VALUE self, VALUE new_class_type)
12921
13084
 
12922
13085
  VALUE_TO_ENUM(new_class_type, class_type, ClassType);
12923
13086
 
13087
+ if (class_type == UndefinedClass)
13088
+ {
13089
+ rb_raise(rb_eArgError, "Invalid class type specified.");
13090
+ }
13091
+
12924
13092
  if (image->storage_class == PseudoClass && class_type == DirectClass)
12925
13093
  {
12926
13094
  (void) SyncImage(image);
@@ -12935,7 +13103,7 @@ Image_class_type_eq(VALUE self, VALUE new_class_type)
12935
13103
  }
12936
13104
 
12937
13105
  (void) SetImageStorageClass(image, class_type);
12938
- return self;
13106
+ return new_class_type;
12939
13107
  }
12940
13108
 
12941
13109
 
@@ -12963,13 +13131,14 @@ Image_store_pixels(VALUE self, VALUE x_arg, VALUE y_arg, VALUE cols_arg
12963
13131
  , VALUE rows_arg, VALUE new_pixels)
12964
13132
  {
12965
13133
  Image *image;
12966
- Pixel *pixels, *pixel;
13134
+ Pixel *pixel;
12967
13135
  VALUE new_pixel;
12968
13136
  long n, size;
12969
13137
  long x, y;
12970
13138
  unsigned long cols, rows;
12971
13139
  unsigned int okay;
12972
13140
  ExceptionInfo *exception;
13141
+ PixelPacket *pixels;
12973
13142
 
12974
13143
  image = rm_check_destroyed(self);
12975
13144
 
@@ -13084,10 +13253,12 @@ Image_swirl(VALUE self, VALUE degrees_obj)
13084
13253
  *
13085
13254
  * @param self this object
13086
13255
  * @return true if succeeded, otherwise false
13256
+ * @deprecated This method has been deprecated.
13087
13257
  */
13088
13258
  VALUE
13089
13259
  Image_sync_profiles(VALUE self)
13090
13260
  {
13261
+ rb_warning("Image#sync_profiles is deprecated");
13091
13262
  Image *image = rm_check_destroyed(self);
13092
13263
  VALUE okay = SyncImageProfiles(image) ? Qtrue : Qfalse;
13093
13264
  rm_check_image_exception(image, RetainOnError);
@@ -13234,7 +13405,7 @@ static
13234
13405
  VALUE threshold_image(int argc, VALUE *argv, VALUE self, thresholder_t thresholder)
13235
13406
  {
13236
13407
  Image *image, *new_image;
13237
- double red, green, blue, opacity;
13408
+ double red, green, blue, alpha;
13238
13409
  char ctarg[200];
13239
13410
 
13240
13411
  image = rm_check_destroyed(self);
@@ -13245,8 +13416,8 @@ VALUE threshold_image(int argc, VALUE *argv, VALUE self, thresholder_t threshold
13245
13416
  red = NUM2DBL(argv[0]);
13246
13417
  green = NUM2DBL(argv[1]);
13247
13418
  blue = NUM2DBL(argv[2]);
13248
- opacity = NUM2DBL(argv[3]);
13249
- sprintf(ctarg, "%f,%f,%f,%f", red, green, blue, opacity);
13419
+ alpha = get_named_alpha_value(argv[3]);
13420
+ sprintf(ctarg, "%f,%f,%f,%f", red, green, blue, QuantumRange - alpha);
13250
13421
  break;
13251
13422
  case 3:
13252
13423
  red = NUM2DBL(argv[0]);
@@ -13298,6 +13469,8 @@ thumbnail(int bang, int argc, VALUE *argv, VALUE self)
13298
13469
  Image *image, *new_image;
13299
13470
  unsigned long columns, rows;
13300
13471
  double scale_arg, drows, dcols;
13472
+ char image_geometry[MaxTextExtent];
13473
+ RectangleInfo geometry;
13301
13474
  ExceptionInfo *exception;
13302
13475
 
13303
13476
  Data_Get_Struct(self, Image, image);
@@ -13332,8 +13505,13 @@ thumbnail(int bang, int argc, VALUE *argv, VALUE self)
13332
13505
  break;
13333
13506
  }
13334
13507
 
13508
+ snprintf(image_geometry, sizeof(image_geometry), "%ldx%ld", columns, rows);
13509
+
13335
13510
  exception = AcquireExceptionInfo();
13336
- new_image = ThumbnailImage(image, columns, rows, exception);
13511
+ (void) ParseRegionGeometry(image, image_geometry, &geometry, exception);
13512
+ rm_check_exception(exception, image, RetainOnError);
13513
+
13514
+ new_image = ThumbnailImage(image, geometry.width, geometry.height, exception);
13337
13515
  rm_check_exception(exception, new_image, DestroyOnError);
13338
13516
 
13339
13517
  (void) DestroyExceptionInfo(exception);
@@ -13420,14 +13598,14 @@ Image_ticks_per_second(VALUE self)
13420
13598
  *
13421
13599
  * @param self this object
13422
13600
  * @param tps ticks per second
13423
- * @return self
13601
+ * @return tps
13424
13602
  */
13425
13603
  VALUE
13426
13604
  Image_ticks_per_second_eq(VALUE self, VALUE tps)
13427
13605
  {
13428
13606
  Image *image = rm_check_frozen(self);
13429
13607
  image->ticks_per_second = NUM2ULONG(tps);
13430
- return self;
13608
+ return tps;
13431
13609
  }
13432
13610
 
13433
13611
 
@@ -13435,16 +13613,16 @@ Image_ticks_per_second_eq(VALUE self, VALUE tps)
13435
13613
  * Call TintImage.
13436
13614
  *
13437
13615
  * Ruby usage:
13438
- * - @verbatim Image#tint(tint, red_opacity) @endverbatim
13439
- * - @verbatim Image#tint(tint, red_opacity, green_opacity) @endverbatim
13440
- * - @verbatim Image#tint(tint, red_opacity, green_opacity, blue_opacity) @endverbatim
13441
- * - @verbatim Image#tint(tint, red_opacity, green_opacity, blue_opacity, alpha_opacity) @endverbatim
13616
+ * - @verbatim Image#tint(tint, red_alpha) @endverbatim
13617
+ * - @verbatim Image#tint(tint, red_alpha, green_alpha) @endverbatim
13618
+ * - @verbatim Image#tint(tint, red_alpha, green_alpha, blue_alpha) @endverbatim
13619
+ * - @verbatim Image#tint(tint, red_alpha, green_alpha, blue_alpha, alpha_alpha) @endverbatim
13442
13620
  *
13443
13621
  * Notes:
13444
- * - Default green_opacity is red_opacity
13445
- * - Default blue_opacity is red_opacity
13446
- * - Default alpha_opacity is 1.0
13447
- * - Opacity values are percentages: 0.10 -> 10%.
13622
+ * - Default green_alpha is red_alpha
13623
+ * - Default blue_alpha is red_alpha
13624
+ * - Default alpha_alpha is 1.0
13625
+ * - Alpha values are percentages: 0.10 -> 10%.
13448
13626
  *
13449
13627
  * @param argc number of input arguments
13450
13628
  * @param argv array of input arguments
@@ -13458,7 +13636,7 @@ Image_tint(int argc, VALUE *argv, VALUE self)
13458
13636
  PixelColor tint;
13459
13637
  double red_pct_opaque, green_pct_opaque, blue_pct_opaque;
13460
13638
  double alpha_pct_opaque = 1.0;
13461
- char opacity[50];
13639
+ char alpha[50];
13462
13640
  ExceptionInfo *exception;
13463
13641
 
13464
13642
  image = rm_check_destroyed(self);
@@ -13493,21 +13671,17 @@ Image_tint(int argc, VALUE *argv, VALUE self)
13493
13671
  if (red_pct_opaque < 0.0 || green_pct_opaque < 0.0
13494
13672
  || blue_pct_opaque < 0.0 || alpha_pct_opaque < 0.0)
13495
13673
  {
13496
- rb_raise(rb_eArgError, "opacity percentages must be non-negative.");
13674
+ rb_raise(rb_eArgError, "alpha percentages must be non-negative.");
13497
13675
  }
13498
13676
 
13499
- #if defined(HAVE_SNPRINTF)
13500
- snprintf(opacity, sizeof(opacity),
13501
- #else
13502
- sprintf(opacity,
13503
- #endif
13677
+ snprintf(alpha, sizeof(alpha),
13504
13678
  "%g,%g,%g,%g", red_pct_opaque*100.0, green_pct_opaque*100.0
13505
13679
  , blue_pct_opaque*100.0, alpha_pct_opaque*100.0);
13506
13680
 
13507
13681
  Color_to_PixelColor(&tint, argv[0]);
13508
13682
  exception = AcquireExceptionInfo();
13509
13683
 
13510
- new_image = TintImage(image, opacity, tint, exception);
13684
+ new_image = TintImage(image, alpha, tint, exception);
13511
13685
  rm_check_exception(exception, new_image, DestroyOnError);
13512
13686
 
13513
13687
  (void) DestroyExceptionInfo(exception);
@@ -13639,7 +13813,6 @@ Image_to_color(VALUE self, VALUE pixel_arg)
13639
13813
  // doesn't have a "real" name, just a sequence of hex digits. We don't care
13640
13814
  // about that.
13641
13815
 
13642
- name[0] = '\0';
13643
13816
  (void) QueryColorname(image, &pixel, AllCompliance, name, exception);
13644
13817
  CHECK_EXCEPTION()
13645
13818
 
@@ -13701,13 +13874,13 @@ Image_total_ink_density(VALUE self)
13701
13874
  *
13702
13875
  * Ruby usage:
13703
13876
  * - @verbatim Image#transparent(color-name) @endverbatim
13704
- * - @verbatim Image#transparent(color-name, opacity) @endverbatim
13877
+ * - @verbatim Image#transparent(color-name, alpha: alpha) @endverbatim
13705
13878
  * - @verbatim Image#transparent(pixel) @endverbatim
13706
- * - @verbatim Image#transparent(pixel, opacity) @endverbatim
13879
+ * - @verbatim Image#transparent(pixel, alpha: alpha) @endverbatim
13707
13880
  *
13708
13881
  * Notes:
13709
- * - Default opacity is Magick::TransparentOpacity.
13710
- * - Can use Magick::OpaqueOpacity or Magick::TransparentOpacity, or any
13882
+ * - Default alpha is Magick::TransparentAlpha.
13883
+ * - Can use Magick::OpaqueAlpha or Magick::TransparentAlpha, or any
13711
13884
  * value >= 0 && <= QuantumRange.
13712
13885
  * - Use Image#fuzz= to define the tolerance level.
13713
13886
  *
@@ -13721,7 +13894,7 @@ Image_transparent(int argc, VALUE *argv, VALUE self)
13721
13894
  {
13722
13895
  Image *image, *new_image;
13723
13896
  MagickPixel color;
13724
- Quantum opacity = TransparentOpacity;
13897
+ Quantum alpha = TransparentAlpha;
13725
13898
  MagickBooleanType okay;
13726
13899
 
13727
13900
  image = rm_check_destroyed(self);
@@ -13729,7 +13902,7 @@ Image_transparent(int argc, VALUE *argv, VALUE self)
13729
13902
  switch (argc)
13730
13903
  {
13731
13904
  case 2:
13732
- opacity = APP2QUANTUM(argv[1]);
13905
+ alpha = get_named_alpha_value(argv[1]);
13733
13906
  case 1:
13734
13907
  Color_to_MagickPixel(image, &color, argv[0]);
13735
13908
  break;
@@ -13740,7 +13913,7 @@ Image_transparent(int argc, VALUE *argv, VALUE self)
13740
13913
 
13741
13914
  new_image = rm_clone_image(image);
13742
13915
 
13743
- okay = TransparentPaintImage(new_image, &color, opacity, MagickFalse);
13916
+ okay = TransparentPaintImage(new_image, &color, QuantumRange - alpha, MagickFalse);
13744
13917
  rm_check_image_exception(new_image, DestroyOnError);
13745
13918
  if (!okay)
13746
13919
  {
@@ -13758,11 +13931,11 @@ Image_transparent(int argc, VALUE *argv, VALUE self)
13758
13931
  *
13759
13932
  * Ruby usage:
13760
13933
  * - @verbatim Image#transparent_chroma(low, high) @endverbatim
13761
- * - @verbatim Image#transparent_chroma(low, high, opacity) @endverbatim
13762
- * - @verbatim Image#transparent_chroma(low, high, opacity, invert) @endverbatim
13934
+ * - @verbatim Image#transparent_chroma(low, high, alpha: alpha) @endverbatim
13935
+ * - @verbatim Image#transparent_chroma(low, high, invert, alpha: alpha) @endverbatim
13763
13936
  *
13764
13937
  * Notes:
13765
- * - Default opacity is TransparentOpacity
13938
+ * - Default alpha is TransparentAlpha
13766
13939
  * - Default invert is false
13767
13940
  * - Available in ImageMagick >= 6.4.5-6
13768
13941
  *
@@ -13775,7 +13948,7 @@ VALUE
13775
13948
  Image_transparent_chroma(int argc, VALUE *argv, VALUE self)
13776
13949
  {
13777
13950
  Image *image, *new_image;
13778
- Quantum opacity = TransparentOpacity;
13951
+ Quantum alpha = TransparentAlpha;
13779
13952
  MagickPixel low, high;
13780
13953
  MagickBooleanType invert = MagickFalse;
13781
13954
  MagickBooleanType okay;
@@ -13785,9 +13958,23 @@ Image_transparent_chroma(int argc, VALUE *argv, VALUE self)
13785
13958
  switch (argc)
13786
13959
  {
13787
13960
  case 4:
13788
- invert = RTEST(argv[3]);
13961
+ if (TYPE(argv[argc - 1]) == T_HASH)
13962
+ {
13963
+ invert = RTEST(argv[3]);
13964
+ }
13965
+ else
13966
+ {
13967
+ invert = RTEST(argv[2]);
13968
+ }
13789
13969
  case 3:
13790
- opacity = APP2QUANTUM(argv[2]);
13970
+ if (TYPE(argv[argc - 1]) == T_HASH)
13971
+ {
13972
+ alpha = get_alpha_from_hash(argv[argc - 1]);
13973
+ }
13974
+ else
13975
+ {
13976
+ alpha = get_alpha_from_opacity(argv[2]);
13977
+ }
13791
13978
  case 2:
13792
13979
  Color_to_MagickPixel(image, &high, argv[1]);
13793
13980
  Color_to_MagickPixel(image, &low, argv[0]);
@@ -13799,7 +13986,7 @@ Image_transparent_chroma(int argc, VALUE *argv, VALUE self)
13799
13986
 
13800
13987
  new_image = rm_clone_image(image);
13801
13988
 
13802
- okay = TransparentPaintImageChroma(new_image, &low, &high, opacity, invert);
13989
+ okay = TransparentPaintImageChroma(new_image, &low, &high, QuantumRange - alpha, invert);
13803
13990
  rm_check_image_exception(new_image, DestroyOnError);
13804
13991
  if (!okay)
13805
13992
  {
@@ -13837,14 +14024,14 @@ Image_transparent_color(VALUE self)
13837
14024
  *
13838
14025
  * @param self this object
13839
14026
  * @param color the transparent color
13840
- * @return self
14027
+ * @return color
13841
14028
  */
13842
14029
  VALUE
13843
14030
  Image_transparent_color_eq(VALUE self, VALUE color)
13844
14031
  {
13845
14032
  Image *image = rm_check_frozen(self);
13846
14033
  Color_to_PixelColor(&image->transparent_color, color);
13847
- return self;
14034
+ return color;
13848
14035
  }
13849
14036
 
13850
14037
 
@@ -14047,7 +14234,7 @@ Image_trim_bang(int argc, VALUE *argv, VALUE self)
14047
14234
  VALUE Image_gravity(VALUE self)
14048
14235
  {
14049
14236
  Image *image = rm_check_destroyed(self);
14050
- return GravityType_new(image->gravity);
14237
+ return GravityType_find(image->gravity);
14051
14238
  }
14052
14239
 
14053
14240
 
@@ -14091,7 +14278,7 @@ VALUE Image_image_type(VALUE self)
14091
14278
 
14092
14279
  (void) DestroyExceptionInfo(exception);
14093
14280
 
14094
- return ImageType_new(type);
14281
+ return ImageType_find(type);
14095
14282
  }
14096
14283
 
14097
14284
 
@@ -14186,7 +14373,7 @@ VALUE
14186
14373
  Image_units(VALUE self)
14187
14374
  {
14188
14375
  Image *image = rm_check_destroyed(self);
14189
- return ResolutionType_new(image->units);
14376
+ return ResolutionType_find(image->units);
14190
14377
  }
14191
14378
 
14192
14379
 
@@ -14198,7 +14385,7 @@ Image_units(VALUE self)
14198
14385
  *
14199
14386
  * @param self this object
14200
14387
  * @param restype the resolution type
14201
- * @return self
14388
+ * @return restype
14202
14389
  */
14203
14390
  VALUE
14204
14391
  Image_units_eq(VALUE self, VALUE restype)
@@ -14238,7 +14425,7 @@ Image_units_eq(VALUE self, VALUE restype)
14238
14425
  image->units = units;
14239
14426
  }
14240
14427
 
14241
- return self;
14428
+ return restype;
14242
14429
  }
14243
14430
 
14244
14431
 
@@ -14388,8 +14575,7 @@ Image_unsharp_mask_channel(int argc, VALUE *argv, VALUE self)
14388
14575
  unsharp_mask_args(argc, argv, &radius, &sigma, &amount, &threshold);
14389
14576
 
14390
14577
  exception = AcquireExceptionInfo();
14391
- new_image = UnsharpMaskImageChannel(image, channels, radius, sigma, amount
14392
- , threshold, exception);
14578
+ new_image = UnsharpMaskImageChannel(image, channels, radius, sigma, amount, threshold, exception);
14393
14579
  rm_check_exception(exception, new_image, DestroyOnError);
14394
14580
 
14395
14581
  (void) DestroyExceptionInfo(exception);
@@ -14482,8 +14668,7 @@ Image_virtual_pixel_method(VALUE self)
14482
14668
 
14483
14669
  image = rm_check_destroyed(self);
14484
14670
  vpm = GetImageVirtualPixelMethod(image);
14485
- rm_check_image_exception(image, RetainOnError);
14486
- return VirtualPixelMethod_new(vpm);
14671
+ return VirtualPixelMethod_find(vpm);
14487
14672
  }
14488
14673
 
14489
14674
 
@@ -14495,7 +14680,7 @@ Image_virtual_pixel_method(VALUE self)
14495
14680
  *
14496
14681
  * @param self this object
14497
14682
  * @param method the VirtualPixelMethod
14498
- * @return self
14683
+ * @return method
14499
14684
  */
14500
14685
  VALUE
14501
14686
  Image_virtual_pixel_method_eq(VALUE self, VALUE method)
@@ -14507,7 +14692,7 @@ Image_virtual_pixel_method_eq(VALUE self, VALUE method)
14507
14692
  VALUE_TO_ENUM(method, vpm, VirtualPixelMethod);
14508
14693
  (void) SetImageVirtualPixelMethod(image, vpm);
14509
14694
  rm_check_image_exception(image, RetainOnError);
14510
- return self;
14695
+ return method;
14511
14696
  }
14512
14697
 
14513
14698
 
@@ -14796,10 +14981,10 @@ Image_wet_floor(int argc, VALUE *argv, VALUE self)
14796
14981
  * Call WhiteThresholdImage.
14797
14982
  *
14798
14983
  * Ruby usage:
14799
- * - @verbatim Image#white_threshold(red_channel) @endverbatim
14800
- * - @verbatim Image#white_threshold(red_channel, green_channel) @endverbatim
14801
- * - @verbatim Image#white_threshold(red_channel, green_channel, blue_channel) @endverbatim
14802
- * - @verbatim Image#white_threshold(red_channel, green_channel, blue_channel, opacity_channel) @endverbatim
14984
+ * - @verbatim Image#white_threshold(red) @endverbatim
14985
+ * - @verbatim Image#white_threshold(red, green) @endverbatim
14986
+ * - @verbatim Image#white_threshold(red, green, blue) @endverbatim
14987
+ * - @verbatim Image#white_threshold(red, green, blue, alpha: alpha) @endverbatim
14803
14988
  *
14804
14989
  * @param argc number of input arguments
14805
14990
  * @param argv array of input arguments
@@ -15197,11 +15382,15 @@ xform_image(int bang, VALUE self, VALUE x, VALUE y, VALUE width, VALUE height, x
15197
15382
  new_image = (xformer)(image, &rect, exception);
15198
15383
 
15199
15384
  // An exception can occur in either the old or the new images
15200
- rm_check_image_exception(image, RetainOnError);
15201
15385
  rm_check_exception(exception, new_image, DestroyOnError);
15202
-
15203
15386
  (void) DestroyExceptionInfo(exception);
15204
15387
 
15388
+ if (rm_should_raise_exception(&image->exception, RetainExceptionRetention))
15389
+ {
15390
+ (void) DestroyImage(new_image);
15391
+ rm_check_image_exception(image, RetainOnError);
15392
+ }
15393
+
15205
15394
  rm_ensure_result(new_image);
15206
15395
 
15207
15396
  if (bang)