rmagick 2.5.2 → 2.6.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 (52) hide show
  1. data/ChangeLog +29 -0
  2. data/README.html +7 -7
  3. data/doc/comtasks.html +2 -2
  4. data/doc/constants.html +22 -5
  5. data/doc/draw.html +2 -2
  6. data/doc/ex/affinity.rb +12 -0
  7. data/doc/ex/affinity_images.rb +21 -0
  8. data/doc/ex/composite_tiled.rb +23 -0
  9. data/doc/ex/images/Apple.miff +0 -0
  10. data/doc/ex/images/Leaf.miff +0 -0
  11. data/doc/ex/images/Rocks_On_Beach.miff +0 -0
  12. data/doc/ex/images/Yellow_Rose.miff +0 -0
  13. data/doc/ex/level_colors.rb +11 -0
  14. data/doc/ilist.html +72 -30
  15. data/doc/image1.html +305 -34
  16. data/doc/image2.html +144 -18
  17. data/doc/image3.html +111 -8
  18. data/doc/imageattrs.html +10 -2
  19. data/doc/imusage.html +5 -5
  20. data/doc/index.html +3 -3
  21. data/doc/info.html +2 -2
  22. data/doc/magick.html +2 -2
  23. data/doc/optequiv.html +54 -9
  24. data/doc/rvg.html +2 -2
  25. data/doc/rvgclip.html +2 -2
  26. data/doc/rvggroup.html +2 -2
  27. data/doc/rvgimage.html +2 -2
  28. data/doc/rvgpattern.html +2 -2
  29. data/doc/rvgshape.html +2 -2
  30. data/doc/rvgstyle.html +2 -2
  31. data/doc/rvgtext.html +2 -2
  32. data/doc/rvgtspan.html +2 -2
  33. data/doc/rvgtut.html +2 -2
  34. data/doc/rvguse.html +2 -2
  35. data/doc/rvgxform.html +2 -2
  36. data/doc/struct.html +2 -2
  37. data/doc/usage.html +27 -8
  38. data/ext/RMagick/MANIFEST +9 -3
  39. data/ext/RMagick/extconf.rb +19 -3
  40. data/ext/RMagick/rmagick.h +23 -7
  41. data/ext/RMagick/rmdraw.c +74 -22
  42. data/ext/RMagick/rmfill.c +2 -2
  43. data/ext/RMagick/rmilist.c +79 -29
  44. data/ext/RMagick/rmimage.c +904 -393
  45. data/ext/RMagick/rminfo.c +9 -9
  46. data/ext/RMagick/rmmain.c +64 -9
  47. data/ext/RMagick/rmutil.c +158 -44
  48. data/lib/RMagick.rb +32 -1
  49. data/rmagick.gemspec +1 -1
  50. metadata +10 -4
  51. data/doc/ex/map.rb +0 -28
  52. data/doc/ex/map_f.rb +0 -15
@@ -1,4 +1,4 @@
1
- /* $Id: rmfill.c,v 1.29 2008/05/28 22:40:15 rmagick Exp $ */
1
+ /* $Id: rmfill.c,v 1.30 2008/09/02 23:40:19 rmagick Exp $ */
2
2
  /*============================================================================\
3
3
  | Copyright (C) 2008 by Timothy P. Hunter
4
4
  | Name: rmfill.c
@@ -511,7 +511,7 @@ TextureFill_initialize(VALUE self, VALUE texture_arg)
511
511
 
512
512
  Data_Get_Struct(self, rm_TextureFill, fill);
513
513
 
514
- texture_image = ImageList_cur_image(texture_arg);
514
+ texture_image = rm_cur_image(texture_arg);
515
515
 
516
516
  // Bump the reference count on the texture image.
517
517
  texture = rm_check_destroyed(texture_image);
@@ -1,4 +1,4 @@
1
- /* $Id: rmilist.c,v 1.73 2008/07/13 14:31:37 rmagick Exp $ */
1
+ /* $Id: rmilist.c,v 1.84 2008/09/10 22:08:55 rmagick Exp $ */
2
2
  /*============================================================================\
3
3
  | Copyright (C) 2008 by Timothy P. Hunter
4
4
  | Name: rmilist.c
@@ -16,6 +16,54 @@ static void imagelist_push(VALUE, VALUE);
16
16
  static VALUE ImageList_new(void);
17
17
 
18
18
 
19
+
20
+ /*
21
+ Method: ImageList#affinity(affinity_image=nil, dither_method=RiemersmaDitherMethod)
22
+ Purpose: Call AffinityImages
23
+ Note: See Image_affinity. Immediate - modifies images in-place
24
+ */
25
+ VALUE
26
+ ImageList_affinity(int argc, VALUE *argv, VALUE self)
27
+ {
28
+ #if defined(HAVE_AFFINITYIMAGES)
29
+ Image *images, *affinity_image = NULL;
30
+ QuantizeInfo quantize_info;
31
+
32
+ images = images_from_imagelist(self);
33
+
34
+ if (argc > 0 && argv[0] != Qnil)
35
+ {
36
+ volatile VALUE t = rm_cur_image(argv[0]);
37
+ affinity_image = rm_check_destroyed(t);
38
+ }
39
+
40
+ GetQuantizeInfo(&quantize_info);
41
+
42
+ if (argc > 1)
43
+ {
44
+ VALUE_TO_ENUM(argv[1], quantize_info.dither_method, DitherMethod);
45
+ quantize_info.dither = MagickTrue;
46
+ }
47
+ if (argc > 2)
48
+ {
49
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
50
+ }
51
+
52
+ (void) AffinityImages(&quantize_info, images, affinity_image);
53
+ rm_check_image_exception(images, RetainOnError);
54
+ rm_split(images);
55
+
56
+ return self;
57
+ #else
58
+ self = self;
59
+ argc = argc;
60
+ argv = argv;
61
+ rm_not_implemented();
62
+ return(VALUE)0;
63
+ #endif
64
+ }
65
+
66
+
19
67
  /*
20
68
  Method: ImageList#animate(<delay>)
21
69
  Purpose: repeatedly display the images in the images array to an XWindow
@@ -62,6 +110,7 @@ ImageList_animate(int argc, VALUE *argv, VALUE self)
62
110
  return self;
63
111
  }
64
112
 
113
+
65
114
  /*
66
115
  Method: ImageList#append(stack)
67
116
  Purpose: Append all the images by calling ImageAppend
@@ -92,6 +141,7 @@ ImageList_append(VALUE self, VALUE stack_arg)
92
141
  return rm_image_new(new_image);
93
142
  }
94
143
 
144
+
95
145
  /*
96
146
  Method: ImageList#average
97
147
  Purpose: Average all images together by calling AverageImages
@@ -117,6 +167,7 @@ ImageList_average(VALUE self)
117
167
  return rm_image_new(new_image);
118
168
  }
119
169
 
170
+
120
171
  /*
121
172
  Method: ImageList#coalesce
122
173
  Purpose: call CoalesceImages
@@ -234,6 +285,7 @@ ImageList_deconstruct(VALUE self)
234
285
  return rm_imagelist_from_images(new_images);
235
286
  }
236
287
 
288
+
237
289
  /*
238
290
  Method: ImageList#display
239
291
  Purpose: Display all the images to an X window screen.
@@ -259,6 +311,7 @@ ImageList_display(VALUE self)
259
311
  return self;
260
312
  }
261
313
 
314
+
262
315
  /*
263
316
  Method: ImageList#flatten_images
264
317
  Purpose: merge all the images into a single image
@@ -329,7 +382,6 @@ ImageList_fx(int argc, VALUE *argv, VALUE self)
329
382
  }
330
383
 
331
384
 
332
-
333
385
  /*
334
386
  Method: ImageList#map(reference, dither=false)
335
387
  Purpose: Call MapImages
@@ -344,12 +396,16 @@ ImageList_map(int argc, VALUE *argv, VALUE self)
344
396
  volatile VALUE scene, new_imagelist, t;
345
397
  ExceptionInfo exception;
346
398
 
399
+ #if defined(HAVE_AFFINITYIMAGES)
400
+ rb_warning("ImageList#map is deprecated. Use ImageList#affinity instead.");
401
+ #endif
402
+
347
403
  switch (argc)
348
404
  {
349
405
  case 2:
350
406
  dither = RTEST(argv[1]);
351
407
  case 1:
352
- t = ImageList_cur_image(argv[0]);
408
+ t = rm_cur_image(argv[0]);
353
409
  map = rm_check_destroyed(t);
354
410
  break;
355
411
  default:
@@ -386,6 +442,7 @@ ImageList_map(int argc, VALUE *argv, VALUE self)
386
442
  return new_imagelist;
387
443
  }
388
444
 
445
+
389
446
  /*
390
447
  Method: ImageList#montage <{parm block}>
391
448
  Purpose: Call MontageImages
@@ -436,6 +493,7 @@ ImageList_montage(VALUE self)
436
493
  return rm_imagelist_from_images(new_images);
437
494
  }
438
495
 
496
+
439
497
  /*
440
498
  Method: ImageList#morph(number_images)
441
499
  Purpose: requires a minimum of two images. The first image is
@@ -475,6 +533,7 @@ ImageList_morph(VALUE self, VALUE nimages)
475
533
  return rm_imagelist_from_images(new_images);
476
534
  }
477
535
 
536
+
478
537
  /*
479
538
  Method: ImageList#mosaic
480
539
  Purpose: merge all the images into a single image
@@ -706,6 +765,7 @@ imagelist_scene_eq(VALUE imagelist, VALUE scene)
706
765
  return scene;
707
766
  }
708
767
 
768
+
709
769
  /*
710
770
  Static: imagelist_length
711
771
  Purpose: return the # of images in an imagelist
@@ -717,6 +777,7 @@ imagelist_length(VALUE imagelist)
717
777
  return RARRAY_LEN(images);
718
778
  }
719
779
 
780
+
720
781
  /*
721
782
  Static: imagelist_push
722
783
  Purpose: push an image onto the end of the imagelist
@@ -780,7 +841,15 @@ ImageList_quantize(int argc, VALUE *argv, VALUE self)
780
841
  case 4:
781
842
  quantize_info.tree_depth = (unsigned long)NUM2INT(argv[3]);
782
843
  case 3:
844
+ #if defined(HAVE_TYPE_DITHERMETHOD)
845
+ if (rb_obj_is_kind_of(argv[2], Class_DitherMethod))
846
+ {
847
+ VALUE_TO_ENUM(argv[2], quantize_info.dither_method, DitherMethod);
848
+ quantize_info.dither = quantize_info.dither_method != NoDitherMethod;
849
+ }
850
+ #else
783
851
  quantize_info.dither = (MagickBooleanType) RTEST(argv[2]);
852
+ #endif
784
853
  case 2:
785
854
  VALUE_TO_ENUM(argv[1], quantize_info.colorspace, ColorspaceType);
786
855
  case 1:
@@ -826,6 +895,7 @@ ImageList_quantize(int argc, VALUE *argv, VALUE self)
826
895
  return new_imagelist;
827
896
  }
828
897
 
898
+
829
899
  /*
830
900
  Method: ImageList#to_blob
831
901
  Purpose: returns the imagelist as a blob (a String)
@@ -867,9 +937,11 @@ ImageList_to_blob(VALUE self)
867
937
  // doesn't support multi-image files.
868
938
  info->adjoin = MagickTrue;
869
939
  blob = ImagesToBlob(info, images, &length, &exception);
870
- if (exception.severity != UndefinedException)
940
+ if (blob && exception.severity >= ErrorException)
871
941
  {
872
942
  magick_free((void*)blob);
943
+ blob = NULL;
944
+ length = 0;
873
945
  }
874
946
  rm_split(images);
875
947
  CHECK_EXCEPTION()
@@ -888,17 +960,6 @@ ImageList_to_blob(VALUE self)
888
960
  }
889
961
 
890
962
 
891
- /*
892
- * Static: file_arg_rescue
893
- * Purpose: called when `arg_to_str' raised an exception
894
- */
895
- static VALUE file_arg_rescue(VALUE arg)
896
- {
897
- rb_raise(rb_eTypeError, "argument must be path name or open file (%s given)",
898
- rb_class2name(CLASS_OF(arg)));
899
- }
900
-
901
-
902
963
  /*
903
964
  Method: ImageList#write(file)
904
965
  Purpose: Write all the images to the specified file. If the file format
@@ -914,8 +975,6 @@ ImageList_write(VALUE self, VALUE file)
914
975
  Info *info;
915
976
  const MagickInfo *m;
916
977
  volatile VALUE info_obj;
917
- char *filename;
918
- long filename_l;
919
978
  unsigned long scene;
920
979
  ExceptionInfo exception;
921
980
 
@@ -933,21 +992,14 @@ ImageList_write(VALUE self, VALUE file)
933
992
  }
934
993
  else
935
994
  {
936
- // Convert arg to string. Catch exceptions.
937
- file = rb_rescue(rb_String, file, file_arg_rescue, file);
938
-
939
- // Copy the filename to the Info and to the Image.
940
- filename = rm_str2cstr(file, &filename_l);
941
- filename_l = min(filename_l, MaxTextExtent-1);
942
- memcpy(info->filename, filename, (size_t)filename_l);
943
- info->filename[filename_l] = '\0';
995
+ add_format_prefix(info, file);
944
996
  SetImageInfoFile(info, NULL);
945
997
  }
946
998
 
947
999
  // Convert the images array to an images sequence.
948
1000
  images = images_from_imagelist(self);
949
1001
 
950
- // Copy the filename into each images. Set a scene number to be used if
1002
+ // Copy the filename into each image. Set a scene number to be used if
951
1003
  // writing multiple files. (Ref: ImageMagick's utilities/convert.c
952
1004
  for (scene = 0, img = images; img; img = GetNextImageInList(img))
953
1005
  {
@@ -955,13 +1007,11 @@ ImageList_write(VALUE self, VALUE file)
955
1007
  strcpy(img->filename, info->filename);
956
1008
  }
957
1009
 
1010
+ // Find out if the format supports multi-images files.
958
1011
  GetExceptionInfo(&exception);
959
1012
  (void) SetImageInfo(info, MagickTrue, &exception);
960
1013
  rm_check_exception(&exception, images, RetainOnError);
961
- (void) DestroyExceptionInfo(&exception);
962
1014
 
963
- // Find out if the format supports multi-images files.
964
- GetExceptionInfo(&exception);
965
1015
  m = GetMagickInfo(info->magick, &exception);
966
1016
  rm_check_exception(&exception, images, RetainOnError);
967
1017
  (void) DestroyExceptionInfo(&exception);
@@ -1,4 +1,4 @@
1
- /* $Id: rmimage.c,v 1.298 2008/07/13 21:18:28 rmagick Exp $ */
1
+ /* $Id: rmimage.c,v 1.319 2008/09/10 22:16:58 rmagick Exp $ */
2
2
  /*============================================================================\
3
3
  | Copyright (C) 2008 by Timothy P. Hunter
4
4
  | Name: rmimage.c
@@ -37,11 +37,9 @@ static const char *BlackPointCompensationKey = "PROFILE:black-point-compensation
37
37
  Static: adaptive_method
38
38
  Purpose: call Adaptive(Blur|Sharpen)Image
39
39
  */
40
- static VALUE adaptive_method(
41
- int argc,
42
- VALUE *argv,
43
- VALUE self,
44
- Image *fp(const Image *, const double, const double, ExceptionInfo *))
40
+ static VALUE
41
+ adaptive_method(int argc, VALUE *argv, VALUE self
42
+ , Image *fp(const Image *, const double, const double, ExceptionInfo *))
45
43
  {
46
44
  Image *image, *new_image;
47
45
  double radius = 0.0;
@@ -81,11 +79,9 @@ static VALUE adaptive_method(
81
79
  Static: adaptive_channel_method
82
80
  Purpose: call Adaptive(Blur|Sharpen)ImageChannel
83
81
  */
84
- static VALUE adaptive_channel_method(
85
- int argc,
86
- VALUE *argv,
87
- VALUE self,
88
- Image *fp(const Image *, const ChannelType, const double, const double, ExceptionInfo *))
82
+ static VALUE
83
+ adaptive_channel_method(int argc, VALUE *argv, VALUE self
84
+ , Image *fp(const Image *, const ChannelType, const double, const double, ExceptionInfo *))
89
85
  {
90
86
  Image *image, *new_image;
91
87
  double radius = 0.0;
@@ -434,7 +430,7 @@ Image_add_profile(VALUE self, VALUE name)
434
430
  if (profile)
435
431
  {
436
432
  (void)ProfileImage(image, profile_name, GetStringInfoDatum(profile)
437
- , GetStringInfoLength(profile), MagickFalse);
433
+ , GetStringInfoLength(profile), MagickFalse);
438
434
  if (image->exception.severity >= ErrorException)
439
435
  {
440
436
  break;
@@ -573,6 +569,56 @@ Image_alpha_eq(VALUE self, VALUE type)
573
569
  }
574
570
 
575
571
 
572
+
573
+ /*
574
+ Method: Image#affinity(affinity_image, dither_method=RiemersmaDitherMethod)
575
+ Purpose: Call AffinityImage
576
+ Notes: Immediate - modifies image in-place
577
+ */
578
+ VALUE
579
+ Image_affinity(int argc, VALUE *argv, VALUE self)
580
+ {
581
+ #if defined(HAVE_AFFINITYIMAGE)
582
+ Image *image, *affinity_image;
583
+ QuantizeInfo quantize_info;
584
+
585
+ image = rm_check_frozen(self);
586
+ if (argc > 0)
587
+ {
588
+ volatile VALUE t = rm_cur_image(argv[0]);
589
+ affinity_image = rm_check_destroyed(t);
590
+ }
591
+
592
+ GetQuantizeInfo(&quantize_info);
593
+
594
+ switch (argc)
595
+ {
596
+ case 2:
597
+ VALUE_TO_ENUM(argv[1], quantize_info.dither_method, DitherMethod);
598
+ quantize_info.dither = MagickTrue;
599
+ break;
600
+ case 1:
601
+ break;
602
+ default:
603
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
604
+ break;
605
+ }
606
+
607
+
608
+ (void) AffinityImage(&quantize_info, image, affinity_image);
609
+ rm_check_image_exception(image, RetainOnError);
610
+
611
+ return self;
612
+ #else
613
+ self = self;
614
+ argc = argc;
615
+ argv = argv;
616
+ rm_not_implemented();
617
+ return(VALUE)0;
618
+ #endif
619
+ }
620
+
621
+
576
622
  /*
577
623
  Method: Image#affine_transform(affine_matrix)
578
624
  Purpose: transforms an image as dictated by the affine matrix argument
@@ -718,10 +764,7 @@ Image_aset(VALUE self, VALUE key_arg, VALUE attr_arg)
718
764
  Purpose: Handle #transverse, #transform methods
719
765
  */
720
766
  static VALUE
721
- crisscross(
722
- int bang,
723
- VALUE self,
724
- Image *fp(const Image *, ExceptionInfo *))
767
+ crisscross(int bang, VALUE self, Image *fp(const Image *, ExceptionInfo *))
725
768
  {
726
769
  Image *image, *new_image;
727
770
  ExceptionInfo exception;
@@ -754,7 +797,8 @@ crisscross(
754
797
  automatically orient image based on EXIF orientation value
755
798
  Notes: See mogrify.c in ImageMagick 6.2.8.
756
799
  */
757
- static VALUE auto_orient(int bang, VALUE self)
800
+ static VALUE
801
+ auto_orient(int bang, VALUE self)
758
802
  {
759
803
  Image *image;
760
804
  volatile VALUE new_image;
@@ -815,6 +859,7 @@ Image_auto_orient(VALUE self)
815
859
  return auto_orient(False, self);
816
860
  }
817
861
 
862
+
818
863
  /*
819
864
  Returns nil if the image is already properly oriented
820
865
  */
@@ -855,7 +900,8 @@ Image_background_color_eq(VALUE self, VALUE color)
855
900
  Method: Image#base_columns
856
901
  Purpose: Return the number of rows (before transformations)
857
902
  */
858
- VALUE Image_base_columns(VALUE self)
903
+ VALUE
904
+ Image_base_columns(VALUE self)
859
905
  {
860
906
  Image *image = rm_check_destroyed(self);
861
907
  return INT2FIX(image->magick_columns);
@@ -866,7 +912,8 @@ VALUE Image_base_columns(VALUE self)
866
912
  Purpose: Return the image filename (before transformations)
867
913
  Notes: If there is no base filename, return the current filename.
868
914
  */
869
- VALUE Image_base_filename(VALUE self)
915
+ VALUE
916
+ Image_base_filename(VALUE self)
870
917
  {
871
918
  Image *image = rm_check_destroyed(self);
872
919
  if (*image->magick_filename)
@@ -883,7 +930,8 @@ VALUE Image_base_filename(VALUE self)
883
930
  Method: Image#base_rows
884
931
  Purpose: Return the number of rows (before transformations)
885
932
  */
886
- VALUE Image_base_rows(VALUE self)
933
+ VALUE
934
+ Image_base_rows(VALUE self)
887
935
  {
888
936
  Image *image = rm_check_destroyed(self);
889
937
  return INT2FIX(image->magick_rows);
@@ -895,14 +943,16 @@ VALUE Image_base_rows(VALUE self)
895
943
  Image#bias = a number between 0.0 and 1.0 or "NN%"
896
944
  Purpose: Get/set image bias (used when convolving an image)
897
945
  */
898
- VALUE Image_bias(VALUE self)
946
+ VALUE
947
+ Image_bias(VALUE self)
899
948
  {
900
949
  Image *image = rm_check_destroyed(self);
901
950
  return rb_float_new(image->bias);
902
951
  }
903
952
 
904
953
 
905
- VALUE Image_bias_eq(VALUE self, VALUE pct)
954
+ VALUE
955
+ Image_bias_eq(VALUE self, VALUE pct)
906
956
  {
907
957
  Image *image;
908
958
  double bias;
@@ -1008,12 +1058,7 @@ Image_black_threshold(int argc, VALUE *argv, VALUE self)
1008
1058
  offsets are relative to
1009
1059
  */
1010
1060
  static void
1011
- get_relative_offsets(
1012
- VALUE grav,
1013
- Image *image,
1014
- Image *mark,
1015
- long *x_offset,
1016
- long *y_offset)
1061
+ get_relative_offsets(VALUE grav, Image *image, Image *mark, long *x_offset, long *y_offset)
1017
1062
  {
1018
1063
  MagickEnum *m_enum;
1019
1064
  GravityType gravity;
@@ -1067,12 +1112,8 @@ get_relative_offsets(
1067
1112
  Purpose: compute watermark offsets from gravity type
1068
1113
  */
1069
1114
  static void
1070
- get_offsets_from_gravity(
1071
- GravityType gravity,
1072
- Image *image,
1073
- Image *mark,
1074
- long *x_offset,
1075
- long *y_offset)
1115
+ get_offsets_from_gravity(GravityType gravity, Image *image, Image *mark
1116
+ , long *x_offset, long *y_offset)
1076
1117
  {
1077
1118
 
1078
1119
  switch (gravity)
@@ -1125,7 +1166,8 @@ get_offsets_from_gravity(
1125
1166
  Purpose: called from rb_protect, returns the number if obj is really
1126
1167
  a numeric value.
1127
1168
  */
1128
- static VALUE check_for_long_value(VALUE obj)
1169
+ static VALUE
1170
+ check_for_long_value(VALUE obj)
1129
1171
  {
1130
1172
  long t;
1131
1173
  t = NUM2LONG(obj);
@@ -1138,13 +1180,9 @@ static VALUE check_for_long_value(VALUE obj)
1138
1180
  Static: get_composite_offsets
1139
1181
  Purpose: compute x- and y-offset of source image for a compositing method
1140
1182
  */
1141
- static void get_composite_offsets(
1142
- int argc,
1143
- VALUE *argv,
1144
- Image *dest,
1145
- Image *src,
1146
- long *x_offset,
1147
- long *y_offset)
1183
+ static void
1184
+ get_composite_offsets(int argc, VALUE *argv, Image *dest, Image *src
1185
+ , long *x_offset, long *y_offset)
1148
1186
  {
1149
1187
  GravityType gravity;
1150
1188
  int exc = 0;
@@ -1199,11 +1237,7 @@ static void get_composite_offsets(
1199
1237
  is far in excess of what xMagick will allow.
1200
1238
  */
1201
1239
  static void
1202
- blend_geometry(
1203
- char *geometry,
1204
- size_t geometry_l,
1205
- double src_percent,
1206
- double dst_percent)
1240
+ blend_geometry(char *geometry, size_t geometry_l, double src_percent, double dst_percent)
1207
1241
  {
1208
1242
  size_t sz = 0;
1209
1243
  int fw, prec;
@@ -1259,14 +1293,8 @@ blend_geometry(
1259
1293
 
1260
1294
 
1261
1295
  static VALUE
1262
- special_composite(
1263
- Image *image,
1264
- Image *overlay,
1265
- double image_pct,
1266
- double overlay_pct,
1267
- long x_off,
1268
- long y_off,
1269
- CompositeOperator op)
1296
+ special_composite(Image *image, Image *overlay, double image_pct, double overlay_pct
1297
+ , long x_off, long y_off, CompositeOperator op)
1270
1298
  {
1271
1299
  Image *new_image;
1272
1300
  char geometry[20];
@@ -1305,7 +1333,7 @@ Image_blend(int argc, VALUE *argv, VALUE self)
1305
1333
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 to 6)", argc);
1306
1334
  }
1307
1335
 
1308
- ovly = ImageList_cur_image(argv[0]);
1336
+ ovly = rm_cur_image(argv[0]);
1309
1337
  overlay = rm_check_destroyed(ovly);
1310
1338
 
1311
1339
  if (argc > 3)
@@ -1398,12 +1426,8 @@ Image_blur_image(int argc, VALUE *argv, VALUE self)
1398
1426
  Purpose: surrounds the image with a border of the specified width,
1399
1427
  height, and named color
1400
1428
  */
1401
- static VALUE border(
1402
- int bang,
1403
- VALUE self,
1404
- VALUE width,
1405
- VALUE height,
1406
- VALUE color)
1429
+ static VALUE
1430
+ border(int bang, VALUE self, VALUE width, VALUE height, VALUE color)
1407
1431
  {
1408
1432
  Image *image, *new_image;
1409
1433
  PixelPacket old_border;
@@ -1441,11 +1465,7 @@ static VALUE border(
1441
1465
  }
1442
1466
 
1443
1467
  VALUE
1444
- Image_border_bang(
1445
- VALUE self,
1446
- VALUE width,
1447
- VALUE height,
1448
- VALUE color)
1468
+ Image_border_bang(VALUE self, VALUE width, VALUE height, VALUE color)
1449
1469
  {
1450
1470
  (void) rm_check_frozen(self);
1451
1471
  return border(True, self, width, height, color);
@@ -1453,11 +1473,7 @@ Image_border_bang(
1453
1473
 
1454
1474
 
1455
1475
  VALUE
1456
- Image_border(
1457
- VALUE self,
1458
- VALUE width,
1459
- VALUE height,
1460
- VALUE color)
1476
+ Image_border(VALUE self, VALUE width, VALUE height, VALUE color)
1461
1477
  {
1462
1478
  (void) rm_check_destroyed(self);
1463
1479
  return border(False, self, width, height, color);
@@ -1475,6 +1491,7 @@ Image_border_color(VALUE self)
1475
1491
  return PixelPacket_to_Color_Name(image, &image->border_color);
1476
1492
  }
1477
1493
 
1494
+
1478
1495
  /*
1479
1496
  Method: Image#border_color=
1480
1497
  Purpose: Set the the border color
@@ -1492,7 +1509,8 @@ Image_border_color_eq(VALUE self, VALUE color)
1492
1509
  Method: Image#bounding_box
1493
1510
  Purpose: returns the bounding box of an image canvas
1494
1511
  */
1495
- VALUE Image_bounding_box(VALUE self)
1512
+ VALUE
1513
+ Image_bounding_box(VALUE self)
1496
1514
  {
1497
1515
  Image *image;
1498
1516
  RectangleInfo box;
@@ -1518,10 +1536,7 @@ VALUE Image_bounding_box(VALUE self)
1518
1536
  Purpose: do a screen capture
1519
1537
  */
1520
1538
  VALUE
1521
- Image_capture(
1522
- int argc,
1523
- VALUE *argv,
1524
- VALUE self)
1539
+ Image_capture(int argc, VALUE *argv, VALUE self)
1525
1540
  {
1526
1541
  Image *image;
1527
1542
  ImageInfo *image_info;
@@ -1582,7 +1597,7 @@ Image_change_geometry(VALUE self, VALUE geom_arg)
1582
1597
  volatile VALUE ary;
1583
1598
 
1584
1599
  image = rm_check_destroyed(self);
1585
- geom_str = rb_funcall(geom_arg, rm_ID_to_s, 0);
1600
+ geom_str = rm_to_s(geom_arg);
1586
1601
  geometry = StringValuePtr(geom_str);
1587
1602
 
1588
1603
  memset(&rect, 0, sizeof(rect));
@@ -1785,17 +1800,13 @@ Image_check_destroyed(VALUE self)
1785
1800
  the removed portion
1786
1801
  */
1787
1802
  VALUE
1788
- Image_chop(
1789
- VALUE self,
1790
- VALUE x,
1791
- VALUE y,
1792
- VALUE width,
1793
- VALUE height)
1803
+ Image_chop(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height)
1794
1804
  {
1795
1805
  (void) rm_check_destroyed(self);
1796
1806
  return xform_image(False, self, x, y, width, height, ChopImage);
1797
1807
  }
1798
1808
 
1809
+
1799
1810
  /*
1800
1811
  Method: Image#chromaticity
1801
1812
  Purpose: Return the red, green, blue, and white-point chromaticity
@@ -1808,6 +1819,7 @@ Image_chromaticity(VALUE self)
1808
1819
  return ChromaticityInfo_new(&image->chromaticity);
1809
1820
  }
1810
1821
 
1822
+
1811
1823
  /*
1812
1824
  Method: Image#chromaticity=
1813
1825
  Purpose: Set the red, green, blue, and white-point chromaticity
@@ -1840,11 +1852,11 @@ Image_clone(VALUE self)
1840
1852
  return clone;
1841
1853
  }
1842
1854
 
1855
+
1843
1856
  /*
1844
1857
  Method: Image#clut_channel
1845
1858
  Purpose: Equivalent to -clut option.
1846
1859
  */
1847
-
1848
1860
  VALUE
1849
1861
  Image_clut_channel(int argc, VALUE *argv, VALUE self)
1850
1862
  {
@@ -1891,6 +1903,7 @@ Image_clut_channel(int argc, VALUE *argv, VALUE self)
1891
1903
  #endif
1892
1904
  }
1893
1905
 
1906
+
1894
1907
  /*
1895
1908
  Method: Image_color_histogram(VALUE self);
1896
1909
  Purpose: Call GetImageHistogram
@@ -1959,14 +1972,14 @@ Image_color_histogram(VALUE self)
1959
1972
  }
1960
1973
 
1961
1974
 
1962
-
1963
1975
  /*
1964
1976
  Static: set_profile(target_image, name, profile_image)
1965
1977
  Purpose: The `profile_image' argument is an IPTC or ICC profile. Store
1966
1978
  all the profiles in the profile in the target image.
1967
1979
  Called from Image_color_profile_eq and Image_iptc_profile_eq
1968
1980
  */
1969
- static VALUE set_profile(VALUE self, const char *name, VALUE profile)
1981
+ static VALUE
1982
+ set_profile(VALUE self, const char *name, VALUE profile)
1970
1983
  {
1971
1984
  Image *image, *profile_image;
1972
1985
  ImageInfo *info;
@@ -2051,6 +2064,7 @@ Image_color_profile(VALUE self)
2051
2064
 
2052
2065
  }
2053
2066
 
2067
+
2054
2068
  /*
2055
2069
  Method: Image#color_profile=(String)
2056
2070
  Purpose: Set the ICC color profile. The argument is a string.
@@ -2068,6 +2082,7 @@ Image_color_profile_eq(VALUE self, VALUE profile)
2068
2082
  return self;
2069
2083
  }
2070
2084
 
2085
+
2071
2086
  /*
2072
2087
  Method: Image#color_flood_fill(target_color, fill_color, x, y, method)
2073
2088
  Purpose: changes the color value of any pixel that matches target_color
@@ -2076,13 +2091,8 @@ Image_color_profile_eq(VALUE self, VALUE profile)
2076
2091
  Accepts either the FloodfillMethod or the FillToBorderMethod
2077
2092
  */
2078
2093
  VALUE
2079
- Image_color_flood_fill(
2080
- VALUE self,
2081
- VALUE target_color,
2082
- VALUE fill_color,
2083
- VALUE xv,
2084
- VALUE yv,
2085
- VALUE method)
2094
+ Image_color_flood_fill( VALUE self, VALUE target_color, VALUE fill_color
2095
+ , VALUE xv, VALUE yv, VALUE method)
2086
2096
  {
2087
2097
  Image *image, *new_image;
2088
2098
  PixelPacket target;
@@ -2124,26 +2134,26 @@ Image_color_flood_fill(
2124
2134
 
2125
2135
  #if defined(HAVE_FLOODFILLPAINTIMAGE)
2126
2136
  {
2127
- MagickPixelPacket target_mpp;
2128
- MagickBooleanType invert;
2137
+ MagickPixelPacket target_mpp;
2138
+ MagickBooleanType invert;
2129
2139
 
2130
- GetMagickPixelPacket(new_image, &target_mpp);
2131
- if (fill_method == FillToBorderMethod)
2132
- {
2133
- invert = MagickTrue;
2134
- target_mpp.red = (MagickRealType) image->border_color.red;
2135
- target_mpp.green = (MagickRealType) image->border_color.green;
2136
- target_mpp.blue = (MagickRealType) image->border_color.blue;
2137
- }
2138
- else
2139
- {
2140
- invert = MagickFalse;
2141
- target_mpp.red = (MagickRealType) target.red;
2142
- target_mpp.green = (MagickRealType) target.green;
2143
- target_mpp.blue = (MagickRealType) target.blue;
2144
- }
2140
+ GetMagickPixelPacket(new_image, &target_mpp);
2141
+ if (fill_method == FillToBorderMethod)
2142
+ {
2143
+ invert = MagickTrue;
2144
+ target_mpp.red = (MagickRealType) image->border_color.red;
2145
+ target_mpp.green = (MagickRealType) image->border_color.green;
2146
+ target_mpp.blue = (MagickRealType) image->border_color.blue;
2147
+ }
2148
+ else
2149
+ {
2150
+ invert = MagickFalse;
2151
+ target_mpp.red = (MagickRealType) target.red;
2152
+ target_mpp.green = (MagickRealType) target.green;
2153
+ target_mpp.blue = (MagickRealType) target.blue;
2154
+ }
2145
2155
 
2146
- (void) FloodfillPaintImage(new_image, DefaultChannels, draw_info, &target_mpp, x, y, invert);
2156
+ (void) FloodfillPaintImage(new_image, DefaultChannels, draw_info, &target_mpp, x, y, invert);
2147
2157
  }
2148
2158
  #else
2149
2159
  (void) ColorFloodfillImage(new_image, draw_info, target, x, y, (PaintMethod)fill_method);
@@ -2154,6 +2164,7 @@ Image_color_flood_fill(
2154
2164
  return rm_image_new(new_image);
2155
2165
  }
2156
2166
 
2167
+
2157
2168
  /*
2158
2169
  Method: Image#colorize(r, g, b, target)
2159
2170
  Purpose: blends the fill color specified by "target" with each pixel in
@@ -2161,10 +2172,7 @@ Image_color_flood_fill(
2161
2172
  component.
2162
2173
  */
2163
2174
  VALUE
2164
- Image_colorize(
2165
- int argc,
2166
- VALUE *argv,
2167
- VALUE self)
2175
+ Image_colorize(int argc, VALUE *argv, VALUE self)
2168
2176
  {
2169
2177
  Image *image, *new_image;
2170
2178
  double red, green, blue, matte;
@@ -2313,6 +2321,7 @@ Image_colorspace(VALUE self)
2313
2321
  return ColorspaceType_new(image->colorspace);
2314
2322
  }
2315
2323
 
2324
+
2316
2325
  /*
2317
2326
  Method: Image#colorspace=Magick::ColorspaceType
2318
2327
  Purpose: Set the image's colorspace
@@ -2406,7 +2415,7 @@ VALUE Image_combine(int argc, VALUE *argv, VALUE self)
2406
2415
 
2407
2416
 
2408
2417
  /*
2409
- Method: Image#compare_channel(ref_image, metric [, channel...])
2418
+ Method: Image#compare_channel(ref_image, metric [, channel...]) { optional arguments }
2410
2419
  Purpose: compares one or more channels in two images and returns
2411
2420
  the specified distortion metric and a comparison image.
2412
2421
  Notes: If no channels are specified, the default is AllChannels.
@@ -2419,11 +2428,14 @@ VALUE Image_combine(int argc, VALUE *argv, VALUE self)
2419
2428
  arguments have names that end in _channel. So I renamed
2420
2429
  the method to compare_channel but kept channel_compare as
2421
2430
  an alias.
2431
+
2432
+ The optional arguments are specified thusly:
2433
+ self.highlight_color color
2434
+ self.lowlight-color color
2435
+ where color is either a color name or a Pixel.
2422
2436
  */
2423
- VALUE Image_compare_channel(
2424
- int argc,
2425
- VALUE *argv,
2426
- VALUE self)
2437
+ VALUE
2438
+ Image_compare_channel(int argc, VALUE *argv, VALUE self)
2427
2439
  {
2428
2440
  Image *image, *r_image, *difference_image;
2429
2441
  double distortion;
@@ -2445,7 +2457,9 @@ VALUE Image_compare_channel(
2445
2457
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or more)", argc);
2446
2458
  }
2447
2459
 
2448
- ref = ImageList_cur_image(argv[0]);
2460
+ rm_get_optional_arguments(self);
2461
+
2462
+ ref = rm_cur_image(argv[0]);
2449
2463
  r_image = rm_check_destroyed(ref);
2450
2464
 
2451
2465
  VALUE_TO_ENUM(argv[1], metric_type, MetricType);
@@ -2475,7 +2489,8 @@ VALUE Image_compare_channel(
2475
2489
  Method: Image#compose -> composite_op
2476
2490
  Purpose: Return the composite operator attribute
2477
2491
  */
2478
- VALUE Image_compose(VALUE self)
2492
+ VALUE
2493
+ Image_compose(VALUE self)
2479
2494
  {
2480
2495
  Image *image = rm_check_destroyed(self);
2481
2496
  return CompositeOperator_new(image->compose);
@@ -2486,9 +2501,8 @@ VALUE Image_compose(VALUE self)
2486
2501
  Method: Image#compose=composite_op
2487
2502
  Purpose: Set the composite operator attribute
2488
2503
  */
2489
- VALUE Image_compose_eq(
2490
- VALUE self,
2491
- VALUE compose_arg)
2504
+ VALUE
2505
+ Image_compose_eq(VALUE self, VALUE compose_arg)
2492
2506
  {
2493
2507
  Image *image = rm_check_frozen(self);
2494
2508
  VALUE_TO_ENUM(compose_arg, image->compose, CompositeOperator);
@@ -2508,12 +2522,8 @@ VALUE Image_compose_eq(
2508
2522
  Returns: new composited image, or nil
2509
2523
  */
2510
2524
 
2511
- static VALUE composite(
2512
- int bang,
2513
- int argc,
2514
- VALUE *argv,
2515
- VALUE self,
2516
- ChannelType channels)
2525
+ static VALUE
2526
+ composite(int bang, int argc, VALUE *argv, VALUE self, ChannelType channels)
2517
2527
  {
2518
2528
  Image *image, *new_image;
2519
2529
  Image *comp_image;
@@ -2536,7 +2546,7 @@ static VALUE composite(
2536
2546
  }
2537
2547
 
2538
2548
 
2539
- comp = ImageList_cur_image(argv[0]);
2549
+ comp = rm_cur_image(argv[0]);
2540
2550
  comp_image = rm_check_destroyed(comp);
2541
2551
 
2542
2552
  switch (argc)
@@ -2664,19 +2674,15 @@ static VALUE composite(
2664
2674
  }
2665
2675
 
2666
2676
 
2667
- VALUE Image_composite_bang(
2668
- int argc,
2669
- VALUE *argv,
2670
- VALUE self)
2677
+ VALUE
2678
+ Image_composite_bang(int argc, VALUE *argv, VALUE self)
2671
2679
  {
2672
2680
  return composite(True, argc, argv, self, DefaultChannels);
2673
2681
  }
2674
2682
 
2675
2683
 
2676
- VALUE Image_composite(
2677
- int argc,
2678
- VALUE *argv,
2679
- VALUE self)
2684
+ VALUE
2685
+ Image_composite(int argc, VALUE *argv, VALUE self)
2680
2686
  {
2681
2687
  return composite(False, argc, argv, self, DefaultChannels);
2682
2688
  }
@@ -2688,10 +2694,7 @@ VALUE Image_composite(
2688
2694
  dictated by the affine transform.
2689
2695
  */
2690
2696
  VALUE
2691
- Image_composite_affine(
2692
- VALUE self,
2693
- VALUE source,
2694
- VALUE affine_matrix)
2697
+ Image_composite_affine(VALUE self, VALUE source, VALUE affine_matrix)
2695
2698
  {
2696
2699
  Image *image, *composite_image, *new_image;
2697
2700
  AffineMatrix affine;
@@ -2736,18 +2739,110 @@ composite_channel(int bang, int argc, VALUE *argv, VALUE self)
2736
2739
  }
2737
2740
 
2738
2741
 
2739
- VALUE Image_composite_channel(int argc, VALUE *argv, VALUE self)
2742
+ VALUE
2743
+ Image_composite_channel(int argc, VALUE *argv, VALUE self)
2740
2744
  {
2741
2745
  return composite_channel(False, argc, argv, self);
2742
2746
  }
2743
2747
 
2744
2748
 
2745
- VALUE Image_composite_channel_bang(int argc, VALUE *argv, VALUE self)
2749
+ VALUE
2750
+ Image_composite_channel_bang(int argc, VALUE *argv, VALUE self)
2746
2751
  {
2747
2752
  return composite_channel(True, argc, argv, self);
2748
2753
  }
2749
2754
 
2750
2755
 
2756
+ /*
2757
+ Method: Image#composite_tiled(src [, composite_op = Magick::OverCompositeOp][, channel...])
2758
+ Purpose: Emulate the -tile option to the composite command.
2759
+ Returns: new image
2760
+ Notes: Ref: wand/composite.c (6.2.4)
2761
+ */
2762
+ static VALUE
2763
+ composite_tiled(int bang, int argc, VALUE *argv, VALUE self)
2764
+ {
2765
+ Image *image;
2766
+ Image *comp_image;
2767
+ CompositeOperator operator = OverCompositeOp;
2768
+ long x, y;
2769
+ unsigned long columns;
2770
+ ChannelType channels;
2771
+ MagickStatusType status;
2772
+
2773
+ // Ensure image and composite_image aren't destroyed.
2774
+ if (bang)
2775
+ {
2776
+ image = rm_check_frozen(self);
2777
+ }
2778
+ else
2779
+ {
2780
+ image = rm_check_destroyed(self);
2781
+ }
2782
+
2783
+ if (argc > 0)
2784
+ {
2785
+ comp_image = rm_check_destroyed(rm_cur_image(argv[0]));
2786
+ }
2787
+
2788
+ channels = extract_channels(&argc, argv);
2789
+
2790
+ switch (argc)
2791
+ {
2792
+ case 2:
2793
+ VALUE_TO_ENUM(argv[1], operator, CompositeOperator);
2794
+ case 1:
2795
+ break;
2796
+ case 0:
2797
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1 or more)");
2798
+ break;
2799
+ default:
2800
+ raise_ChannelType_error(argv[argc-1]);
2801
+ break;
2802
+ }
2803
+
2804
+ if (!bang)
2805
+ {
2806
+ image = rm_clone_image(image);
2807
+ }
2808
+
2809
+ #if defined(HAVE_SETIMAGEARTIFACT)
2810
+ (void) SetImageArtifact(comp_image,"modify-outside-overlay", "false");
2811
+ #else
2812
+ (void) SetImageAttribute(comp_image, "[modify-outside-overlay]", "false");
2813
+ #endif
2814
+
2815
+ status = MagickTrue;
2816
+ columns = comp_image->columns;
2817
+
2818
+ // Tile
2819
+ for (y = 0; y < (long) image->rows; y += comp_image->rows)
2820
+ {
2821
+ for (x = 0; status == MagickTrue && x < (long) image->columns; x += columns)
2822
+ {
2823
+ status = CompositeImageChannel(image, channels, operator, comp_image, x, y);
2824
+ rm_check_image_exception(image, bang ? RetainOnError: DestroyOnError);
2825
+ }
2826
+ }
2827
+
2828
+ return bang ? self : rm_image_new(image);
2829
+ }
2830
+
2831
+
2832
+ VALUE
2833
+ Image_composite_tiled(int argc, VALUE *argv, VALUE self)
2834
+ {
2835
+ return composite_tiled(False, argc, argv, self);
2836
+ }
2837
+
2838
+
2839
+ VALUE
2840
+ Image_composite_tiled_bang(int argc, VALUE *argv, VALUE self)
2841
+ {
2842
+ return composite_tiled(True, argc, argv, self);
2843
+ }
2844
+
2845
+
2751
2846
  /*
2752
2847
  Method: Image#compression
2753
2848
  Image#compression=
@@ -2952,12 +3047,8 @@ Image_contrast(int argc, VALUE *argv, VALUE self)
2952
3047
  Purpose: Convert percentages to #pixels. If the white-point (2nd)
2953
3048
  argument is not supplied set it to #pixels - black-point.
2954
3049
  */
2955
- static void get_black_white_point(
2956
- Image *image,
2957
- int argc,
2958
- VALUE *argv,
2959
- double *black_point,
2960
- double *white_point)
3050
+ static void
3051
+ get_black_white_point(Image *image, int argc, VALUE *argv, double *black_point, double *white_point)
2961
3052
  {
2962
3053
  double pixels;
2963
3054
 
@@ -3043,10 +3134,7 @@ Image_contrast_stretch_channel(int argc, VALUE *argv, VALUE self)
3043
3134
  "kernel" is an order**2 array of doubles
3044
3135
  */
3045
3136
  VALUE
3046
- Image_convolve(
3047
- VALUE self,
3048
- VALUE order_arg,
3049
- VALUE kernel_arg)
3137
+ Image_convolve(VALUE self, VALUE order_arg, VALUE kernel_arg)
3050
3138
  {
3051
3139
  Image *image, *new_image;
3052
3140
  double *kernel;
@@ -3087,10 +3175,7 @@ Image_convolve(
3087
3175
  * Purpose: call ConvolveImageChannel
3088
3176
  */
3089
3177
  VALUE
3090
- Image_convolve_channel(
3091
- int argc,
3092
- VALUE *argv,
3093
- VALUE self)
3178
+ Image_convolve_channel(int argc, VALUE *argv, VALUE self)
3094
3179
  {
3095
3180
  Image *image, *new_image;
3096
3181
  double *kernel;
@@ -3182,6 +3267,7 @@ Image_crop(int argc, VALUE *argv, VALUE self)
3182
3267
  return cropper(False, argc, argv, self);
3183
3268
  }
3184
3269
 
3270
+
3185
3271
  VALUE
3186
3272
  Image_crop_bang(int argc, VALUE *argv, VALUE self)
3187
3273
  {
@@ -3189,6 +3275,7 @@ Image_crop_bang(int argc, VALUE *argv, VALUE self)
3189
3275
  return cropper(True, argc, argv, self);
3190
3276
  }
3191
3277
 
3278
+
3192
3279
  /*
3193
3280
  Method: Image#cycle_colormap
3194
3281
  Purpose: Call CycleColormapImage
@@ -3209,6 +3296,7 @@ Image_cycle_colormap(VALUE self, VALUE amount)
3209
3296
  return rm_image_new(new_image);
3210
3297
  }
3211
3298
 
3299
+
3212
3300
  /*
3213
3301
  Method: Image#density
3214
3302
  Purpose: Get the x & y resolutions.
@@ -3226,6 +3314,7 @@ Image_density(VALUE self)
3226
3314
  return rb_str_new2(density);
3227
3315
  }
3228
3316
 
3317
+
3229
3318
  /*
3230
3319
  Method: Image#density="XxY"
3231
3320
  Image#density=aGeometry
@@ -3293,31 +3382,6 @@ Image_density_eq(VALUE self, VALUE density_arg)
3293
3382
  return self;
3294
3383
  }
3295
3384
 
3296
- /*
3297
- Method: Image#depth
3298
- Purpose: Return the image depth (8 or 16).
3299
- Note: If all pixels have lower-order bytes equal to higher-order
3300
- bytes, the depth will be reported as 8 even if the depth
3301
- field in the Image structure says 16.
3302
- */
3303
- VALUE
3304
- Image_depth(VALUE self)
3305
- {
3306
- Image *image;
3307
- unsigned long depth = 0;
3308
- ExceptionInfo exception;
3309
-
3310
- image = rm_check_destroyed(self);
3311
- GetExceptionInfo(&exception);
3312
-
3313
- depth = GetImageDepth(image, &exception);
3314
- CHECK_EXCEPTION()
3315
-
3316
- (void) DestroyExceptionInfo(&exception);
3317
-
3318
- return INT2FIX(depth);
3319
- }
3320
-
3321
3385
 
3322
3386
  /*
3323
3387
  Method: Image#decipher(passphrase)
@@ -3353,7 +3417,52 @@ Image_decipher(VALUE self, VALUE passphrase)
3353
3417
  self = self;
3354
3418
  passphrase = passphrase;
3355
3419
  rm_not_implemented();
3356
- return (VALUE)0;
3420
+ return(VALUE)0;
3421
+ #endif
3422
+ }
3423
+
3424
+
3425
+ /*
3426
+ Method: value = Image#define(artifact, value)
3427
+ Purpose: Call SetImageArtifact
3428
+ Note: Normally a script should never call this method. Any calls
3429
+ to SetImageArtifact will be part of the methods in which they're
3430
+ needed, or be called via the OptionalMethodArguments class.
3431
+ */
3432
+ VALUE
3433
+ Image_define(VALUE self, VALUE artifact, VALUE value)
3434
+ {
3435
+ #if defined(HAVE_SETIMAGEARTIFACT)
3436
+ Image *image;
3437
+ char *key, *val;
3438
+ MagickBooleanType status;
3439
+
3440
+ image = rm_check_frozen(self);
3441
+ artifact = rb_String(artifact);
3442
+ key = StringValuePtr(artifact);
3443
+
3444
+ if (value == Qnil)
3445
+ {
3446
+ (void) DeleteImageArtifact(image, key);
3447
+ }
3448
+ else
3449
+ {
3450
+ value = rb_String(value);
3451
+ val = StringValuePtr(value);
3452
+ status = SetImageArtifact(image, key, val);
3453
+ if (!status)
3454
+ {
3455
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
3456
+ }
3457
+ }
3458
+
3459
+ return value;
3460
+ #else
3461
+ rm_not_implemented();
3462
+ artifact = artifact;
3463
+ value = value;
3464
+ self = self;
3465
+ return(VALUE)0;
3357
3466
  #endif
3358
3467
  }
3359
3468
 
@@ -3376,8 +3485,8 @@ Image_delete_compose_mask(VALUE self)
3376
3485
  // Store a clone of the mask image
3377
3486
  #if defined(HAVE_SETIMAGEMASK)
3378
3487
  {
3379
- (void) SetImageMask(image, NULL);
3380
- rm_check_image_exception(image, RetainOnError);
3488
+ (void) SetImageMask(image, NULL);
3489
+ rm_check_image_exception(image, RetainOnError);
3381
3490
  }
3382
3491
  #else
3383
3492
  if (image->clip_mask)
@@ -3407,6 +3516,82 @@ Image_delete_profile(VALUE self, VALUE name)
3407
3516
  }
3408
3517
 
3409
3518
 
3519
+ /*
3520
+ Method: Image#depth
3521
+ Purpose: Return the image depth (8 or 16).
3522
+ Note: If all pixels have lower-order bytes equal to higher-order
3523
+ bytes, the depth will be reported as 8 even if the depth
3524
+ field in the Image structure says 16.
3525
+ */
3526
+ VALUE
3527
+ Image_depth(VALUE self)
3528
+ {
3529
+ Image *image;
3530
+ unsigned long depth = 0;
3531
+ ExceptionInfo exception;
3532
+
3533
+ image = rm_check_destroyed(self);
3534
+ GetExceptionInfo(&exception);
3535
+
3536
+ depth = GetImageDepth(image, &exception);
3537
+ CHECK_EXCEPTION()
3538
+
3539
+ (void) DestroyExceptionInfo(&exception);
3540
+
3541
+ return INT2FIX(depth);
3542
+ }
3543
+
3544
+
3545
+ /*
3546
+ Method: Image#deskew(threshold=0.40, auto-crop-width)
3547
+ Purpose: Implement convert -deskew option
3548
+ */
3549
+ VALUE
3550
+ Image_deskew(int argc, VALUE *argv, VALUE self)
3551
+ {
3552
+ #if defined(HAVE_DESKEWIMAGE)
3553
+ Image *image, *new_image;
3554
+ double threshold = 40.0 * QuantumRange / 100.0;
3555
+ unsigned long width;
3556
+ char auto_crop_width[20];
3557
+ ExceptionInfo exception;
3558
+
3559
+ image = rm_check_destroyed(self);
3560
+
3561
+ switch (argc)
3562
+ {
3563
+ case 2:
3564
+ width = NUM2ULONG(argv[1]);
3565
+ memset(auto_crop_width, 0, sizeof(auto_crop_width));
3566
+ sprintf(auto_crop_width, "%ld", width);
3567
+ SetImageArtifact(image, "deskew:auto-crop", auto_crop_width);
3568
+ case 1:
3569
+ threshold = rm_percentage(argv[0]) * QuantumRange;
3570
+ case 0:
3571
+ break;
3572
+ default:
3573
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
3574
+ break;
3575
+ }
3576
+
3577
+ GetExceptionInfo(&exception);
3578
+ new_image = DeskewImage(image, threshold, &exception);
3579
+ CHECK_EXCEPTION()
3580
+ rm_ensure_result(new_image);
3581
+
3582
+ (void) DestroyExceptionInfo(&exception);
3583
+
3584
+ return rm_image_new(new_image);
3585
+ #else
3586
+ self = self; // defeat "unused parameter" message
3587
+ argv = argv;
3588
+ argc = argc;
3589
+ rm_not_implemented();
3590
+ return(VALUE)0;
3591
+ #endif
3592
+ }
3593
+
3594
+
3410
3595
  /*
3411
3596
  Method: Image#despeckle
3412
3597
  Purpose: reduces the speckle noise in an image while preserving the
@@ -3437,7 +3622,8 @@ Image_despeckle(VALUE self)
3437
3622
  Method: Image#destroy!
3438
3623
  Purpose: Free all the memory associated with an image
3439
3624
  */
3440
- VALUE Image_destroy_bang(VALUE self)
3625
+ VALUE
3626
+ Image_destroy_bang(VALUE self)
3441
3627
  {
3442
3628
  Image *image;
3443
3629
 
@@ -3453,7 +3639,8 @@ VALUE Image_destroy_bang(VALUE self)
3453
3639
  Method: Image#destroyed?
3454
3640
  Purpose: Returns true if the image has been destroyed, false otherwise
3455
3641
  */
3456
- VALUE Image_destroyed_q(VALUE self)
3642
+ VALUE
3643
+ Image_destroyed_q(VALUE self)
3457
3644
  {
3458
3645
  Image *image;
3459
3646
 
@@ -3471,14 +3658,15 @@ VALUE Image_destroyed_q(VALUE self)
3471
3658
  [2] normalized maximum error
3472
3659
  Notes: "other" can be either an Image or an Image
3473
3660
  */
3474
- VALUE Image_difference(VALUE self, VALUE other)
3661
+ VALUE
3662
+ Image_difference(VALUE self, VALUE other)
3475
3663
  {
3476
3664
  Image *image;
3477
3665
  Image *image2;
3478
3666
  volatile VALUE mean, nmean, nmax;
3479
3667
 
3480
3668
  image = rm_check_destroyed(self);
3481
- other = ImageList_cur_image(other);
3669
+ other = rm_cur_image(other);
3482
3670
  image2 = rm_check_destroyed(other);
3483
3671
 
3484
3672
  (void) IsImagesEqual(image, image2);
@@ -3515,7 +3703,7 @@ Image_displace(int argc, VALUE *argv, VALUE self)
3515
3703
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 to 6)", argc);
3516
3704
  }
3517
3705
 
3518
- dmap = ImageList_cur_image(argv[0]);
3706
+ dmap = rm_cur_image(argv[0]);
3519
3707
  displacement_map = rm_check_destroyed(dmap);
3520
3708
 
3521
3709
  if (argc > 3)
@@ -3636,11 +3824,13 @@ Image_dispatch(int argc, VALUE *argv, VALUE self)
3636
3824
  return pixels_ary;
3637
3825
  }
3638
3826
 
3827
+
3639
3828
  /*
3640
3829
  Method: Image#display
3641
3830
  Purpose: display the image to an X window screen
3642
3831
  */
3643
- VALUE Image_display(VALUE self)
3832
+ VALUE
3833
+ Image_display(VALUE self)
3644
3834
  {
3645
3835
  Image *image;
3646
3836
  Info *info;
@@ -3662,6 +3852,7 @@ VALUE Image_display(VALUE self)
3662
3852
  return self;
3663
3853
  }
3664
3854
 
3855
+
3665
3856
  /*
3666
3857
  Method: Image#dispose
3667
3858
  Purpose: Return the dispose attribute as a DisposeType enum
@@ -3673,6 +3864,7 @@ Image_dispose(VALUE self)
3673
3864
  return DisposeType_new(image->dispose);
3674
3865
  }
3675
3866
 
3867
+
3676
3868
  /*
3677
3869
  Method: Image#dispose=
3678
3870
  Purpose: Set the dispose attribute
@@ -3709,7 +3901,7 @@ Image_dissolve(int argc, VALUE *argv, VALUE self)
3709
3901
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 to 6)", argc);
3710
3902
  }
3711
3903
 
3712
- ovly = ImageList_cur_image(argv[0]);
3904
+ ovly = rm_cur_image(argv[0]);
3713
3905
  overlay = rm_check_destroyed(ovly);
3714
3906
 
3715
3907
  if (argc > 3)
@@ -3732,17 +3924,23 @@ Image_dissolve(int argc, VALUE *argv, VALUE self)
3732
3924
  }
3733
3925
 
3734
3926
  composite_image = special_composite(image, overlay, src_percent, dst_percent
3735
- , x_offset, y_offset, DissolveCompositeOp);
3927
+ , x_offset, y_offset, DissolveCompositeOp);
3736
3928
 
3737
3929
  return composite_image;
3738
3930
  }
3739
3931
 
3740
3932
 
3741
3933
  /*
3742
- * Method: Image#distort(type, points, bestfit=false)
3934
+ * Method: Image#distort(type, points, bestfit=false) { optional arguments }
3743
3935
  * Purpose: Call DistortImage
3744
3936
  * Notes: points is an Array of Numeric values
3937
+ * optional arguments are
3938
+ * self.define "distort:viewport", WxH+X+Y
3939
+ * self.define "distort:scale", N
3940
+ * self.verbose true
3745
3941
  */
3942
+
3943
+
3746
3944
  VALUE
3747
3945
  Image_distort(int argc, VALUE *argv, VALUE self)
3748
3946
  {
@@ -3756,6 +3954,7 @@ Image_distort(int argc, VALUE *argv, VALUE self)
3756
3954
  ExceptionInfo exception;
3757
3955
 
3758
3956
  image = rm_check_destroyed(self);
3957
+ rm_get_optional_arguments(self);
3759
3958
 
3760
3959
  switch (argc)
3761
3960
  {
@@ -3824,7 +4023,7 @@ Image_distortion_channel(int argc, VALUE *argv, VALUE self)
3824
4023
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or more)", argc);
3825
4024
  }
3826
4025
 
3827
- rec = ImageList_cur_image(argv[0]);
4026
+ rec = rm_cur_image(argv[0]);
3828
4027
  reconstruct = rm_check_destroyed(rec);
3829
4028
  VALUE_TO_ENUM(argv[1], metric, MetricType);
3830
4029
  GetExceptionInfo(&exception);
@@ -3837,6 +4036,7 @@ Image_distortion_channel(int argc, VALUE *argv, VALUE self)
3837
4036
  return rb_float_new(distortion);
3838
4037
  }
3839
4038
 
4039
+
3840
4040
  /*
3841
4041
  Method: Image#_dump(aDepth)
3842
4042
  Purpose: implement marshalling
@@ -3896,6 +4096,7 @@ Image__dump(VALUE self, VALUE depth)
3896
4096
  return rb_str_cat(str, (char *)blob, (long)length);
3897
4097
  }
3898
4098
 
4099
+
3899
4100
  /*
3900
4101
  Method: Image#dup
3901
4102
  Purpose: Construct a new image object and call initialize_copy
@@ -3914,6 +4115,7 @@ Image_dup(VALUE self)
3914
4115
  return rb_funcall(dup, rm_ID_initialize_copy, 1, self);
3915
4116
  }
3916
4117
 
4118
+
3917
4119
  /*
3918
4120
  Method: Image#each_profile
3919
4121
  Purpose: Iterate over image profiles
@@ -3953,6 +4155,7 @@ Image_each_profile(VALUE self)
3953
4155
  return val;
3954
4156
  }
3955
4157
 
4158
+
3956
4159
  /*
3957
4160
  Method: Image#edge(radius=0)
3958
4161
  Purpose: finds edges in an image. "radius" defines the radius of the
@@ -3991,16 +4194,13 @@ Image_edge(int argc, VALUE *argv, VALUE self)
3991
4194
  return rm_image_new(new_image);
3992
4195
  }
3993
4196
 
4197
+
3994
4198
  /*
3995
4199
  Static: effect_image
3996
4200
  Purpose: call one of the effects methods
3997
4201
  */
3998
4202
  static VALUE
3999
- effect_image(
4000
- VALUE self,
4001
- int argc,
4002
- VALUE *argv,
4003
- effector_t effector)
4203
+ effect_image(VALUE self, int argc, VALUE *argv, effector_t effector)
4004
4204
  {
4005
4205
  Image *image, *new_image;
4006
4206
  ExceptionInfo exception;
@@ -4037,6 +4237,7 @@ effect_image(
4037
4237
  return rm_image_new(new_image);
4038
4238
  }
4039
4239
 
4240
+
4040
4241
  /*
4041
4242
  Method: Image#emboss(radius=0.0, sigma=1.0)
4042
4243
  Purpose: creates a grayscale image with a three-dimensional effect
@@ -4082,7 +4283,7 @@ Image_encipher(VALUE self, VALUE passphrase)
4082
4283
  self = self;
4083
4284
  passphrase = passphrase;
4084
4285
  rm_not_implemented();
4085
- return (VALUE)0;
4286
+ return(VALUE)0;
4086
4287
  #endif
4087
4288
  }
4088
4289
 
@@ -4135,6 +4336,7 @@ Image_enhance(VALUE self)
4135
4336
  return rm_image_new(new_image);
4136
4337
  }
4137
4338
 
4339
+
4138
4340
  /*
4139
4341
  Method: Image#equalize
4140
4342
  Purpose: applies a histogram equalization to the image
@@ -4157,6 +4359,7 @@ Image_equalize(VALUE self)
4157
4359
  return rm_image_new(new_image);
4158
4360
  }
4159
4361
 
4362
+
4160
4363
  /*
4161
4364
  Method: Image#equalize_channel
4162
4365
  Purpose: call EqualizeImageChannel
@@ -4191,10 +4394,11 @@ Image_equalize_channel(int argc, VALUE *argv, VALUE self)
4191
4394
  argv = argv;
4192
4395
  self = self;
4193
4396
  rm_not_implemented();
4194
- return (VALUE) 0;
4397
+ return(VALUE) 0;
4195
4398
  #endif
4196
4399
  }
4197
4400
 
4401
+
4198
4402
  /*
4199
4403
  Method: Image#erase!
4200
4404
  Purpose: reset the image to the background color
@@ -4212,6 +4416,7 @@ Image_erase_bang(VALUE self)
4212
4416
  return self;
4213
4417
  }
4214
4418
 
4419
+
4215
4420
  /*
4216
4421
  Method: Image#excerpt(x, y, width, height)
4217
4422
  Purpose: lightweight crop
@@ -4258,6 +4463,7 @@ excerpt(int bang, VALUE self, VALUE x, VALUE y, VALUE width, VALUE height)
4258
4463
  #endif
4259
4464
  }
4260
4465
 
4466
+
4261
4467
  VALUE
4262
4468
  Image_excerpt(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height)
4263
4469
  {
@@ -4265,6 +4471,7 @@ Image_excerpt(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height)
4265
4471
  return excerpt(False, self, x, y, width, height);
4266
4472
  }
4267
4473
 
4474
+
4268
4475
  VALUE
4269
4476
  Image_excerpt_bang(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height)
4270
4477
  {
@@ -4272,6 +4479,7 @@ Image_excerpt_bang(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height)
4272
4479
  return excerpt(True, self, x, y, width, height);
4273
4480
  }
4274
4481
 
4482
+
4275
4483
  /*
4276
4484
  Method: Image#export_pixels(x=0, y=0, cols=self.columns, rows=self.rows, map="RGB")
4277
4485
  Purpose: extract image pixels in the form of an array
@@ -4527,6 +4735,7 @@ Image_export_pixels_to_str(int argc, VALUE *argv, VALUE self)
4527
4735
  return string;
4528
4736
  }
4529
4737
 
4738
+
4530
4739
  /*
4531
4740
  Method: Image#extract_info, extract_info=
4532
4741
  Purpose: the extract_info attribute accessors
@@ -4538,6 +4747,7 @@ Image_extract_info(VALUE self)
4538
4747
  return Rectangle_from_RectangleInfo(&image->extract_info);
4539
4748
  }
4540
4749
 
4750
+
4541
4751
  VALUE
4542
4752
  Image_extract_info_eq(VALUE self, VALUE rect)
4543
4753
  {
@@ -4572,6 +4782,7 @@ Image_filter(VALUE self)
4572
4782
  return FilterTypes_new(image->filter);
4573
4783
  }
4574
4784
 
4785
+
4575
4786
  VALUE
4576
4787
  Image_filter_eq(VALUE self, VALUE filter)
4577
4788
  {
@@ -4604,7 +4815,7 @@ Image_find_similar_region(int argc, VALUE *argv, VALUE self)
4604
4815
  case 2:
4605
4816
  x = NUM2LONG(argv[1]);
4606
4817
  case 1:
4607
- targ = ImageList_cur_image(argv[0]);
4818
+ targ = rm_cur_image(argv[0]);
4608
4819
  target = rm_check_destroyed(targ);
4609
4820
  break;
4610
4821
  default:
@@ -4665,6 +4876,7 @@ flipflop(int bang, VALUE self, flipper_t flipflopper)
4665
4876
  return rm_image_new(new_image);
4666
4877
  }
4667
4878
 
4879
+
4668
4880
  VALUE
4669
4881
  Image_flip(VALUE self)
4670
4882
  {
@@ -4672,6 +4884,7 @@ Image_flip(VALUE self)
4672
4884
  return flipflop(False, self, FlipImage);
4673
4885
  }
4674
4886
 
4887
+
4675
4888
  VALUE
4676
4889
  Image_flip_bang(VALUE self)
4677
4890
  {
@@ -4679,6 +4892,7 @@ Image_flip_bang(VALUE self)
4679
4892
  return flipflop(True, self, FlipImage);
4680
4893
  }
4681
4894
 
4895
+
4682
4896
  /*
4683
4897
  Method: Image#flop
4684
4898
  Image#flop!
@@ -4694,6 +4908,7 @@ Image_flop(VALUE self)
4694
4908
  return flipflop(False, self, FlopImage);
4695
4909
  }
4696
4910
 
4911
+
4697
4912
  VALUE
4698
4913
  Image_flop_bang(VALUE self)
4699
4914
  {
@@ -4840,6 +5055,7 @@ Image_frame(int argc, VALUE *argv, VALUE self)
4840
5055
  return rm_image_new(new_image);
4841
5056
  }
4842
5057
 
5058
+
4843
5059
  /*
4844
5060
  Method: Image.from_blob(blob) <{ parm block }>
4845
5061
  Purpose: Call BlobToImage
@@ -4875,14 +5091,17 @@ Image_from_blob(VALUE class, VALUE blob_arg)
4875
5091
  return array_from_images(images);
4876
5092
  }
4877
5093
 
5094
+
4878
5095
  DEF_ATTR_READER(Image, fuzz, dbl)
4879
5096
 
5097
+
4880
5098
  /*
4881
5099
  Method: Image#fuzz=number
4882
5100
  Image#fuzz=NN%
4883
5101
  Notes: See Info#fuzz.
4884
5102
  */
4885
- VALUE Image_fuzz_eq(VALUE self, VALUE fuzz)
5103
+ VALUE
5104
+ Image_fuzz_eq(VALUE self, VALUE fuzz)
4886
5105
  {
4887
5106
  Image *image = rm_check_frozen(self);
4888
5107
  image->fuzz = rm_fuzz_to_dbl(fuzz);
@@ -4979,6 +5198,7 @@ Image_gamma_correct(int argc, VALUE *argv, VALUE self)
4979
5198
  return rm_image_new(new_image);
4980
5199
  }
4981
5200
 
5201
+
4982
5202
  /*
4983
5203
  Method: Image#gaussian_blur(radius, sigma)
4984
5204
  Purpose: blur the image
@@ -5037,6 +5257,7 @@ Image_gaussian_blur_channel(int argc, VALUE *argv, VALUE self)
5037
5257
  */
5038
5258
  DEF_ATTR_READER(Image, geometry, str)
5039
5259
 
5260
+
5040
5261
  VALUE
5041
5262
  Image_geometry_eq(
5042
5263
  VALUE self,
@@ -5056,7 +5277,7 @@ Image_geometry_eq(
5056
5277
  }
5057
5278
 
5058
5279
 
5059
- geom_str = rb_funcall(geometry, rm_ID_to_s, 0);
5280
+ geom_str = rm_to_s(geometry);
5060
5281
  geom = StringValuePtr(geom_str);
5061
5282
  if (!IsGeometry(geom))
5062
5283
  {
@@ -5078,12 +5299,7 @@ Image_geometry_eq(
5078
5299
  store_pixels calls GetImagePixels, then SyncImage
5079
5300
  */
5080
5301
  VALUE
5081
- Image_get_pixels(
5082
- VALUE self,
5083
- VALUE x_arg,
5084
- VALUE y_arg,
5085
- VALUE cols_arg,
5086
- VALUE rows_arg)
5302
+ Image_get_pixels(VALUE self, VALUE x_arg, VALUE y_arg, VALUE cols_arg, VALUE rows_arg)
5087
5303
  {
5088
5304
  Image *image;
5089
5305
  const PixelPacket *pixels;
@@ -5133,7 +5349,8 @@ Image_get_pixels(
5133
5349
  }
5134
5350
 
5135
5351
 
5136
- static VALUE has_attribute(VALUE self, MagickBooleanType (attr_test)(const Image *, ExceptionInfo *))
5352
+ static VALUE
5353
+ has_attribute(VALUE self, MagickBooleanType (attr_test)(const Image *, ExceptionInfo *))
5137
5354
  {
5138
5355
  Image *image;
5139
5356
  ExceptionInfo exception;
@@ -5377,6 +5594,7 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
5377
5594
  return self;
5378
5595
  }
5379
5596
 
5597
+
5380
5598
  /*
5381
5599
  Method: Image#inspect
5382
5600
  Purpose: Overrides Object#inspect - returns a string description of the
@@ -5385,7 +5603,8 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
5385
5603
  Notes: this is essentially the IdentifyImage except the description is
5386
5604
  built in a char buffer instead of being written to a file.
5387
5605
  */
5388
- static void build_inspect_string(Image *image, char *buffer, size_t len)
5606
+ static void
5607
+ build_inspect_string(Image *image, char *buffer, size_t len)
5389
5608
  {
5390
5609
  unsigned long quantum_depth;
5391
5610
  int x = 0; // # bytes used in buffer
@@ -5578,6 +5797,7 @@ Image_iptc_profile_eq(VALUE self, VALUE profile)
5578
5797
  return self;
5579
5798
  }
5580
5799
 
5800
+
5581
5801
  /*
5582
5802
  These are undocumented methods. The writer is
5583
5803
  called only by Image#iterations=.
@@ -5629,6 +5849,7 @@ Image_level2(int argc, VALUE *argv, VALUE self)
5629
5849
  return rm_image_new(new_image);
5630
5850
  }
5631
5851
 
5852
+
5632
5853
  /*
5633
5854
  Method: Image#level_channel(aChannelType, black=0, white=QuantumRange, gamma=1.0)
5634
5855
  Purpose: similar to Image#level but applies to a single channel only
@@ -5654,26 +5875,163 @@ Image_level_channel(int argc, VALUE *argv, VALUE self)
5654
5875
  black_point = NUM2DBL(argv[1]);
5655
5876
  white_point = NUM2DBL(argv[2]);
5656
5877
  break;
5657
- case 4:
5658
- black_point = NUM2DBL(argv[1]);
5659
- white_point = NUM2DBL(argv[2]);
5660
- gamma_val = NUM2DBL(argv[3]);
5878
+ case 4:
5879
+ black_point = NUM2DBL(argv[1]);
5880
+ white_point = NUM2DBL(argv[2]);
5881
+ gamma_val = NUM2DBL(argv[3]);
5882
+ break;
5883
+ default:
5884
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 to 4)", argc);
5885
+ break;
5886
+ }
5887
+
5888
+ VALUE_TO_ENUM(argv[0], channel, ChannelType);
5889
+
5890
+ new_image = rm_clone_image(image);
5891
+
5892
+ (void) LevelImageChannel(new_image, channel, black_point, white_point, gamma_val);
5893
+ rm_check_image_exception(new_image, DestroyOnError);
5894
+
5895
+ return rm_image_new(new_image);
5896
+ }
5897
+
5898
+
5899
+ /*
5900
+ Method: Image#level_colors(black_color="black", white_color="white", invert=true [, channel...])
5901
+ Purpose: Implement +level_colors blank_color,white_color
5902
+ */
5903
+ VALUE
5904
+ Image_level_colors(int argc, VALUE *argv, VALUE self)
5905
+ {
5906
+ #if defined(HAVE_LEVELIMAGECOLORS)
5907
+ Image *image, *new_image;
5908
+ MagickPixelPacket black_color, white_color;
5909
+ ChannelType channels;
5910
+ ExceptionInfo exception;
5911
+ MagickBooleanType invert = MagickTrue;
5912
+ MagickBooleanType status;
5913
+
5914
+ image = rm_check_destroyed(self);
5915
+
5916
+ channels = extract_channels(&argc, argv);
5917
+
5918
+ switch (argc)
5919
+ {
5920
+ case 3:
5921
+ invert = RTEST(argv[2]);
5922
+
5923
+ case 2:
5924
+ Color_to_MagickPixelPacket(image, &white_color, argv[1]);
5925
+ Color_to_MagickPixelPacket(image, &black_color, argv[0]);
5926
+ break;
5927
+
5928
+ case 1:
5929
+ Color_to_MagickPixelPacket(image, &black_color, argv[0]);
5930
+ GetExceptionInfo(&exception);
5931
+
5932
+ GetMagickPixelPacket(image, &white_color);
5933
+ (void) QueryMagickColor("white", &white_color, &exception);
5934
+ CHECK_EXCEPTION()
5935
+
5936
+ DestroyExceptionInfo(&exception);
5937
+
5938
+ case 0:
5939
+ GetExceptionInfo(&exception);
5940
+
5941
+ GetMagickPixelPacket(image, &white_color);
5942
+ (void) QueryMagickColor("white", &white_color, &exception);
5943
+ CHECK_EXCEPTION()
5944
+
5945
+ GetMagickPixelPacket(image, &black_color);
5946
+ (void) QueryMagickColor("black", &black_color, &exception);
5947
+ CHECK_EXCEPTION()
5948
+
5949
+ DestroyExceptionInfo(&exception);
5950
+ break;
5951
+
5952
+ default:
5953
+ raise_ChannelType_error(argv[argc-1]);
5954
+ break;
5955
+ }
5956
+
5957
+ new_image = rm_clone_image(image);
5958
+
5959
+ status = LevelImageColors(new_image, channels, &black_color, &white_color, invert);
5960
+ rm_check_image_exception(new_image, DestroyOnError);
5961
+ if (!status)
5962
+ {
5963
+ rb_raise(rb_eRuntimeError, "LevelImageColors failed for unknown reason.");
5964
+ }
5965
+
5966
+ return rm_image_new(new_image);
5967
+
5968
+ #else
5969
+ rm_not_implemented();
5970
+ self = self;
5971
+ argc = argc;
5972
+ argv = argv;
5973
+ return(VALUE)0;
5974
+ #endif
5975
+ }
5976
+
5977
+
5978
+
5979
+ /*
5980
+ Method: Image#levelize_channel(black_point[, white_point[, gamma=1.0[, channel...]])
5981
+ */
5982
+ VALUE
5983
+ Image_levelize_channel(int argc, VALUE *argv, VALUE self)
5984
+ {
5985
+ #if defined(HAVE_LEVELIZEIMAGECHANNEL)
5986
+ Image *image, *new_image;
5987
+ ChannelType channels;
5988
+ double black_point, white_point;
5989
+ double gamma = 1.0;
5990
+ MagickBooleanType status;
5991
+
5992
+ image = rm_check_destroyed(self);
5993
+ channels = extract_channels(&argc, argv);
5994
+ if (argc > 3)
5995
+ {
5996
+ raise_ChannelType_error(argv[argc-1]);
5997
+ }
5998
+
5999
+ switch (argc)
6000
+ {
6001
+ case 3:
6002
+ gamma = NUM2DBL(argv[2]);
6003
+ case 2:
6004
+ white_point = NUM2DBL(argv[1]);
6005
+ black_point = NUM2DBL(argv[0]);
6006
+ break;
6007
+ case 1:
6008
+ black_point = NUM2DBL(argv[0]);
6009
+ white_point = QuantumRange - black_point;
5661
6010
  break;
5662
6011
  default:
5663
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 to 4)", argc);
6012
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or more)", argc);
5664
6013
  break;
5665
6014
  }
5666
6015
 
5667
- VALUE_TO_ENUM(argv[0], channel, ChannelType);
5668
-
5669
6016
  new_image = rm_clone_image(image);
6017
+ status = LevelizeImageChannel(new_image, channels, black_point, white_point, gamma);
5670
6018
 
5671
- (void) LevelImageChannel(new_image, channel, black_point, white_point, gamma_val);
5672
6019
  rm_check_image_exception(new_image, DestroyOnError);
5673
-
6020
+ if (!status)
6021
+ {
6022
+ rb_raise(rb_eRuntimeError, "LevelizeImageChannel failed for unknown reason.");
6023
+ }
5674
6024
  return rm_image_new(new_image);
6025
+ #else
6026
+ rm_not_implemented();
6027
+ self = self;
6028
+ argc = argc;
6029
+ argv = argv;
6030
+ return(VALUE)0;
6031
+ #endif
5675
6032
  }
5676
6033
 
6034
+
5677
6035
  /*
5678
6036
  Method: Image_linear_stretch(black_point <, white_point>)
5679
6037
  Purpose: Call LinearStretchImage
@@ -5752,6 +6110,7 @@ Image_liquid_rescale(int argc, VALUE *argv, VALUE self)
5752
6110
  #endif
5753
6111
  }
5754
6112
 
6113
+
5755
6114
  /*
5756
6115
  Method: Image._load
5757
6116
  Purpose: implement marshalling
@@ -5860,6 +6219,7 @@ magnify(int bang, VALUE self, magnifier_t magnifier)
5860
6219
  return rm_image_new(new_image);
5861
6220
  }
5862
6221
 
6222
+
5863
6223
  VALUE
5864
6224
  Image_magnify(VALUE self)
5865
6225
  {
@@ -5867,6 +6227,7 @@ Image_magnify(VALUE self)
5867
6227
  return magnify(False, self, MagnifyImage);
5868
6228
  }
5869
6229
 
6230
+
5870
6231
  VALUE
5871
6232
  Image_magnify_bang(VALUE self)
5872
6233
  {
@@ -5874,12 +6235,12 @@ Image_magnify_bang(VALUE self)
5874
6235
  return magnify(True, self, MagnifyImage);
5875
6236
  }
5876
6237
 
6238
+
5877
6239
  /*
5878
6240
  Method: Image#map(map_image, dither=false)
5879
6241
  Purpose: Call MapImage
5880
6242
  Returns: a new image
5881
6243
  */
5882
-
5883
6244
  VALUE
5884
6245
  Image_map(int argc, VALUE *argv, VALUE self)
5885
6246
  {
@@ -5889,6 +6250,11 @@ Image_map(int argc, VALUE *argv, VALUE self)
5889
6250
  unsigned int dither = MagickFalse;
5890
6251
 
5891
6252
  image = rm_check_destroyed(self);
6253
+
6254
+ #if defined(HAVE_AFFINITYIMAGE)
6255
+ rb_warning("Image#map is deprecated. Use Image#affinity instead");
6256
+ #endif
6257
+
5892
6258
  switch (argc)
5893
6259
  {
5894
6260
  case 2:
@@ -5903,7 +6269,7 @@ Image_map(int argc, VALUE *argv, VALUE self)
5903
6269
 
5904
6270
  new_image = rm_clone_image(image);
5905
6271
 
5906
- map_obj = ImageList_cur_image(map_arg);
6272
+ map_obj = rm_cur_image(map_arg);
5907
6273
  map = rm_check_destroyed(map_obj);
5908
6274
  (void) MapImage(new_image, map, dither);
5909
6275
  rm_check_image_exception(new_image, DestroyOnError);
@@ -5984,7 +6350,7 @@ Image_mask(int argc, VALUE *argv, VALUE self)
5984
6350
 
5985
6351
  if (mask != Qnil)
5986
6352
  {
5987
- mask = ImageList_cur_image(mask);
6353
+ mask = rm_cur_image(mask);
5988
6354
  mask_image = rm_check_destroyed(mask);
5989
6355
  clip_mask = rm_clone_image(mask_image);
5990
6356
 
@@ -6118,18 +6484,13 @@ Image_matte_color_eq(VALUE self, VALUE color)
6118
6484
  return self;
6119
6485
  }
6120
6486
 
6487
+
6121
6488
  /*
6122
6489
  Method: Image#matte_flood_fill(color, opacity, x, y, method_obj)
6123
6490
  Purpose: Call MatteFloodFillImage
6124
6491
  */
6125
6492
  VALUE
6126
- Image_matte_flood_fill(
6127
- VALUE self,
6128
- VALUE color,
6129
- VALUE opacity,
6130
- VALUE x_obj,
6131
- VALUE y_obj,
6132
- VALUE method_obj)
6493
+ Image_matte_flood_fill(VALUE self, VALUE color, VALUE opacity, VALUE x_obj, VALUE y_obj, VALUE method_obj)
6133
6494
  {
6134
6495
  Image *image, *new_image;
6135
6496
  PixelPacket target;
@@ -6161,34 +6522,34 @@ Image_matte_flood_fill(
6161
6522
 
6162
6523
  #if defined(HAVE_FLOODFILLPAINTIMAGE)
6163
6524
  {
6164
- DrawInfo *draw_info;
6165
- MagickPixelPacket target_mpp;
6166
- MagickBooleanType invert;
6525
+ DrawInfo *draw_info;
6526
+ MagickPixelPacket target_mpp;
6527
+ MagickBooleanType invert;
6167
6528
 
6168
- // FloodfillPaintImage looks for the opacity in the DrawInfo.fill field.
6169
- draw_info = CloneDrawInfo(NULL, NULL);
6170
- if (!draw_info)
6171
- {
6172
- rb_raise(rb_eNoMemError, "not enough memory to continue");
6173
- }
6174
- draw_info->fill.opacity = op;
6529
+ // FloodfillPaintImage looks for the opacity in the DrawInfo.fill field.
6530
+ draw_info = CloneDrawInfo(NULL, NULL);
6531
+ if (!draw_info)
6532
+ {
6533
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
6534
+ }
6535
+ draw_info->fill.opacity = op;
6175
6536
 
6176
- if (method == FillToBorderMethod)
6177
- {
6178
- invert = MagickTrue;
6179
- target_mpp.red = (MagickRealType) image->border_color.red;
6180
- target_mpp.green = (MagickRealType) image->border_color.green;
6181
- target_mpp.blue = (MagickRealType) image->border_color.blue;
6182
- }
6183
- else
6184
- {
6185
- invert = MagickFalse;
6186
- target_mpp.red = (MagickRealType) target.red;
6187
- target_mpp.green = (MagickRealType) target.green;
6188
- target_mpp.blue = (MagickRealType) target.blue;
6189
- }
6537
+ if (method == FillToBorderMethod)
6538
+ {
6539
+ invert = MagickTrue;
6540
+ target_mpp.red = (MagickRealType) image->border_color.red;
6541
+ target_mpp.green = (MagickRealType) image->border_color.green;
6542
+ target_mpp.blue = (MagickRealType) image->border_color.blue;
6543
+ }
6544
+ else
6545
+ {
6546
+ invert = MagickFalse;
6547
+ target_mpp.red = (MagickRealType) target.red;
6548
+ target_mpp.green = (MagickRealType) target.green;
6549
+ target_mpp.blue = (MagickRealType) target.blue;
6550
+ }
6190
6551
 
6191
- (void) FloodfillPaintImage(new_image, OpacityChannel, draw_info, &target_mpp, x, y, invert);
6552
+ (void) FloodfillPaintImage(new_image, OpacityChannel, draw_info, &target_mpp, x, y, invert);
6192
6553
  }
6193
6554
  #else
6194
6555
  (void) MatteFloodfillImage(new_image, target, op, x, y, method);
@@ -6198,6 +6559,7 @@ Image_matte_flood_fill(
6198
6559
  return rm_image_new(new_image);
6199
6560
  }
6200
6561
 
6562
+
6201
6563
  /*
6202
6564
  Method: Image#median_filter(radius=0.0)
6203
6565
  Purpose: applies a digital filter that improves the quality of a noisy
@@ -6236,8 +6598,10 @@ Image_median_filter(int argc, VALUE *argv, VALUE self)
6236
6598
  return rm_image_new(new_image);
6237
6599
  }
6238
6600
 
6601
+
6239
6602
  DEF_ATTR_READERF(Image, mean_error_per_pixel, error.mean_error_per_pixel, dbl)
6240
6603
 
6604
+
6241
6605
  /*
6242
6606
  Method: Image#mime_type
6243
6607
  Purpose: Return the officially registered (or de facto) MIME media-type
@@ -6264,6 +6628,7 @@ Image_mime_type(VALUE self)
6264
6628
  return mime_type;
6265
6629
  }
6266
6630
 
6631
+
6267
6632
  /*
6268
6633
  Method: Image#minify
6269
6634
  Image#minify!
@@ -6278,6 +6643,7 @@ Image_minify(VALUE self)
6278
6643
  return magnify(False, self, MinifyImage);
6279
6644
  }
6280
6645
 
6646
+
6281
6647
  VALUE
6282
6648
  Image_minify_bang(VALUE self)
6283
6649
  {
@@ -6285,6 +6651,7 @@ Image_minify_bang(VALUE self)
6285
6651
  return magnify(True, self, MinifyImage);
6286
6652
  }
6287
6653
 
6654
+
6288
6655
  /*
6289
6656
  Method: Image#modulate(<brightness<, saturation<, hue>>>)
6290
6657
  Purpose: control the brightness, saturation, and hue of an image
@@ -6330,6 +6697,7 @@ Image_modulate(int argc, VALUE *argv, VALUE self)
6330
6697
  return rm_image_new(new_image);
6331
6698
  }
6332
6699
 
6700
+
6333
6701
  /*
6334
6702
  Method: Image#monitor= proc
6335
6703
  Purpose: Establish a progress monitor
@@ -6357,8 +6725,6 @@ Image_monitor_eq(VALUE self, VALUE monitor)
6357
6725
  }
6358
6726
 
6359
6727
 
6360
-
6361
-
6362
6728
  /*
6363
6729
  Method: Image#monochrome?
6364
6730
  Purpose: return true if all the pixels in the image have the same red,
@@ -6371,6 +6737,7 @@ Image_monochrome_q(VALUE self)
6371
6737
  return has_attribute(self, IsMonochromeImage);
6372
6738
  }
6373
6739
 
6740
+
6374
6741
  /*
6375
6742
  Method: Image#montage
6376
6743
  Purpose: Tile size and offset within an image montage.
@@ -6384,11 +6751,8 @@ DEF_ATTR_READER(Image, montage, str)
6384
6751
  Purpose: called from Image_motion_blur and Image_sketch
6385
6752
  */
6386
6753
  static VALUE
6387
- motion_blur(
6388
- int argc,
6389
- VALUE *argv,
6390
- VALUE self,
6391
- Image *fp(const Image *, const double, const double, const double, ExceptionInfo *))
6754
+ motion_blur(int argc, VALUE *argv, VALUE self
6755
+ , Image *fp(const Image *, const double, const double, const double, ExceptionInfo *))
6392
6756
  {
6393
6757
  Image *image, *new_image;
6394
6758
  double radius = 0.0;
@@ -6478,7 +6842,6 @@ Image_negate(int argc, VALUE *argv, VALUE self)
6478
6842
  }
6479
6843
 
6480
6844
 
6481
-
6482
6845
  /*
6483
6846
  * Method: Image#negate_channel(grayscale=false, channel=AllChannels)
6484
6847
  * Returns a new image
@@ -6608,6 +6971,7 @@ rm_image_new(Image *image)
6608
6971
  return Data_Wrap_Struct(Class_Image, NULL, rm_image_destroy, image);
6609
6972
  }
6610
6973
 
6974
+
6611
6975
  /*
6612
6976
  Method: Image#normalize
6613
6977
  Purpose: enhances the contrast of a color image by adjusting the pixels
@@ -6654,9 +7018,11 @@ Image_normalize_channel(int argc, VALUE *argv, VALUE self)
6654
7018
  return rm_image_new(new_image);
6655
7019
  }
6656
7020
 
7021
+
6657
7022
  DEF_ATTR_READERF(Image, normalized_mean_error, error.normalized_mean_error, dbl)
6658
7023
  DEF_ATTR_READERF(Image, normalized_maximum_error, error.normalized_maximum_error, dbl)
6659
7024
 
7025
+
6660
7026
  /*
6661
7027
  Method: Image#number_colors
6662
7028
  Purpose: return the number of unique colors in the image
@@ -6679,8 +7045,10 @@ Image_number_colors(VALUE self)
6679
7045
  return ULONG2NUM(n);
6680
7046
  }
6681
7047
 
7048
+
6682
7049
  DEF_ATTR_ACCESSOR(Image, offset, long)
6683
7050
 
7051
+
6684
7052
  /*
6685
7053
  Method: Image#oil_paint(radius=3.0)
6686
7054
  Purpose: applies a special effect filter that simulates an oil painting
@@ -6716,6 +7084,7 @@ Image_oil_paint(int argc, VALUE *argv, VALUE self)
6716
7084
  return rm_image_new(new_image);
6717
7085
  }
6718
7086
 
7087
+
6719
7088
  /*
6720
7089
  Method: Image#opaque(target-color-name, fill-color-name)
6721
7090
  Image#opaque(target-pixel, fill-pixel)
@@ -6826,12 +7195,11 @@ Image_opaque_channel(int argc, VALUE *argv, VALUE self)
6826
7195
  argv = argv;
6827
7196
  self = self;
6828
7197
  rm_not_implemented();
6829
- return (VALUE)0;
7198
+ return(VALUE)0;
6830
7199
  #endif
6831
7200
  }
6832
7201
 
6833
7202
 
6834
-
6835
7203
  /*
6836
7204
  Method: Image#opaque?
6837
7205
  Purpose: return true if any of the pixels in the image have an opacity
@@ -6843,6 +7211,7 @@ Image_opaque_q(VALUE self)
6843
7211
  return has_attribute(self, IsOpaqueImage);
6844
7212
  }
6845
7213
 
7214
+
6846
7215
  /*
6847
7216
  Method: Image#ordered_dither(threshold_map='2x2')
6848
7217
  Purpose: perform ordered dither on image
@@ -7014,7 +7383,7 @@ Image_paint_transparent(int argc, VALUE *argv, VALUE self)
7014
7383
  argv = argv;
7015
7384
  self = self;
7016
7385
  rm_not_implemented();
7017
- return (VALUE)0;
7386
+ return(VALUE)0;
7018
7387
  #endif
7019
7388
  }
7020
7389
 
@@ -7030,6 +7399,7 @@ Image_palette_q(VALUE self)
7030
7399
  return has_attribute(self, IsPaletteImage);
7031
7400
  }
7032
7401
 
7402
+
7033
7403
  /*
7034
7404
  Method: Image.ping(file)
7035
7405
  Purpose: Call ImagePing
@@ -7042,6 +7412,7 @@ Image_ping(VALUE class, VALUE file_arg)
7042
7412
  return rd_image(class, file_arg, PingImage);
7043
7413
  }
7044
7414
 
7415
+
7045
7416
  /*
7046
7417
  Method: Image#pixel_color(x, y<, color>)
7047
7418
  Purpose: Gets/sets the color of the pixel at x,y
@@ -7052,10 +7423,7 @@ Image_ping(VALUE class, VALUE file_arg)
7052
7423
  Based on Magick++'s Magick::pixelColor methods
7053
7424
  */
7054
7425
  VALUE
7055
- Image_pixel_color(
7056
- int argc,
7057
- VALUE *argv,
7058
- VALUE self)
7426
+ Image_pixel_color(int argc, VALUE *argv, VALUE self)
7059
7427
  {
7060
7428
  Image *image;
7061
7429
  PixelPacket old_color, new_color, *pixel;
@@ -7229,8 +7597,6 @@ Image_polaroid(int argc, VALUE *argv, VALUE self)
7229
7597
  }
7230
7598
 
7231
7599
 
7232
-
7233
-
7234
7600
  /*
7235
7601
  Method: posterize
7236
7602
  Purpose: call PosterizeImage
@@ -7266,6 +7632,7 @@ Image_posterize(int argc, VALUE *argv, VALUE self)
7266
7632
  return rm_image_new(new_image);
7267
7633
  }
7268
7634
 
7635
+
7269
7636
  /*
7270
7637
  Method: preview
7271
7638
  Purpose: Call PreviewImage
@@ -7460,7 +7827,15 @@ Image_quantize(int argc, VALUE *argv, VALUE self)
7460
7827
  case 4:
7461
7828
  quantize_info.tree_depth = NUM2UINT(argv[3]);
7462
7829
  case 3:
7830
+ #if defined(HAVE_TYPE_DITHERMETHOD)
7831
+ if (rb_obj_is_kind_of(argv[2], Class_DitherMethod))
7832
+ {
7833
+ VALUE_TO_ENUM(argv[2], quantize_info.dither_method, DitherMethod);
7834
+ quantize_info.dither = quantize_info.dither_method != NoDitherMethod;
7835
+ }
7836
+ #else
7463
7837
  quantize_info.dither = (MagickBooleanType) RTEST(argv[2]);
7838
+ #endif
7464
7839
  case 2:
7465
7840
  VALUE_TO_ENUM(argv[1], quantize_info.colorspace, ColorspaceType);
7466
7841
  case 1:
@@ -7481,7 +7856,6 @@ Image_quantize(int argc, VALUE *argv, VALUE self)
7481
7856
  }
7482
7857
 
7483
7858
 
7484
-
7485
7859
  /*
7486
7860
  Method: Image#radial_blur(angle)
7487
7861
  Purpose: Call RadialBlurImage
@@ -7506,6 +7880,7 @@ Image_radial_blur(VALUE self, VALUE angle)
7506
7880
  return rm_image_new(new_image);
7507
7881
  }
7508
7882
 
7883
+
7509
7884
  /*
7510
7885
  Method: Image#radial_blur_channel(angle[, channel..])
7511
7886
  Purpose: Call RadialBlurImageChannel
@@ -7551,10 +7926,7 @@ Image_radial_blur_channel(
7551
7926
  PUrpose: Call RandomThresholdImageChannel
7552
7927
  */
7553
7928
  VALUE
7554
- Image_random_threshold_channel(
7555
- int argc,
7556
- VALUE *argv,
7557
- VALUE self)
7929
+ Image_random_threshold_channel(int argc, VALUE *argv, VALUE self)
7558
7930
  {
7559
7931
  Image *image, *new_image;
7560
7932
  ChannelType channels;
@@ -7577,7 +7949,7 @@ Image_random_threshold_channel(
7577
7949
  }
7578
7950
 
7579
7951
  // Accept any argument that has a to_s method.
7580
- geom_str = rb_funcall(argv[0], rm_ID_to_s, 0);
7952
+ geom_str = rm_to_s(argv[0]);
7581
7953
  thresholds = StringValuePtr(geom_str);
7582
7954
 
7583
7955
  new_image = rm_clone_image(image);
@@ -7637,6 +8009,7 @@ Image_raise(int argc, VALUE *argv, VALUE self)
7637
8009
  return rm_image_new(new_image);
7638
8010
  }
7639
8011
 
8012
+
7640
8013
  /*
7641
8014
  Method: Image.read(file)
7642
8015
  Purpose: Call ReadImage
@@ -7658,6 +8031,7 @@ file_arg_rescue(VALUE arg)
7658
8031
  {
7659
8032
  rb_raise(rb_eTypeError, "argument must be path name or open file (%s given)",
7660
8033
  rb_class2name(CLASS_OF(arg)));
8034
+ return(VALUE)0;
7661
8035
  }
7662
8036
 
7663
8037
 
@@ -7829,7 +8203,8 @@ Image_read_inline(VALUE self, VALUE content)
7829
8203
  Static: array_from_images
7830
8204
  Purpose: convert a list of images to an array of Image objects
7831
8205
  */
7832
- static VALUE array_from_images(Image *images)
8206
+ static VALUE
8207
+ array_from_images(Image *images)
7833
8208
  {
7834
8209
  volatile VALUE image_obj, image_ary;
7835
8210
  Image *image;
@@ -7870,6 +8245,7 @@ Image_reduce_noise(VALUE self, VALUE radius)
7870
8245
  return rm_image_new(new_image);
7871
8246
  }
7872
8247
 
8248
+
7873
8249
  /*
7874
8250
  Method: Image#rendering_intent=
7875
8251
  Purpose: get rendering_intent
@@ -7881,6 +8257,7 @@ Image_rendering_intent(VALUE self)
7881
8257
  return RenderingIntent_new(image->rendering_intent);
7882
8258
  }
7883
8259
 
8260
+
7884
8261
  /*
7885
8262
  Method: Image#rendering_intent=
7886
8263
  Purpose: set rendering_intent
@@ -7893,6 +8270,7 @@ Image_rendering_intent_eq(VALUE self, VALUE ri)
7893
8270
  return self;
7894
8271
  }
7895
8272
 
8273
+
7896
8274
  /*
7897
8275
  Method: Image#resize(scale) or (cols, rows<, filter<, blur>>)
7898
8276
  Image#resize!(scale) or (cols, rows<, filter<, blur>>)
@@ -7972,6 +8350,7 @@ resize(int bang, int argc, VALUE *argv, VALUE self)
7972
8350
  return rm_image_new(new_image);
7973
8351
  }
7974
8352
 
8353
+
7975
8354
  VALUE
7976
8355
  Image_resize(int argc, VALUE *argv, VALUE self)
7977
8356
  {
@@ -7979,6 +8358,7 @@ Image_resize(int argc, VALUE *argv, VALUE self)
7979
8358
  return resize(False, argc, argv, self);
7980
8359
  }
7981
8360
 
8361
+
7982
8362
  VALUE
7983
8363
  Image_resize_bang(int argc, VALUE *argv, VALUE self)
7984
8364
  {
@@ -7986,6 +8366,7 @@ Image_resize_bang(int argc, VALUE *argv, VALUE self)
7986
8366
  return resize(True, argc, argv, self);
7987
8367
  }
7988
8368
 
8369
+
7989
8370
  /*
7990
8371
  Method: Image#roll(x_offset, y_offset)
7991
8372
  Purpose: offsets an image as defined by x_offset and y_offset
@@ -8072,6 +8453,7 @@ rotate(int bang, int argc, VALUE *argv, VALUE self)
8072
8453
  return rm_image_new(new_image);
8073
8454
  }
8074
8455
 
8456
+
8075
8457
  VALUE
8076
8458
  Image_rotate(int argc, VALUE *argv, VALUE self)
8077
8459
  {
@@ -8079,6 +8461,7 @@ Image_rotate(int argc, VALUE *argv, VALUE self)
8079
8461
  return rotate(False, argc, argv, self);
8080
8462
  }
8081
8463
 
8464
+
8082
8465
  VALUE
8083
8466
  Image_rotate_bang(int argc, VALUE *argv, VALUE self)
8084
8467
  {
@@ -8086,8 +8469,10 @@ Image_rotate_bang(int argc, VALUE *argv, VALUE self)
8086
8469
  return rotate(True, argc, argv, self);
8087
8470
  }
8088
8471
 
8472
+
8089
8473
  DEF_ATTR_READER(Image, rows, int)
8090
8474
 
8475
+
8091
8476
  /*
8092
8477
  Method: Image#sample(scale) or (cols, rows)
8093
8478
  Image#sample!
@@ -8102,6 +8487,7 @@ Image_sample(int argc, VALUE *argv, VALUE self)
8102
8487
  return scale(False, argc, argv, self, SampleImage);
8103
8488
  }
8104
8489
 
8490
+
8105
8491
  VALUE
8106
8492
  Image_sample_bang(int argc, VALUE *argv, VALUE self)
8107
8493
  {
@@ -8109,6 +8495,7 @@ Image_sample_bang(int argc, VALUE *argv, VALUE self)
8109
8495
  return scale(True, argc, argv, self, SampleImage);
8110
8496
  }
8111
8497
 
8498
+
8112
8499
  /*
8113
8500
  Method: Image#scale(scale) or (cols, rows)
8114
8501
  Image#scale!
@@ -8123,6 +8510,7 @@ Image_scale(int argc, VALUE *argv, VALUE self)
8123
8510
  return scale(False, argc, argv, self, ScaleImage);
8124
8511
  }
8125
8512
 
8513
+
8126
8514
  VALUE
8127
8515
  Image_scale_bang(int argc, VALUE *argv, VALUE self)
8128
8516
  {
@@ -8130,6 +8518,7 @@ Image_scale_bang(int argc, VALUE *argv, VALUE self)
8130
8518
  return scale(True, argc, argv, self, ScaleImage);
8131
8519
  }
8132
8520
 
8521
+
8133
8522
  /*
8134
8523
  Static: scale
8135
8524
  Purpose: Call ScaleImage or SampleImage
@@ -8194,6 +8583,7 @@ scale(int bang, int argc, VALUE *argv, VALUE self, scaler_t scaler)
8194
8583
  return rm_image_new(new_image);
8195
8584
  }
8196
8585
 
8586
+
8197
8587
  DEF_ATTR_READER(Image, scene, ulong)
8198
8588
 
8199
8589
 
@@ -8330,6 +8720,7 @@ Image_segment(int argc, VALUE *argv, VALUE self)
8330
8720
  return rm_image_new(new_image);
8331
8721
  }
8332
8722
 
8723
+
8333
8724
  /*
8334
8725
  Method: Image#opacity=
8335
8726
  Purpose: Call SetImageOpacity
@@ -8544,6 +8935,7 @@ Image_shadow(int argc, VALUE *argv, VALUE self)
8544
8935
  return rm_image_new(new_image);
8545
8936
  }
8546
8937
 
8938
+
8547
8939
  /*
8548
8940
  Method: Image#sharpen(radius=0, sigma=1)
8549
8941
  Purpose: sharpens an image
@@ -8607,10 +8999,7 @@ Image_sharpen_channel(int argc, VALUE *argv, VALUE self)
8607
8999
  shave!: self, shaved
8608
9000
  */
8609
9001
  VALUE
8610
- Image_shave(
8611
- VALUE self,
8612
- VALUE width,
8613
- VALUE height)
9002
+ Image_shave(VALUE self, VALUE width, VALUE height)
8614
9003
  {
8615
9004
  (void) rm_check_destroyed(self);
8616
9005
  return xform_image(False, self, INT2FIX(0), INT2FIX(0), width, height, ShaveImage);
@@ -8618,10 +9007,7 @@ Image_shave(
8618
9007
 
8619
9008
 
8620
9009
  VALUE
8621
- Image_shave_bang(
8622
- VALUE self,
8623
- VALUE width,
8624
- VALUE height)
9010
+ Image_shave_bang(VALUE self, VALUE width, VALUE height)
8625
9011
  {
8626
9012
  (void) rm_check_frozen(self);
8627
9013
  return xform_image(True, self, INT2FIX(0), INT2FIX(0), width, height, ShaveImage);
@@ -8635,10 +9021,7 @@ Image_shave_bang(
8635
9021
  Returns: a new image
8636
9022
  */
8637
9023
  VALUE
8638
- Image_shear(
8639
- VALUE self,
8640
- VALUE x_shear,
8641
- VALUE y_shear)
9024
+ Image_shear(VALUE self, VALUE x_shear, VALUE y_shear)
8642
9025
  {
8643
9026
  Image *image, *new_image;
8644
9027
  ExceptionInfo exception;
@@ -8695,6 +9078,7 @@ Image_sigmoidal_contrast_channel(int argc, VALUE *argv, VALUE self)
8695
9078
  return rm_image_new(new_image);
8696
9079
  }
8697
9080
 
9081
+
8698
9082
  /*
8699
9083
  Method: Image#signature
8700
9084
  Purpose: computes a message digest from an image pixel stream with an
@@ -8719,7 +9103,6 @@ Image_signature(VALUE self)
8719
9103
  }
8720
9104
 
8721
9105
 
8722
-
8723
9106
  /*
8724
9107
  Method: Image#sketch(radius=0.0, sigma=1.0, angle=0.0)
8725
9108
  Purpose: Call SketchImage
@@ -8769,6 +9152,7 @@ Image_solarize(int argc, VALUE *argv, VALUE self)
8769
9152
  return rm_image_new(new_image);
8770
9153
  }
8771
9154
 
9155
+
8772
9156
  /*
8773
9157
  Method: Image#spaceship (a <=> b)
8774
9158
  Purpose: compare two images
@@ -8806,6 +9190,62 @@ Image_spaceship(VALUE self, VALUE other)
8806
9190
  return INT2FIX(res);
8807
9191
  }
8808
9192
 
9193
+
9194
+ /*
9195
+ Method: Image#sparse_color(method, pts[, channel...])
9196
+ Purpose: Call SparseColorInterpolate
9197
+ */
9198
+ VALUE
9199
+ Image_sparse_color(int argc, VALUE *argv, VALUE self)
9200
+ {
9201
+ #if defined(HAVE_SPARSECOLORINTERPOLATE) && 0
9202
+ Image *image, *new_image;
9203
+ unsigned long n, npoints;
9204
+ SparseColorInterpolateMethod interpolate_method;
9205
+ double *points;
9206
+ ChannelType channels;
9207
+
9208
+ ExceptionInfo exception;
9209
+
9210
+ image = rm_check_destroyed(self);
9211
+ channels = extract_channels(&argc, argv);
9212
+
9213
+ if (argc != 2)
9214
+ {
9215
+ raise_ChannelType_error(argv[argc-1]);
9216
+ }
9217
+
9218
+ VALUE_TO_ENUM(argv[0], interpolate_method, SparseColorInterpolateMethod);
9219
+ npoints = RARRAY_LEN(argv[1]);
9220
+
9221
+ // Allocate points array from Ruby's memory. If an error occurs Ruby will
9222
+ // be able to clean it up.
9223
+ points = ALLOC_N(double, npoints);
9224
+
9225
+ for (n = 0; n < npoints; n++)
9226
+ {
9227
+ points[n] = NUM2DBL(rb_ary_entry(argv[1], n));
9228
+ }
9229
+
9230
+ GetExceptionInfo(&exception);
9231
+ new_image = SparseColorInterpolate(image, interpolate_method, npoints, points, channels, &exception);
9232
+ xfree(points);
9233
+ rm_check_exception(&exception, new_image, DestroyOnError);
9234
+ (void) DestroyExceptionInfo(&exception);
9235
+ rm_ensure_result(new_image);
9236
+
9237
+ return rm_image_new(new_image);
9238
+
9239
+ #else
9240
+ self = self;
9241
+ argc = argc;
9242
+ argv = argv;
9243
+ rm_not_implemented();
9244
+ return(VALUE)0;
9245
+ #endif
9246
+ }
9247
+
9248
+
8809
9249
  /*
8810
9250
  Method: Image#splice(x, y, width, height[, color])
8811
9251
  Purpose: Splice a solid color into the part of the image specified
@@ -8862,6 +9302,7 @@ Image_splice(int argc, VALUE *argv, VALUE self)
8862
9302
  return rm_image_new(new_image);
8863
9303
  }
8864
9304
 
9305
+
8865
9306
  /*
8866
9307
  Method: Image#spread(radius=3)
8867
9308
  Purpose: randomly displaces each pixel in a block defined by "radius"
@@ -8896,6 +9337,7 @@ Image_spread(int argc, VALUE *argv, VALUE self)
8896
9337
  return rm_image_new(new_image);
8897
9338
  }
8898
9339
 
9340
+
8899
9341
  DEF_ATTR_ACCESSOR(Image, start_loop, bool)
8900
9342
 
8901
9343
 
@@ -8908,10 +9350,7 @@ DEF_ATTR_ACCESSOR(Image, start_loop, bool)
8908
9350
  Returns: a new image
8909
9351
  */
8910
9352
  VALUE
8911
- Image_stegano(
8912
- VALUE self,
8913
- VALUE watermark_image,
8914
- VALUE offset)
9353
+ Image_stegano(VALUE self, VALUE watermark_image, VALUE offset)
8915
9354
  {
8916
9355
  Image *image, *new_image;
8917
9356
  volatile VALUE wm_image;
@@ -8920,7 +9359,7 @@ Image_stegano(
8920
9359
 
8921
9360
  image = rm_check_destroyed(self);
8922
9361
 
8923
- wm_image = ImageList_cur_image(watermark_image);
9362
+ wm_image = rm_cur_image(watermark_image);
8924
9363
  watermark = rm_check_destroyed(wm_image);
8925
9364
 
8926
9365
  image->offset = NUM2LONG(offset);
@@ -8936,6 +9375,7 @@ Image_stegano(
8936
9375
  return rm_image_new(new_image);
8937
9376
  }
8938
9377
 
9378
+
8939
9379
  /*
8940
9380
  Method: Image#stereo(offset_image)
8941
9381
  Purpose: combines two images and produces a single image that is the
@@ -8945,9 +9385,7 @@ Image_stegano(
8945
9385
  Returns: a new image
8946
9386
  */
8947
9387
  VALUE
8948
- Image_stereo(
8949
- VALUE self,
8950
- VALUE offset_image_arg)
9388
+ Image_stereo(VALUE self, VALUE offset_image_arg)
8951
9389
  {
8952
9390
  Image *image, *new_image;
8953
9391
  volatile VALUE offset_image;
@@ -8956,7 +9394,7 @@ Image_stereo(
8956
9394
 
8957
9395
  image = rm_check_destroyed(self);
8958
9396
 
8959
- offset_image = ImageList_cur_image(offset_image_arg);
9397
+ offset_image = rm_cur_image(offset_image_arg);
8960
9398
  offset = rm_check_destroyed(offset_image);
8961
9399
 
8962
9400
  GetExceptionInfo(&exception);
@@ -8970,6 +9408,7 @@ Image_stereo(
8970
9408
  return rm_image_new(new_image);
8971
9409
  }
8972
9410
 
9411
+
8973
9412
  /*
8974
9413
  Method: Image#class_type
8975
9414
  Purpose: return the image's storage class (a.k.a. storage type, class type)
@@ -8982,6 +9421,7 @@ Image_class_type(VALUE self)
8982
9421
  return ClassType_new(image->storage_class);
8983
9422
  }
8984
9423
 
9424
+
8985
9425
  /*
8986
9426
  Method: Image#class_type=
8987
9427
  Purpose: change the image's storage class
@@ -9015,6 +9455,7 @@ Image_class_type_eq(VALUE self, VALUE new_class_type)
9015
9455
  return self;
9016
9456
  }
9017
9457
 
9458
+
9018
9459
  /*
9019
9460
  Method: Image#store_pixels
9020
9461
  Purpose: Replace the pixels in the specified rectangle
@@ -9024,13 +9465,8 @@ Image_class_type_eq(VALUE self, VALUE new_class_type)
9024
9465
  "new_pixels" argument.
9025
9466
  */
9026
9467
  VALUE
9027
- Image_store_pixels(
9028
- VALUE self,
9029
- VALUE x_arg,
9030
- VALUE y_arg,
9031
- VALUE cols_arg,
9032
- VALUE rows_arg,
9033
- VALUE new_pixels)
9468
+ Image_store_pixels(VALUE self, VALUE x_arg, VALUE y_arg, VALUE cols_arg
9469
+ , VALUE rows_arg, VALUE new_pixels)
9034
9470
  {
9035
9471
  Image *image;
9036
9472
  Pixel *pixels, *pixel;
@@ -9160,13 +9596,8 @@ Image_sync_profiles(VALUE self)
9160
9596
  stopping at pixels matching the specified color."
9161
9597
  */
9162
9598
  VALUE
9163
- Image_texture_flood_fill(
9164
- VALUE self,
9165
- VALUE color_obj,
9166
- VALUE texture_obj,
9167
- VALUE x_obj,
9168
- VALUE y_obj,
9169
- VALUE method_obj)
9599
+ Image_texture_flood_fill(VALUE self, VALUE color_obj, VALUE texture_obj
9600
+ , VALUE x_obj, VALUE y_obj, VALUE method_obj)
9170
9601
  {
9171
9602
  Image *image, *new_image;
9172
9603
  Image *texture_image;
@@ -9179,7 +9610,7 @@ Image_texture_flood_fill(
9179
9610
  image = rm_check_destroyed(self);
9180
9611
 
9181
9612
  Color_to_PixelPacket(&color, color_obj);
9182
- texture = ImageList_cur_image(texture_obj);
9613
+ texture = rm_cur_image(texture_obj);
9183
9614
  texture_image = rm_check_destroyed(texture);
9184
9615
 
9185
9616
  x = NUM2LONG(x_obj);
@@ -9210,26 +9641,26 @@ Image_texture_flood_fill(
9210
9641
 
9211
9642
  #if defined(HAVE_FLOODFILLPAINTIMAGE)
9212
9643
  {
9213
- MagickPixelPacket color_mpp;
9214
- MagickBooleanType invert;
9644
+ MagickPixelPacket color_mpp;
9645
+ MagickBooleanType invert;
9215
9646
 
9216
- GetMagickPixelPacket(new_image, &color_mpp);
9217
- if (method == FillToBorderMethod)
9218
- {
9219
- invert = MagickTrue;
9220
- color_mpp.red = (MagickRealType) image->border_color.red;
9221
- color_mpp.green = (MagickRealType) image->border_color.green;
9222
- color_mpp.blue = (MagickRealType) image->border_color.blue;
9223
- }
9224
- else
9225
- {
9226
- invert = MagickFalse;
9227
- color_mpp.red = (MagickRealType) color.red;
9228
- color_mpp.green = (MagickRealType) color.green;
9229
- color_mpp.blue = (MagickRealType) color.blue;
9230
- }
9647
+ GetMagickPixelPacket(new_image, &color_mpp);
9648
+ if (method == FillToBorderMethod)
9649
+ {
9650
+ invert = MagickTrue;
9651
+ color_mpp.red = (MagickRealType) image->border_color.red;
9652
+ color_mpp.green = (MagickRealType) image->border_color.green;
9653
+ color_mpp.blue = (MagickRealType) image->border_color.blue;
9654
+ }
9655
+ else
9656
+ {
9657
+ invert = MagickFalse;
9658
+ color_mpp.red = (MagickRealType) color.red;
9659
+ color_mpp.green = (MagickRealType) color.green;
9660
+ color_mpp.blue = (MagickRealType) color.blue;
9661
+ }
9231
9662
 
9232
- (void) FloodfillPaintImage(new_image, DefaultChannels, draw_info, &color_mpp, x, y, invert);
9663
+ (void) FloodfillPaintImage(new_image, DefaultChannels, draw_info, &color_mpp, x, y, invert);
9233
9664
  }
9234
9665
 
9235
9666
  #else
@@ -9243,6 +9674,7 @@ Image_texture_flood_fill(
9243
9674
  return rm_image_new(new_image);
9244
9675
  }
9245
9676
 
9677
+
9246
9678
  /*
9247
9679
  Method: Image#threshold(threshold)
9248
9680
  Purpose: changes the value of individual pixels based on the intensity of
@@ -9269,11 +9701,7 @@ Image_threshold(VALUE self, VALUE threshold)
9269
9701
  * Purpose: call one of the xxxxThresholdImage methods
9270
9702
  */
9271
9703
  static
9272
- VALUE threshold_image(
9273
- int argc,
9274
- VALUE *argv,
9275
- VALUE self,
9276
- thresholder_t thresholder)
9704
+ VALUE threshold_image(int argc, VALUE *argv, VALUE self, thresholder_t thresholder)
9277
9705
  {
9278
9706
  Image *image, *new_image;
9279
9707
  double red, green, blue, opacity;
@@ -9383,6 +9811,7 @@ thumbnail(int bang, int argc, VALUE *argv, VALUE self)
9383
9811
  return rm_image_new(new_image);
9384
9812
  }
9385
9813
 
9814
+
9386
9815
  VALUE
9387
9816
  Image_thumbnail(int argc, VALUE *argv, VALUE self)
9388
9817
  {
@@ -9390,6 +9819,7 @@ Image_thumbnail(int argc, VALUE *argv, VALUE self)
9390
9819
  return thumbnail(False, argc, argv, self);
9391
9820
  }
9392
9821
 
9822
+
9393
9823
  VALUE
9394
9824
  Image_thumbnail_bang(int argc, VALUE *argv, VALUE self)
9395
9825
  {
@@ -9490,6 +9920,7 @@ Image_tint(int argc, VALUE *argv, VALUE self)
9490
9920
  return rm_image_new(new_image);
9491
9921
  }
9492
9922
 
9923
+
9493
9924
  /*
9494
9925
  Method: Image#to_blob
9495
9926
  Purpose: Return a "blob" (a String) from the image
@@ -9569,6 +10000,7 @@ Image_to_blob(VALUE self)
9569
10000
  return blob_str;
9570
10001
  }
9571
10002
 
10003
+
9572
10004
  /*
9573
10005
  Method: Image#to_color
9574
10006
  Purpose: Return a color name for the color intensity specified by the
@@ -9601,6 +10033,7 @@ Image_to_color(VALUE self, VALUE pixel_arg)
9601
10033
 
9602
10034
  }
9603
10035
 
10036
+
9604
10037
  /*
9605
10038
  Method: Image#total_colors
9606
10039
  Purpose: alias for Image#number_colors
@@ -9613,6 +10046,7 @@ Image_total_colors(VALUE self)
9613
10046
  return Image_number_colors(self);
9614
10047
  }
9615
10048
 
10049
+
9616
10050
  /*
9617
10051
  Method: Image#transparent(color-name<, opacity>)
9618
10052
  Image#transparent(pixel<, opacity>)
@@ -9791,6 +10225,7 @@ Image_trim(int argc, VALUE *argv, VALUE self)
9791
10225
  return trimmer(False, argc, argv, self);
9792
10226
  }
9793
10227
 
10228
+
9794
10229
  VALUE
9795
10230
  Image_trim_bang(int argc, VALUE *argv, VALUE self)
9796
10231
  {
@@ -9851,6 +10286,33 @@ VALUE Image_image_type_eq(VALUE self, VALUE image_type)
9851
10286
  }
9852
10287
 
9853
10288
 
10289
+ /*
10290
+ Method: Image#undefine(artifact)
10291
+ Purpose: Call RemoveImageArtifact
10292
+ Note: Normally a script should never call this method.
10293
+ See Image_define.
10294
+ */
10295
+ VALUE
10296
+ Image_undefine(VALUE self, VALUE artifact)
10297
+ {
10298
+ #if defined(HAVE_REMOVEIMAGEARTIFACT)
10299
+ Image *image;
10300
+ char *key;
10301
+ long key_l;
10302
+
10303
+ image = rm_check_frozen(self);
10304
+ key = rm_str2cstr(artifact, &key_l);
10305
+ (void) RemoveImageArtifact(image, key);
10306
+ return self;
10307
+ #else
10308
+ rm_not_implemented();
10309
+ artifact = artifact;
10310
+ self = self;
10311
+ return(VALUE)0;
10312
+ #endif
10313
+ }
10314
+
10315
+
9854
10316
  /*
9855
10317
  Method: Image#unique_colors
9856
10318
  Purpose: Call UniqueImageColors
@@ -9885,6 +10347,7 @@ Image_units(VALUE self)
9885
10347
  return ResolutionType_new(image->units);
9886
10348
  }
9887
10349
 
10350
+
9888
10351
  /*
9889
10352
  Method: Image#units=
9890
10353
  Purpose: Set the resolution type field
@@ -9914,8 +10377,8 @@ Image_units_eq(
9914
10377
  case PixelsPerCentimeterResolution:
9915
10378
  if (units == PixelsPerInchResolution)
9916
10379
  {
9917
- image->x_resolution *= 2.54;
9918
- image->y_resolution *= 2.54;
10380
+ image->x_resolution *= 2.54;
10381
+ image->y_resolution *= 2.54;
9919
10382
  }
9920
10383
  break;
9921
10384
 
@@ -9932,6 +10395,7 @@ Image_units_eq(
9932
10395
  return self;
9933
10396
  }
9934
10397
 
10398
+
9935
10399
  /*
9936
10400
  Method: Image#unsharp_mask(radius=0.0, sigma=1.0, amount=1.0, threshold=0.05)
9937
10401
  Purpose: sharpens an image. "amount" is the percentage of the difference
@@ -9940,13 +10404,8 @@ Image_units_eq(
9940
10404
  apply the diffence amount.
9941
10405
  */
9942
10406
  static void
9943
- unsharp_mask_args(
9944
- int argc,
9945
- VALUE *argv,
9946
- double *radius,
9947
- double *sigma,
9948
- double *amount,
9949
- double *threshold)
10407
+ unsharp_mask_args(int argc, VALUE *argv, double *radius, double *sigma
10408
+ , double *amount, double *threshold)
9950
10409
  {
9951
10410
  switch (argc)
9952
10411
  {
@@ -10126,8 +10585,6 @@ Image_virtual_pixel_method_eq(VALUE self, VALUE method)
10126
10585
  }
10127
10586
 
10128
10587
 
10129
-
10130
-
10131
10588
  /*
10132
10589
  Method: Image#watermark(mark, brightness=100.0, saturation=100.0
10133
10590
  , [gravity,] x_off=0, y_off=0)
@@ -10151,7 +10608,7 @@ Image_watermark(int argc, VALUE *argv, VALUE self)
10151
10608
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 to 6)", argc);
10152
10609
  }
10153
10610
 
10154
- ovly = ImageList_cur_image(argv[0]);
10611
+ ovly = rm_cur_image(argv[0]);
10155
10612
  overlay = rm_check_destroyed(ovly);
10156
10613
 
10157
10614
  if (argc > 3)
@@ -10185,6 +10642,7 @@ Image_watermark(int argc, VALUE *argv, VALUE self)
10185
10642
  return rm_image_new(new_image);
10186
10643
  }
10187
10644
 
10645
+
10188
10646
  /*
10189
10647
  Method: Image#wave(amplitude=25.0, wavelength=150.0)
10190
10648
  Purpose: creates a "ripple" effect in the image by shifting the pixels
@@ -10378,6 +10836,91 @@ Image_white_threshold(int argc, VALUE *argv, VALUE self)
10378
10836
  }
10379
10837
 
10380
10838
 
10839
+ /*
10840
+ Copy the filename to the Info and to the Image. Add format
10841
+ prefix if necessary. This complicated code is necessary to handle filenames
10842
+ like the kind Tempfile.new produces, which have an "extension" in the form
10843
+ ".n", which confuses SetMagickInfo. So we don't use SetMagickInfo any longer.
10844
+ */
10845
+ void add_format_prefix(Info *info, VALUE file)
10846
+ {
10847
+ char *filename;
10848
+ long filename_l;
10849
+ const MagickInfo *magick_info, *magick_info2;
10850
+ ExceptionInfo exception;
10851
+ char magic[MaxTextExtent];
10852
+ size_t magic_l;
10853
+ size_t prefix_l;
10854
+ void *p;
10855
+
10856
+ // Convert arg to string. If an exception occurs raise an error condition.
10857
+ file = rb_rescue(rb_String, file, file_arg_rescue, file);
10858
+
10859
+ filename = rm_str2cstr(file, &filename_l);
10860
+
10861
+ if (*info->magick == '\0')
10862
+ {
10863
+ memset(info->filename, 0, sizeof(info->filename));
10864
+ memcpy(info->filename, filename, (size_t)min(filename_l, MaxTextExtent-1));
10865
+ return;
10866
+ }
10867
+
10868
+ // If the filename starts with a prefix, and it's a valid image format
10869
+ // prefix, then check for a conflict. If it's not a valid format prefix,
10870
+ // ignore it.
10871
+ p = memchr(filename, ':', (size_t)filename_l);
10872
+ if (p)
10873
+ {
10874
+ memset(magic, '\0', sizeof(magic));
10875
+ magic_l = p - (void *)filename;
10876
+ memcpy(magic, filename, magic_l);
10877
+
10878
+ GetExceptionInfo(&exception);
10879
+ magick_info = GetMagickInfo(magic, &exception);
10880
+ CHECK_EXCEPTION();
10881
+ DestroyExceptionInfo(&exception);
10882
+
10883
+ if (magick_info && magick_info->module)
10884
+ {
10885
+ // We have to compare the module names because some formats have
10886
+ // more than one name. JPG and JPEG, for example.
10887
+ GetExceptionInfo(&exception);
10888
+ magick_info2 = GetMagickInfo(info->magick, &exception);
10889
+ CHECK_EXCEPTION();
10890
+ DestroyExceptionInfo(&exception);
10891
+
10892
+ if (magick_info2->module && strcmp(magick_info->module, magick_info2->module) != 0)
10893
+ {
10894
+ rb_raise(rb_eRuntimeError
10895
+ , "filename prefix `%s' conflicts with output format `%s'"
10896
+ , magick_info->name, info->magick);
10897
+ }
10898
+
10899
+ // The filename prefix already matches the specified format.
10900
+ // Just copy the filename as-is.
10901
+ memset(info->filename, 0, sizeof(info->filename));
10902
+ filename_l = min((size_t)filename_l, sizeof(info->filename));
10903
+ memcpy(info->filename, filename, (size_t)filename_l);
10904
+ return;
10905
+ }
10906
+ }
10907
+
10908
+ // The filename doesn't start with a format prefix. Add the format from
10909
+ // the image info as the filename prefix.
10910
+
10911
+ memset(info->filename, 0, sizeof(info->filename));
10912
+ prefix_l = min(sizeof(info->filename)-1, strlen(info->magick));
10913
+ memcpy(info->filename, info->magick, prefix_l);
10914
+ info->filename[prefix_l++] = ':';
10915
+
10916
+ filename_l = min(sizeof(info->filename) - prefix_l - 1, (size_t)filename_l);
10917
+ memcpy(info->filename+prefix_l, filename, (size_t)filename_l);
10918
+ info->filename[prefix_l+filename_l] = '\0';
10919
+
10920
+ return;
10921
+ }
10922
+
10923
+
10381
10924
  /*
10382
10925
  Method: Image#write(filename)
10383
10926
  Purpose: Write the image to the file.
@@ -10389,9 +10932,6 @@ Image_write(VALUE self, VALUE file)
10389
10932
  Image *image;
10390
10933
  Info *info;
10391
10934
  volatile VALUE info_obj;
10392
- char *filename;
10393
- long filename_l;
10394
- ExceptionInfo exception;
10395
10935
 
10396
10936
  image = rm_check_destroyed(self);
10397
10937
 
@@ -10406,31 +10946,12 @@ Image_write(VALUE self, VALUE file)
10406
10946
  GetOpenFile(file, fptr);
10407
10947
  rb_io_check_writable(fptr);
10408
10948
  SetImageInfoFile(info, GetWriteFile(fptr));
10949
+ memset(image->filename, 0, sizeof(image->filename));
10409
10950
  }
10410
10951
  else
10411
10952
  {
10412
- // Copy the filename to the Info and to the Image, then call
10413
- // SetImageInfo. (Ref: ImageMagick's utilities/convert.c.)
10414
-
10415
- // Convert arg to string. If an exception occurs raise an error condition.
10416
- file = rb_rescue(rb_String, file, file_arg_rescue, file);
10417
-
10418
- filename = rm_str2cstr(file, &filename_l);
10419
- filename_l = min(filename_l, MaxTextExtent-1);
10420
- memcpy(info->filename, filename, (size_t)filename_l);
10421
- info->filename[filename_l] = '\0';
10953
+ add_format_prefix(info, file);
10422
10954
  strcpy(image->filename, info->filename);
10423
-
10424
- GetExceptionInfo(&exception);
10425
- (void) SetImageInfo(info, MagickTrue, &exception);
10426
- CHECK_EXCEPTION()
10427
-
10428
- (void) DestroyExceptionInfo(&exception);
10429
-
10430
- if (*info->magick == '\0')
10431
- {
10432
- return Qnil;
10433
- }
10434
10955
  SetImageInfoFile(info, NULL);
10435
10956
  }
10436
10957
 
@@ -10640,21 +11161,13 @@ cropper(int bang, int argc, VALUE *argv, VALUE self)
10640
11161
  }
10641
11162
 
10642
11163
 
10643
-
10644
11164
  /*
10645
11165
  Static: xform_image
10646
11166
  Purpose: call one of the image transformation functions
10647
11167
  Returns: a new image, or transformed self
10648
11168
  */
10649
11169
  static VALUE
10650
- xform_image(
10651
- int bang,
10652
- VALUE self,
10653
- VALUE x,
10654
- VALUE y,
10655
- VALUE width,
10656
- VALUE height,
10657
- xformer_t xformer)
11170
+ xform_image(int bang, VALUE self, VALUE x, VALUE y, VALUE width, VALUE height, xformer_t xformer)
10658
11171
  {
10659
11172
  Image *image, *new_image;
10660
11173
  RectangleInfo rect;
@@ -10699,9 +11212,7 @@ xform_image(
10699
11212
  no channel arguments were found. Returns the
10700
11213
  number of remaining arguments.
10701
11214
  */
10702
- ChannelType extract_channels(
10703
- int *argc,
10704
- VALUE *argv)
11215
+ ChannelType extract_channels(int *argc, VALUE *argv)
10705
11216
  {
10706
11217
  volatile VALUE arg;
10707
11218
  ChannelType channels, ch_arg;