rmagick 1.9.3 → 1.10.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 (62) hide show
  1. data/ChangeLog +18 -0
  2. data/README.html +12 -12
  3. data/README.txt +10 -10
  4. data/configure +728 -367
  5. data/configure.ac +134 -69
  6. data/doc/comtasks.html +11 -3
  7. data/doc/constants.html +162 -40
  8. data/doc/draw.html +2 -2
  9. data/doc/ex/crop_resized.rb +10 -0
  10. data/doc/ex/get_type_metrics.rb +26 -22
  11. data/doc/ex/vignette.rb +19 -0
  12. data/doc/ilist.html +0 -5
  13. data/doc/image1.html +219 -49
  14. data/doc/image2.html +115 -47
  15. data/doc/image3.html +105 -23
  16. data/doc/imageattrs.html +4 -23
  17. data/doc/imusage.html +1 -1
  18. data/doc/index.html +8 -9
  19. data/doc/info.html +23 -3
  20. data/doc/magick.html +1 -1
  21. data/doc/rvg.html +1 -1
  22. data/doc/rvgclip.html +1 -1
  23. data/doc/rvggroup.html +1 -1
  24. data/doc/rvgimage.html +1 -1
  25. data/doc/rvgpattern.html +1 -1
  26. data/doc/rvgshape.html +1 -1
  27. data/doc/rvgstyle.html +1 -1
  28. data/doc/rvgtext.html +3 -3
  29. data/doc/rvgtspan.html +1 -1
  30. data/doc/rvgtut.html +119 -101
  31. data/doc/rvguse.html +1 -1
  32. data/doc/rvgxform.html +1 -1
  33. data/doc/struct.html +17 -11
  34. data/doc/usage.html +22 -4
  35. data/examples/histogram.rb +48 -12
  36. data/examples/spinner.rb +49 -0
  37. data/ext/RMagick/MANIFEST +4 -1
  38. data/ext/RMagick/rmagick.h +62 -33
  39. data/ext/RMagick/rmagick_config.h.in +28 -31
  40. data/ext/RMagick/rmdraw.c +14 -6
  41. data/ext/RMagick/rmfill.c +2 -2
  42. data/ext/RMagick/rmilist.c +8 -36
  43. data/ext/RMagick/rmimage.c +370 -97
  44. data/ext/RMagick/rminfo.c +6 -6
  45. data/ext/RMagick/rmmain.c +114 -25
  46. data/ext/RMagick/rmutil.c +98 -35
  47. data/lib/RMagick.rb +17 -2
  48. data/lib/rvg/clippath.rb +2 -2
  49. data/lib/rvg/container.rb +2 -2
  50. data/lib/rvg/describable.rb +2 -2
  51. data/lib/rvg/embellishable.rb +2 -2
  52. data/lib/rvg/misc.rb +3 -3
  53. data/lib/rvg/paint.rb +2 -2
  54. data/lib/rvg/pathdata.rb +2 -2
  55. data/lib/rvg/rvg.rb +2 -2
  56. data/lib/rvg/stretchable.rb +2 -2
  57. data/lib/rvg/stylable.rb +2 -2
  58. data/lib/rvg/text.rb +2 -2
  59. data/lib/rvg/transformable.rb +2 -2
  60. data/lib/rvg/units.rb +2 -2
  61. data/rmagick.gemspec +1 -1
  62. metadata +362 -353
@@ -3,20 +3,20 @@
3
3
  #undef HAVE_ACQUIREMAGICKMEMORY
4
4
  /* Introduced in IM 6.0.0 */
5
5
  #undef HAVE_ACQUIRESTRINGINFO
6
- /* Introduced in IM 5.5.2, GM 1.0 */
7
- #undef HAVE_ADAPTIVETHRESHOLDIMAGE
8
- /* Introduced in GM 1.1 */
6
+ /* GraphicsMagick only */
9
7
  #undef HAVE_ADDDEFINITIONS
8
+ /* Introduced in IM 6.2.5 */
9
+ #undef HAVE_ADDNOISEIMAGECHANNEL
10
10
  /* Introduced in IM 6.0.0, GM 1.1 */
11
11
  #undef HAVE_ALLCHANNELS
12
- /* Introduced in IM 5.5.2, GM 1.0 */
13
- #undef HAVE_APPENDIMAGETOLIST
14
12
  /* Introduced in IM 6.0.0 */
15
13
  #undef HAVE_BILEVELIMAGECHANNEL
16
14
  /* Introduced in IM 5.5.7, GM 1.1 */
17
15
  #undef HAVE_BLACKTHRESHOLDIMAGE
18
16
  /* Introduced in IM 6.0.1 */
19
17
  #undef HAVE_BLURIMAGECHANNEL
18
+ /* Introduced in GM 1.2 */
19
+ #undef HAVE_CINEONLOGRGBCOLORSPACE
20
20
  /* Introduced in IM 6.0.0 */
21
21
  #undef HAVE_COLORDODGECOMPOSITEOP
22
22
  /* Introduced in IM 6.0.0, GM 1.1 */
@@ -25,8 +25,6 @@
25
25
  #undef HAVE_CONVOLVEIMAGECHANNEL
26
26
  /* Introduced in IM 5.5.7, GM 1.1 */
27
27
  #undef HAVE_COPYCYANCOMPOSITEOP
28
- /* Introduced in IM 5.5.1, GM 1.0 */
29
- #undef HAVE_DISPOSETYPE
30
28
  /* Introduced in IM 6.0.0 */
31
29
  #undef HAVE_DSTCOMPOSITEOP
32
30
  /* Introduced in IM 6.0.1 */
@@ -39,7 +37,7 @@
39
37
  /* Introduced in IM 5.5.2, deprecated in IM 6.0.0 */
40
38
  #undef HAVE_EXTENDEDSIGNEDINTEGRALTYPE
41
39
  #undef HAVE_EXTENDEDUNSIGNEDINTEGRALTYPE
42
- /* Introduced in IM 5.5.5 */
40
+ /* Introduced in IM 5.5.5 - Not defined in GraphicsMagick */
43
41
  #undef HAVE_FUZZYCOLORCOMPARE
44
42
  /* Introduced in IM 6.0.0, GM 1.1 */
45
43
  #undef HAVE_GAMMAIMAGECHANNEL
@@ -73,10 +71,6 @@
73
71
  #undef HAVE_OLD_GETIMAGEQUANTUMDEPTH
74
72
  /* Introduced in GM 1.1 */
75
73
  #undef HAVE_GETIMAGESTATISTICS
76
- /* Introduced in IM 5.5.2, GM 1.0 */
77
- #undef HAVE_GETLOCALEEXCEPTIONMESSAGE
78
- /* Introduced in IM 5.5.1, GM 1.0 */
79
- #undef HAVE_GETMAGICKGEOMETRY
80
74
  /* Introduced in GM 1.1 */
81
75
  #undef HAVE_GETMAGICKINFOARRAY
82
76
  /* Introduced in IM 6.0.1 */
@@ -85,8 +79,8 @@
85
79
  #undef HAVE_GETMULTILINETYPEMETRICS
86
80
  /* API changed in IM 6.1.3 */
87
81
  #undef HAVE_OLD_GETMAGICKINFOLIST
82
+ /* Introduced in IM 6.2.1 */
88
83
  #undef HAVE_GETNEXTIMAGEATTRIBUTE
89
- #undef HAVE_GETNEXTIMAGEINLIST
90
84
  /* Introduced in IM 6.0.0 */
91
85
  #undef HAVE_GETNEXTIMAGEPROFILE
92
86
  /* Introduced in IM 6.0.1 */
@@ -96,31 +90,29 @@
96
90
  #undef HAVE_GRAYCHANNEL
97
91
  /* Introduced in GM 1.0 */
98
92
  #undef HAVE_GRAYSCALEPSEUDOCLASSIMAGE
99
- /* Introduced in IM 6.0.0 */
93
+ /* Introduced in IM 6.0.0 - Not available in GM */
100
94
  #undef HAVE_HSBCOLORSPACE
101
- /* Introduced in IM 5.5.7, GM 1.0 */
102
- #undef HAVE_HSLCOLORSPACE
103
- /* Introduced in IM 5.5.7, GM 1.0 */
104
- #undef HAVE_HWBCOLORSPACE
105
- /* Introduced in IM 6.0.0, GM 1.1 */
106
95
  #undef HAVE_INDEXCHANNEL
107
- /* Introduced in IM 5.5.6 */
96
+ /* Introduced in IM 5.5.6 - Not available in GM */
108
97
  #undef HAVE_IMAGE_EXTRACT_INFO
109
98
  /* Introduced in IM 6.0.0 */
110
99
  #undef HAVE_IMAGE_QUALITY
111
100
  /* Introduced in IM 6.0.0 */
112
101
  #undef HAVE_IMAGE_ORIENTATION
102
+ #undef HAVE_IMAGEINFO_ORIENTATION
113
103
  /* Introduced in IM 6.2.4 */
114
104
  #undef HAVE_IMAGE_TICKS_PER_SECOND
115
- /* Introduced in IM 5.5.6 */
116
- #undef HAVE_IMAGEINFO_NUMBER_SCENES
117
105
  /* Introduced in IM 5.5.7, GM 1.1 */
118
106
  #undef HAVE_IMPORTIMAGEPIXELS
119
107
  #undef HAVE_INTTYPES_H
108
+ /* Introduced in IM 6.2.5 */
109
+ #undef HAVE_ISCOLORSIMILAR
120
110
  /* Introduced in IM 6.2.2 */
121
111
  #undef HAVE_JPEG2000COMPRESSION
122
- /* Introduced in IM 5.5.3, GM 1.0 */
123
- #undef HAVE_LEVELIMAGECHANNEL
112
+ /* Introduced in GM 1.2 */
113
+ #undef HAVE_LABCOLORSPACE
114
+ /* Introduced in IM 6.2.3 */
115
+ #undef HAVE_LOGCOLORSPACE
124
116
  /* Introduced in IM 6.0.2 */
125
117
  #undef HAVE_MAGICKBOOLEANTYPE
126
118
  /* Introduced in IM 5.5.3, GM 1.0 */
@@ -133,36 +125,40 @@
133
125
  #undef HAVE_MEMORY_H
134
126
  /* Introduced in IM 6.0.0, GM 1.1 */
135
127
  #undef HAVE_NEGATEIMAGECHANNEL
136
- /* Introduced in IM 5.5.1, GM 1.0 */
137
- #undef HAVE_NOCOMPLIANCE
138
128
  /* Introduced in IM 6.1.0 */
139
129
  #undef HAVE_NORMALIZEIMAGECHANNEL
140
- /* Introduced in IM 5.5.4 */
130
+ /* Introduced in IM 5.5.4 - Not available in GM */
141
131
  #undef HAVE_PARSESIZEGEOMETRY
142
132
  /* Introduced in IM 6.0.0 */
143
133
  #undef HAVE_POSTERIZEIMAGE
144
- /* Introduced in IM 5.5.1, GM 1.0 */
134
+ /* Introduced in IM 5.5.1? Not available in GM */
145
135
  #undef HAVE_PREVIEWIMAGE
146
136
  #undef HAVE_QUANTUMOPERATORREGIONIMAGE
147
137
  /* Introduced in IM 6.2.0 */
148
138
  #undef HAVE_QUANTUMPIXEL
139
+ /* Not available in GM */
149
140
  #undef HAVE_RADIALBLURIMAGE
150
141
  #undef HAVE_RANDOMCHANNELTHRESHOLDIMAGE
151
142
  #undef HAVE_RANDOMTHRESHOLDIMAGECHANNEL
152
- #undef HAVE_REMOVEFIRSTIMAGEFROMLIST
143
+ /* Introduced in GM 1.2 & IM 6.2.2 */
144
+ #undef HAVE_REC601LUMACOLORSPACE
145
+ #undef HAVE_REC601YCBCRCOLORSPACE
146
+ #undef HAVE_REC709LUMACOLORSPACE
147
+ #undef HAVE_REC709YCBCRCOLORSPACE
153
148
  /* Introduced in IM 6.2.1 */
154
149
  #undef HAVE_NEW_REMOVEIMAGEPROFILE
155
150
  #undef HAVE_REPLACECOMPOSITEOP
156
151
  #undef HAVE_SEPARATEIMAGECHANNEL
157
152
  /* Introduced in IM 6.2.1 */
158
153
  #undef HAVE_SEPIATONEIMAGE
154
+ /* Introduced in IM 6.2.1 */
155
+ #undef HAVE_SETIMAGEBACKGROUNDCOLOR
159
156
  #undef HAVE_SETIMAGECOLORSPACE
160
157
  /* Introduced in IM 6.0.0, GM 1.1 */
161
158
  #undef HAVE_SETIMAGECHANNELDEPTH
162
159
  #undef HAVE_SETIMAGEOPTION
163
160
  /* Introduced in IM 6.1.0 */
164
161
  #undef HAVE_SETIMAGEPROGRESSMONITOR
165
- #undef HAVE_SETLOGFORMAT
166
162
  /* Introduced in IM 6.1.7 */
167
163
  #undef HAVE_SHADOWIMAGE
168
164
  /* Introduced in IM 6.0.1 */
@@ -179,7 +175,6 @@
179
175
  #undef HAVE_SYS_STAT_H
180
176
  #undef HAVE_SYS_TYPES_H
181
177
  #undef HAVE_THRESHOLDIMAGECHANNEL
182
- #undef HAVE_THUMBNAILIMAGE
183
178
  #undef HAVE_TINTIMAGE
184
179
  /* Introduced in IM 6.2.4 */
185
180
  #undef HAVE_TRANSPARENTVIRTUALPIXELMETHOD
@@ -189,6 +184,8 @@
189
184
  /* Introduced in IM 6.1.0 */
190
185
  #undef HAVE_UNSHARPMASKIMAGECHANNEL
191
186
  #undef HAVE_WHITETHRESHOLDIMAGE
187
+ /* Introduced in IM 6.2.6 */
188
+ #undef HAVE_VIGNETTEIMAGE
192
189
  #undef HAVE_XIMPORTIMAGE
193
190
  #undef MAGICKNAME
194
191
  #undef PACKAGE_BUGREPORT
@@ -1,6 +1,6 @@
1
- /* $Id: rmdraw.c,v 1.23 2005/06/24 22:31:33 rmagick Exp $ */
1
+ /* $Id: rmdraw.c,v 1.27 2005/12/31 14:40:50 rmagick Exp $ */
2
2
  /*============================================================================\
3
- | Copyright (C) 2005 by Timothy P. Hunter
3
+ | Copyright (C) 2006 by Timothy P. Hunter
4
4
  | Name: rmdraw.c
5
5
  | Author: Tim Hunter
6
6
  | Purpose: Contains Draw class methods.
@@ -412,8 +412,12 @@ VALUE Draw_annotate(
412
412
  rm_check_frozen(ImageList_cur_image(image_arg));
413
413
  Data_Get_Struct(ImageList_cur_image(image_arg), Image, image);
414
414
 
415
- // Copy text to Draw structure
416
- magick_clone_string(&draw->info->text, STRING_PTR(text));
415
+ // Translate & store in Draw structure
416
+ draw->info->text = TranslateText(NULL, image, STRING_PTR(text));
417
+ if (!draw->info->text)
418
+ {
419
+ rb_raise(rb_eArgError, "no text");
420
+ }
417
421
 
418
422
  // Create geometry string, copy to Draw structure, overriding
419
423
  // any previously existing value.
@@ -1300,14 +1304,18 @@ get_type_metrics(
1300
1304
  }
1301
1305
 
1302
1306
  Data_Get_Struct(self, Draw, draw);
1303
- magick_clone_string(&draw->info->text, text);
1307
+ draw->info->text = TranslateText(NULL, image, text);
1308
+ if (!draw->info->text)
1309
+ {
1310
+ rb_raise(rb_eArgError, "no text to measure");
1311
+ }
1304
1312
 
1305
1313
  okay = (*getter)(image, draw->info, &metrics);
1306
1314
 
1307
1315
  if (!okay)
1308
1316
  {
1309
1317
  rb_raise(rb_eRuntimeError, "Can't measure text. Are the fonts installed? "
1310
- "Check the ImageMagick/GraphicsMagick 'type.xml' configuration file.");
1318
+ "Is the FreeType library installed?");
1311
1319
  }
1312
1320
  return TypeMetric_from_TypeMetric(&metrics);
1313
1321
  }
@@ -1,6 +1,6 @@
1
- /* $Id: rmfill.c,v 1.12 2005/05/06 00:28:41 rmagick Exp $ */
1
+ /* $Id: rmfill.c,v 1.13 2005/12/31 14:40:50 rmagick Exp $ */
2
2
  /*============================================================================\
3
- | Copyright (C) 2005 by Timothy P. Hunter
3
+ | Copyright (C) 2006 by Timothy P. Hunter
4
4
  | Name: rmfill.c
5
5
  | Author: Tim Hunter
6
6
  | Purpose: GradientFill, TextureFill class definitions for RMagick
@@ -1,6 +1,6 @@
1
- /* $Id: rmilist.c,v 1.27 2005/10/13 23:01:29 rmagick Exp $ */
1
+ /* $Id: rmilist.c,v 1.30 2006/01/06 23:55:53 rmagick Exp $ */
2
2
  /*============================================================================\
3
- | Copyright (C) 2005 by Timothy P. Hunter
3
+ | Copyright (C) 2006 by Timothy P. Hunter
4
4
  | Name: rmilist.c
5
5
  | Author: Tim Hunter
6
6
  | Purpose: ImageList class method definitions for RMagick
@@ -36,7 +36,7 @@ ImageList_animate(int argc, VALUE *argv, VALUE self)
36
36
  unsigned int delay;
37
37
 
38
38
  delay = NUM2UINT(argv[0]);
39
- for (img = images; img; img = GET_NEXT_IMAGE(img))
39
+ for (img = images; img; img = GetNextImageInList(img))
40
40
  {
41
41
  img->delay = delay;
42
42
  }
@@ -275,7 +275,7 @@ ImageList_montage(VALUE self)
275
275
  if (montage->compose != UndefinedCompositeOp)
276
276
  {
277
277
  Image *i;
278
- for (i = image_list; i; i = GET_NEXT_IMAGE(i))
278
+ for (i = image_list; i; i = GetNextImageInList(i))
279
279
  {
280
280
  i->compose = montage->compose;
281
281
  }
@@ -321,6 +321,7 @@ ImageList_morph(VALUE self, VALUE nimages)
321
321
  images = rm_images_from_imagelist(self);
322
322
  GetExceptionInfo(&exception);
323
323
  new_images = MorphImages(images, (unsigned long)number_images, &exception);
324
+ rm_split(images);
324
325
  HANDLE_ERROR
325
326
 
326
327
  return rm_imagelist_from_images(new_images);
@@ -368,7 +369,6 @@ VALUE
368
369
  rm_imagelist_from_images(Image *images)
369
370
  {
370
371
  volatile VALUE new_imagelist;
371
- #if defined(HAVE_REMOVEFIRSTIMAGEFROMLIST)
372
372
  Image *image;
373
373
 
374
374
  new_imagelist = rm_imagelist_new();
@@ -378,18 +378,6 @@ rm_imagelist_from_images(Image *images)
378
378
  image = RemoveFirstImageFromList(&images);
379
379
  rm_imagelist_push(new_imagelist, rm_image_new(image));
380
380
  }
381
- #else
382
- Image *image, *next;
383
-
384
- new_imagelist = rm_imagelist_new();
385
-
386
- for (image = images; image; image = next)
387
- {
388
- next = GET_NEXT_IMAGE(image);
389
- image->previous = image->next = NULL;
390
- rm_imagelist_push(new_imagelist, rm_image_new(image));
391
- }
392
- #endif
393
381
 
394
382
  rb_iv_set(new_imagelist, "@scene", INT2FIX(0));
395
383
  return new_imagelist;
@@ -407,9 +395,6 @@ rm_images_from_imagelist(VALUE imagelist)
407
395
  {
408
396
  long x, len;
409
397
  Image *head = NULL;
410
- #if !defined(HAVE_APPENDIMAGETOLIST)
411
- Image *tail = NULL;
412
- #endif
413
398
 
414
399
  Check_Type(imagelist, T_ARRAY);
415
400
  len = rm_imagelist_length(imagelist);
@@ -423,20 +408,7 @@ rm_images_from_imagelist(VALUE imagelist)
423
408
  Image *image;
424
409
 
425
410
  Data_Get_Struct(rb_ary_entry(imagelist, x), Image, image);
426
- #if defined(HAVE_APPENDIMAGETOLIST)
427
411
  AppendImageToList(&head, image);
428
- #else
429
- if (!head)
430
- {
431
- head = image;
432
- }
433
- else
434
- {
435
- image->previous = tail;
436
- tail->next = image;
437
- }
438
- tail = image;
439
- #endif
440
412
  }
441
413
 
442
414
  return head;
@@ -573,7 +545,7 @@ ImageList_to_blob(VALUE self)
573
545
  if (*info->magick != '\0')
574
546
  {
575
547
  Image *img;
576
- for (img = images; img; img = GET_NEXT_IMAGE(img))
548
+ for (img = images; img; img = GetNextImageInList(img))
577
549
  {
578
550
  strncpy(img->magick, info->magick, sizeof(info->magick)-1);
579
551
  }
@@ -657,7 +629,7 @@ ImageList_write(VALUE self, VALUE file)
657
629
 
658
630
  // Copy the filename into each images. Set a scene number to be used if
659
631
  // writing multiple files. (Ref: ImageMagick's utilities/convert.c
660
- for (scene = 0, img = images; img; img = GET_NEXT_IMAGE(img))
632
+ for (scene = 0, img = images; img; img = GetNextImageInList(img))
661
633
  {
662
634
  img->scene = scene++;
663
635
  strcpy(img->filename, info->filename);
@@ -676,7 +648,7 @@ ImageList_write(VALUE self, VALUE file)
676
648
  info->adjoin = True;
677
649
  }
678
650
 
679
- for (img = images; img; img = GET_NEXT_IMAGE(img))
651
+ for (img = images; img; img = GetNextImageInList(img))
680
652
  {
681
653
  (void) WriteImage(info, img);
682
654
  // images will be split before raising an exception
@@ -1,6 +1,6 @@
1
- /* $Id: rmimage.c,v 1.123 2005/09/26 23:37:04 rmagick Exp $ */
1
+ /* $Id: rmimage.c,v 1.139 2006/01/18 00:22:33 rmagick Exp $ */
2
2
  /*============================================================================\
3
- | Copyright (C) 2005 by Timothy P. Hunter
3
+ | Copyright (C) 2006 by Timothy P. Hunter
4
4
  | Name: rmimage.c
5
5
  | Author: Tim Hunter
6
6
  | Purpose: Image class method definitions for RMagick
@@ -26,7 +26,7 @@ typedef Image *(xformer_t)(const Image *, const RectangleInfo *, ExceptionInfo *
26
26
 
27
27
  static VALUE effect_image(VALUE, int, VALUE *, effector_t *);
28
28
  static VALUE rd_image(VALUE, VALUE, reader_t);
29
- static VALUE scale_image(int, int, VALUE *, VALUE, scaler_t *);
29
+ static VALUE scale(int, int, VALUE *, VALUE, scaler_t *);
30
30
  static VALUE cropper(int, int, VALUE *, VALUE);
31
31
  static VALUE xform_image(int, VALUE, VALUE, VALUE, VALUE, VALUE, xformer_t);
32
32
  static VALUE threshold_image(int, VALUE *, VALUE, thresholder_t);
@@ -47,7 +47,6 @@ static ImageAttribute *Next_Attribute;
47
47
  VALUE
48
48
  Image_adaptive_threshold(int argc, VALUE *argv, VALUE self)
49
49
  {
50
- #ifdef HAVE_ADAPTIVETHRESHOLDIMAGE
51
50
  Image *image, *new_image;
52
51
  unsigned long width = 3, height = 3, offset = 0;
53
52
  ExceptionInfo exception;
@@ -72,10 +71,6 @@ Image_adaptive_threshold(int argc, VALUE *argv, VALUE self)
72
71
  new_image = AdaptiveThresholdImage(image, width, height, offset, &exception);
73
72
  HANDLE_ERROR
74
73
  return rm_image_new(new_image);
75
- #else
76
- rm_not_implemented();
77
- return (VALUE)0;
78
- #endif
79
74
  }
80
75
 
81
76
  /*
@@ -87,18 +82,60 @@ VALUE
87
82
  Image_add_noise(VALUE self, VALUE noise)
88
83
  {
89
84
  Image *image, *new_image;
90
- NoiseType nt;
85
+ NoiseType noise_type;
91
86
  ExceptionInfo exception;
92
87
 
93
88
  Data_Get_Struct(self, Image, image);
89
+
94
90
  GetExceptionInfo(&exception);
91
+ VALUE_TO_ENUM(noise, noise_type, NoiseType);
95
92
 
96
- VALUE_TO_ENUM(noise, nt, NoiseType);
97
- new_image = AddNoiseImage(image, nt, &exception);
93
+ new_image = AddNoiseImage(image, noise_type, &exception);
98
94
  HANDLE_ERROR
99
95
  return rm_image_new(new_image);
100
96
  }
101
97
 
98
+ /*
99
+ Method: Image#add_noise_channel(noise_type[,channel...])
100
+ Purpose: add random noise to a copy of the image
101
+ Returns: a new image
102
+ */
103
+ VALUE
104
+ Image_add_noise_channel(int argc, VALUE *argv, VALUE self)
105
+ {
106
+ #if defined(HAVE_ADDNOISEIMAGECHANNEL)
107
+ Image *image, *new_image;
108
+ NoiseType noise_type;
109
+ ExceptionInfo exception;
110
+ ChannelType channels;
111
+
112
+ channels = extract_channels(&argc, argv);
113
+
114
+ // There must be 1 remaining argument.
115
+ if (argc == 0)
116
+ {
117
+ rb_raise(rb_eArgError, "missing noise type argument");
118
+ }
119
+ else if (argc > 1)
120
+ {
121
+ raise_ChannelType_error(argv[argc-1]);
122
+ }
123
+
124
+ Data_Get_Struct(self, Image, image);
125
+ GetExceptionInfo(&exception);
126
+ VALUE_TO_ENUM(argv[0], noise_type, NoiseType);
127
+ channels &= ~OpacityChannel;
128
+
129
+ new_image = AddNoiseImageChannel(image, channels, noise_type, &exception);
130
+ HANDLE_ERROR
131
+ return rm_image_new(new_image);
132
+
133
+ #else
134
+ rm_not_implemented();
135
+ return (VALUE)0;
136
+ #endif
137
+ }
138
+
102
139
  /*
103
140
  Method: Image#affine_transform(affine_matrix)
104
141
  Purpose: transforms an image as dictated by the affine matrix argument
@@ -634,7 +671,7 @@ Image_change_geometry(VALUE self, VALUE geom_arg)
634
671
 
635
672
  return rb_yield(ary);
636
673
 
637
- #elif defined(HAVE_GETMAGICKGEOMETRY)
674
+ #else
638
675
  Image *image;
639
676
  char *geometry;
640
677
  unsigned int flags;
@@ -663,9 +700,6 @@ Image_change_geometry(VALUE self, VALUE geom_arg)
663
700
 
664
701
  return rb_yield(ary);
665
702
 
666
- #else
667
- rm_not_implemented();
668
- return (VALUE)0;
669
703
  #endif
670
704
  }
671
705
 
@@ -1246,7 +1280,7 @@ Image_color_profile(VALUE self)
1246
1280
  }
1247
1281
 
1248
1282
  #else /* !defined(HAVE_ACQUIRESTRINGINFO) */
1249
- const char *str;
1283
+ const unsigned char *str;
1250
1284
  size_t length;
1251
1285
 
1252
1286
  Data_Get_Struct(self, Image, image);
@@ -1256,7 +1290,7 @@ Image_color_profile(VALUE self)
1256
1290
  str = GetImageProfile(image, "icc", &length);
1257
1291
  if (str)
1258
1292
  {
1259
- profile = rb_str_new(str, length);
1293
+ profile = rb_str_new((char *)str, length);
1260
1294
  }
1261
1295
 
1262
1296
  #endif
@@ -1355,7 +1389,7 @@ Image_color_profile_eq(VALUE self, VALUE profile)
1355
1389
  }
1356
1390
  else
1357
1391
  {
1358
- prof = STRING_PTR_LEN(profile, prof_l);
1392
+ prof = (unsigned char *)STRING_PTR_LEN(profile, prof_l);
1359
1393
  (void) SetImageProfile(image, "icc", prof, (size_t)prof_l);
1360
1394
  }
1361
1395
  #endif /* defined(HAVE_SETIMAGEPROFILE) */
@@ -2113,7 +2147,11 @@ Image_constitute(VALUE class, VALUE width_arg, VALUE height_arg
2113
2147
  }
2114
2148
  image->columns = width;
2115
2149
  image->rows = height;
2150
+ #if defined(HAVE_SETIMAGEBACKGROUNDCOLOR)
2151
+ SetImageBackgroundColor(image);
2152
+ #else
2116
2153
  SetImage(image, OpaqueOpacity);
2154
+ #endif
2117
2155
  okay = ImportImagePixels(image, 0, 0, width, height, map, stg_type, (void *)pixels.v);
2118
2156
  if (!okay)
2119
2157
  {
@@ -2977,41 +3015,57 @@ Image_erase_bang(VALUE self)
2977
3015
 
2978
3016
  rm_check_frozen(self);
2979
3017
  Data_Get_Struct(self, Image, image);
3018
+
3019
+ #if defined(HAVE_SETIMAGEBACKGROUNDCOLOR)
3020
+ SetImageBackgroundColor(image);
3021
+ #else
2980
3022
  SetImage(image, OpaqueOpacity);
3023
+ #endif
2981
3024
 
2982
3025
  return self;
2983
3026
  }
2984
3027
 
2985
3028
  /*
2986
- Method: Image#export_pixels
3029
+ Method: Image#export_pixels(x=0, y=0, cols=self.columns, rows=self.rows, map="RGB")
2987
3030
  Purpose: extract image pixels in the form of an array
2988
3031
  */
2989
3032
  VALUE
2990
- Image_export_pixels(
2991
- VALUE self,
2992
- VALUE x_arg,
2993
- VALUE y_arg,
2994
- VALUE cols_arg,
2995
- VALUE rows_arg,
2996
- VALUE map_arg)
3033
+ Image_export_pixels(int argc, VALUE *argv, VALUE self)
2997
3034
  {
2998
3035
  #if defined(HAVE_EXPORTIMAGEPIXELS)
2999
3036
  Image *image;
3000
- long x_off, y_off;
3037
+ long x_off = 0L, y_off = 0L;
3001
3038
  unsigned long cols, rows;
3002
3039
  unsigned long n, npixels;
3003
3040
  unsigned int okay;
3004
- char *map;
3041
+ char *map = "RGB";
3005
3042
  volatile unsigned int *pixels;
3006
3043
  volatile VALUE ary;
3007
3044
  ExceptionInfo exception;
3008
3045
 
3009
3046
 
3010
3047
  Data_Get_Struct(self, Image, image);
3011
- x_off = NUM2LONG(x_arg);
3012
- y_off = NUM2LONG(y_arg);
3013
- cols = NUM2ULONG(cols_arg);
3014
- rows = NUM2ULONG(rows_arg);
3048
+ cols = image->columns;
3049
+ rows = image->rows;
3050
+
3051
+ switch (argc)
3052
+ {
3053
+ case 5:
3054
+ map = STRING_PTR(argv[4]);
3055
+ case 4:
3056
+ rows = NUM2ULONG(argv[3]);
3057
+ case 3:
3058
+ cols = NUM2ULONG(argv[2]);
3059
+ case 2:
3060
+ y_off = NUM2LONG(argv[1]);
3061
+ case 1:
3062
+ x_off = NUM2LONG(argv[0]);
3063
+ case 0:
3064
+ break;
3065
+ default:
3066
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 to 5)", argc);
3067
+ break;
3068
+ }
3015
3069
 
3016
3070
  if ( x_off < 0 || x_off > image->columns
3017
3071
  || y_off < 0 || y_off > image->rows
@@ -3020,7 +3074,6 @@ Image_export_pixels(
3020
3074
  rb_raise(rb_eArgError, "invalid extract geometry");
3021
3075
  }
3022
3076
 
3023
- map = STRING_PTR(map_arg);
3024
3077
 
3025
3078
  npixels = cols * rows * strlen(map);
3026
3079
  pixels = ALLOC_N(unsigned int, npixels);
@@ -3057,6 +3110,118 @@ Image_export_pixels(
3057
3110
  #endif
3058
3111
  }
3059
3112
 
3113
+ /*
3114
+ Method: Image#export_pixels_to_str(x=0, y=0, cols=self.columns,
3115
+ rows=self.rows, map="RGB", type=Magick::CharPixel)
3116
+ Purpose: extract image pixels to a Ruby string
3117
+ */
3118
+ VALUE
3119
+ Image_export_pixels_to_str(int argc, VALUE *argv, VALUE self)
3120
+ {
3121
+ #if defined(HAVE_EXPORTIMAGEPIXELS)
3122
+ Image *image;
3123
+ long x_off = 0L, y_off = 0L;
3124
+ unsigned long cols, rows;
3125
+ unsigned long npixels;
3126
+ size_t sz;
3127
+ unsigned int okay;
3128
+ char *map = "RGB";
3129
+ StorageType type = CharPixel;
3130
+ volatile VALUE string;
3131
+ char *str;
3132
+ ExceptionInfo exception;
3133
+
3134
+ Data_Get_Struct(self, Image, image);
3135
+ cols = image->columns;
3136
+ rows = image->rows;
3137
+
3138
+ switch (argc)
3139
+ {
3140
+ case 6:
3141
+ VALUE_TO_ENUM(argv[5], type, StorageType);
3142
+ case 5:
3143
+ map = STRING_PTR(argv[4]);
3144
+ case 4:
3145
+ rows = NUM2ULONG(argv[3]);
3146
+ case 3:
3147
+ cols = NUM2ULONG(argv[2]);
3148
+ case 2:
3149
+ y_off = NUM2LONG(argv[1]);
3150
+ case 1:
3151
+ x_off = NUM2LONG(argv[0]);
3152
+ case 0:
3153
+ break;
3154
+ default:
3155
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 to 6)", argc);
3156
+ break;
3157
+ }
3158
+
3159
+ if ( x_off < 0 || x_off > image->columns
3160
+ || y_off < 0 || y_off > image->rows
3161
+ || cols == 0 || rows == 0)
3162
+ {
3163
+ rb_raise(rb_eArgError, "invalid extract geometry");
3164
+ }
3165
+
3166
+
3167
+ npixels = cols * rows * strlen(map);
3168
+ switch (type)
3169
+ {
3170
+ case CharPixel:
3171
+ sz = sizeof(unsigned char);
3172
+ break;
3173
+ case ShortPixel:
3174
+ sz = sizeof(unsigned short);
3175
+ break;
3176
+ case DoublePixel:
3177
+ sz = sizeof(double);
3178
+ break;
3179
+ case FloatPixel:
3180
+ sz = sizeof(float);
3181
+ break;
3182
+ case IntegerPixel:
3183
+ sz = sizeof(unsigned int);
3184
+ break;
3185
+ case LongPixel:
3186
+ sz = sizeof(unsigned long);
3187
+ break;
3188
+ #if defined(HAVE_QUANTUMPIXEL)
3189
+ case QuantumPixel:
3190
+ sz = sizeof(Quantum);
3191
+ break;
3192
+ #endif
3193
+ case UndefinedPixel:
3194
+ default:
3195
+ rb_raise(rb_eArgError, "undefined storage type");
3196
+ break;
3197
+ }
3198
+
3199
+ // Allocate a string long enough to hold the exported pixel data.
3200
+ // Get a pointer to the buffer.
3201
+ string = rb_str_new2("");
3202
+ rb_str_resize(string, (long)(sz * npixels));
3203
+ str = STRING_PTR(string);
3204
+
3205
+ GetExceptionInfo(&exception);
3206
+
3207
+ okay = ExportImagePixels(image, x_off, y_off, cols, rows, map, type, (void *)str, &exception);
3208
+ if (!okay)
3209
+ {
3210
+ // Let GC have the string buffer.
3211
+ rb_str_resize(string, 0);
3212
+ HANDLE_ERROR
3213
+ // Should never get here...
3214
+ rb_raise(rb_eStandardError, "ExportImagePixels failed with no explanation.");
3215
+ }
3216
+
3217
+ return string;
3218
+
3219
+ #else
3220
+ rm_not_implemented();
3221
+ return (VALUE)0;
3222
+ #endif
3223
+ }
3224
+
3060
3225
  /*
3061
3226
  Method: Image#extract_info, extract_info=
3062
3227
  Purpose: the extract_info attribute accessors
@@ -3760,7 +3925,7 @@ VALUE
3760
3925
  Image_import_pixels(int argc, VALUE *argv, VALUE self)
3761
3926
  {
3762
3927
  #if defined(HAVE_IMPORTIMAGEPIXELS)
3763
- Image *image, *clone_image;
3928
+ Image *image;
3764
3929
  long x_off, y_off;
3765
3930
  unsigned long cols, rows;
3766
3931
  unsigned long npixels;
@@ -3772,7 +3937,6 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
3772
3937
  volatile int *pixels = NULL;
3773
3938
  volatile void *buffer;
3774
3939
  unsigned int okay;
3775
- ExceptionInfo exception;
3776
3940
 
3777
3941
  rm_check_frozen(self);
3778
3942
 
@@ -3883,15 +4047,9 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
3883
4047
  }
3884
4048
 
3885
4049
 
3886
- // Import into a clone - ImportImagePixels destroys the input image if an error occurs.
3887
- GetExceptionInfo(&exception);
3888
- clone_image = CloneImage(image, 0, 0, True, &exception);
3889
- HANDLE_ERROR
4050
+ okay = ImportImagePixels(image, x_off, y_off, cols, rows, map, stg_type, (const void *)buffer);
3890
4051
 
3891
- okay = ImportImagePixels(clone_image, x_off, y_off, cols, rows, map, stg_type, (const void *)buffer);
3892
-
3893
- // Free pixel array before checking for errors. If an error occurred, ImportImagePixels
3894
- // destroyed the clone image, so we don't have to.
4052
+ // Free pixel array before checking for errors.
3895
4053
  if (pixels)
3896
4054
  {
3897
4055
  xfree((void *)pixels);
@@ -3899,15 +4057,11 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
3899
4057
 
3900
4058
  if (!okay)
3901
4059
  {
3902
- HANDLE_ERROR_IMG(clone_image)
4060
+ HANDLE_ERROR_IMG(image)
3903
4061
  // Shouldn't get here...
3904
4062
  rb_raise(rb_eStandardError, "ImportImagePixels failed with no explanation.");
3905
4063
  }
3906
4064
 
3907
- // Everything worked. Replace the image with the clone and destroy the original.
3908
- DATA_PTR(self) = clone_image;
3909
- DestroyImage(image);
3910
-
3911
4065
  return self;
3912
4066
 
3913
4067
  #else
@@ -3942,11 +4096,7 @@ Image_inspect(VALUE self)
3942
4096
  // Print current filename.
3943
4097
  x += sprintf(buffer+x, "%s", image->filename);
3944
4098
  // Print scene number.
3945
- #if defined(HAVE_GETNEXTIMAGEINLIST)
3946
4099
  if ((GetPreviousImageInList(image) != NULL) && (GetNextImageInList(image) != NULL) && image->scene > 0)
3947
- #else
3948
- if ((image->previous || image->next) && image->scene > 0)
3949
- #endif
3950
4100
  {
3951
4101
  x += sprintf(buffer+x, "[%lu]", image->scene);
3952
4102
  }
@@ -4123,7 +4273,7 @@ Image_iptc_profile(VALUE self)
4123
4273
  prof = GetImageProfile(image, "iptc", &length);
4124
4274
  if (prof)
4125
4275
  {
4126
- profile = rb_str_new(prof, (long) length);
4276
+ profile = rb_str_new((char *)prof, (long) length);
4127
4277
  }
4128
4278
  #endif
4129
4279
 
@@ -4220,7 +4370,7 @@ Image_iptc_profile_eq(VALUE self, VALUE profile)
4220
4370
  }
4221
4371
  else
4222
4372
  {
4223
- prof = STRING_PTR_LEN(profile, prof_l);
4373
+ prof = (unsigned char *)STRING_PTR_LEN(profile, prof_l);
4224
4374
  (void) SetImageProfile(image, "iptc", prof, (size_t)prof_l);
4225
4375
  }
4226
4376
  #endif
@@ -4311,7 +4461,6 @@ Image_level(int argc, VALUE *argv, VALUE self)
4311
4461
  VALUE
4312
4462
  Image_level_channel(int argc, VALUE *argv, VALUE self)
4313
4463
  {
4314
- #ifdef HAVE_LEVELIMAGECHANNEL
4315
4464
  Image *image, *new_image;
4316
4465
  double black_point = 0.0, mid_point = 1.0, white_point = (double)MaxRGB;
4317
4466
  ChannelType channel;
@@ -4353,10 +4502,6 @@ Image_level_channel(int argc, VALUE *argv, VALUE self)
4353
4502
  , white_point);
4354
4503
  HANDLE_ERROR_IMG(new_image)
4355
4504
  return rm_image_new(new_image);
4356
- #else
4357
- rm_not_implemented();
4358
- return (VALUE)0;
4359
- #endif
4360
4505
  }
4361
4506
 
4362
4507
  /*
@@ -4985,7 +5130,11 @@ Image_initialize(VALUE self, VALUE info_obj, VALUE width, VALUE height, VALUE fi
4985
5130
  // specifying it when creating the Info parm block.
4986
5131
  if (!fill)
4987
5132
  {
5133
+ #if defined(HAVE_SETIMAGEBACKGROUNDCOLOR)
5134
+ SetImageBackgroundColor(image);
5135
+ #else
4988
5136
  SetImage(image, OpaqueOpacity);
5137
+ #endif
4989
5138
  }
4990
5139
  // fillobj.fill(self)
4991
5140
  else
@@ -5254,23 +5403,54 @@ Image_opaque_q(VALUE self)
5254
5403
  }
5255
5404
 
5256
5405
  /*
5257
- Method: Image#ordered_dither
5258
- Purpose: call OrderedDitherImage
5406
+ Method: Image#ordered_dither(order=2)
5407
+ Purpose: perform ordered dither on image
5408
+ Notes: order must be 2, 3, or 4
5409
+ I don't call OrderedDitherImages anymore. Sometime after
5410
+ IM 6.0.0 it quit working. IM and GM use the routines I use
5411
+ below to implement the "ordered-dither" option.
5259
5412
  */
5260
5413
  VALUE
5261
- Image_ordered_dither(VALUE self)
5414
+ Image_ordered_dither(int argc, VALUE *argv, VALUE self)
5262
5415
  {
5263
5416
  Image *image, *new_image;
5417
+ int order;
5418
+ const char *thresholds = "2x2";
5264
5419
  ExceptionInfo exception;
5265
5420
 
5421
+ if (argc > 1)
5422
+ {
5423
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc);
5424
+ }
5425
+ if (argc == 1)
5426
+ {
5427
+ order = NUM2INT(argv[0]);
5428
+ if (order == 3)
5429
+ {
5430
+ thresholds = "3x3";
5431
+ }
5432
+ else if (order == 4)
5433
+ {
5434
+ thresholds = "4x4";
5435
+ }
5436
+ else if (order != 2)
5437
+ {
5438
+ rb_raise(rb_eArgError, "order must be 2, 3, or 4 (%d given)", order);
5439
+ }
5440
+ }
5441
+
5442
+
5266
5443
  Data_Get_Struct(self, Image, image);
5267
5444
  GetExceptionInfo(&exception);
5268
5445
 
5269
5446
  new_image = CloneImage(image, 0, 0, True, &exception);
5270
5447
  HANDLE_ERROR
5271
-
5272
- (void) OrderedDitherImage(new_image);
5273
- HANDLE_ERROR_IMG(new_image)
5448
+ #if defined(HAVE_RANDOMTHRESHOLDIMAGECHANNEL)
5449
+ (void) RandomThresholdImageChannel(new_image, AllChannels, thresholds, &exception);
5450
+ #else
5451
+ (void) RandomChannelThresholdImage(new_image, "all", thresholds, &exception);
5452
+ #endif
5453
+ HANDLE_ERROR
5274
5454
  return rm_image_new(new_image);
5275
5455
  }
5276
5456
 
@@ -6174,18 +6354,11 @@ static VALUE array_from_images(Image *images)
6174
6354
  // Orphan the image, create an Image object, add it to the array.
6175
6355
 
6176
6356
  image_ary = rb_ary_new();
6177
- #ifdef HAVE_REMOVEFIRSTIMAGEFROMLIST
6357
+ next = NULL;
6178
6358
  next = next; // defeat "never referenced" message from icc
6179
6359
  while (images)
6180
6360
  {
6181
6361
  image = RemoveFirstImageFromList(&images);
6182
-
6183
- #else
6184
- for (image = images; image; image = next)
6185
- {
6186
- next = images->next;
6187
- image->next = image->previous = NULL;
6188
- #endif
6189
6362
  image_obj = rm_image_new(image);
6190
6363
  rb_ary_push(image_ary, image_obj);
6191
6364
  }
@@ -6258,7 +6431,7 @@ resize(int bang, int argc, VALUE *argv, VALUE self)
6258
6431
  double scale;
6259
6432
  FilterTypes filter;
6260
6433
  unsigned long rows, columns;
6261
- double blur;
6434
+ double blur, drows, dcols;
6262
6435
  ExceptionInfo exception;
6263
6436
 
6264
6437
  Data_Get_Struct(self, Image, image);
@@ -6278,11 +6451,25 @@ resize(int bang, int argc, VALUE *argv, VALUE self)
6278
6451
  case 2:
6279
6452
  rows = NUM2ULONG(argv[1]);
6280
6453
  columns = NUM2ULONG(argv[0]);
6454
+ if (columns == 0 || rows == 0)
6455
+ {
6456
+ rb_raise(rb_eArgError, "invalid result dimension (%lu, %lu given)", columns, rows);
6457
+ }
6281
6458
  break;
6282
6459
  case 1:
6283
6460
  scale = NUM2DBL(argv[0]);
6284
- rows = scale * image->rows;
6285
- columns = scale * image->columns;
6461
+ if (scale < 0.0)
6462
+ {
6463
+ rb_raise(rb_eArgError, "invalid scale value (%g given)", scale);
6464
+ }
6465
+ drows = scale * image->rows + 0.5;
6466
+ dcols = scale * image->columns + 0.5;
6467
+ if (drows > ULONG_MAX || dcols > ULONG_MAX)
6468
+ {
6469
+ rb_raise(rb_eRangeError, "resulting image too big");
6470
+ }
6471
+ rows = (unsigned long) drows;
6472
+ columns = (unsigned long) dcols;
6286
6473
  break;
6287
6474
  default:
6288
6475
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 to 4)", argc);
@@ -6386,14 +6573,14 @@ DEF_ATTR_READER(Image, rows, int)
6386
6573
  VALUE
6387
6574
  Image_sample(int argc, VALUE *argv, VALUE self)
6388
6575
  {
6389
- return scale_image(False, argc, argv, self, SampleImage);
6576
+ return scale(False, argc, argv, self, SampleImage);
6390
6577
  }
6391
6578
 
6392
6579
  VALUE
6393
6580
  Image_sample_bang(int argc, VALUE *argv, VALUE self)
6394
6581
  {
6395
6582
  rm_check_frozen(self);
6396
- return scale_image(True, argc, argv, self, SampleImage);
6583
+ return scale(True, argc, argv, self, SampleImage);
6397
6584
  }
6398
6585
 
6399
6586
  /*
@@ -6406,28 +6593,28 @@ Image_sample_bang(int argc, VALUE *argv, VALUE self)
6406
6593
  VALUE
6407
6594
  Image_scale(int argc, VALUE *argv, VALUE self)
6408
6595
  {
6409
- return scale_image(False, argc, argv, self, ScaleImage);
6596
+ return scale(False, argc, argv, self, ScaleImage);
6410
6597
  }
6411
6598
 
6412
6599
  VALUE
6413
6600
  Image_scale_bang(int argc, VALUE *argv, VALUE self)
6414
6601
  {
6415
6602
  rm_check_frozen(self);
6416
- return scale_image(True, argc, argv, self, ScaleImage);
6603
+ return scale(True, argc, argv, self, ScaleImage);
6417
6604
  }
6418
6605
 
6419
6606
  /*
6420
- Static: scale_image
6607
+ Static: scale
6421
6608
  Purpose: Call ScaleImage or SampleImage
6422
6609
  Arguments: if 1 argument > 0, multiply current size by this much
6423
6610
  if 2 arguments, (cols, rows)
6424
6611
  */
6425
6612
  static VALUE
6426
- scale_image(int bang, int argc, VALUE *argv, VALUE self, scaler_t *scaler)
6613
+ scale(int bang, int argc, VALUE *argv, VALUE self, scaler_t *scaler)
6427
6614
  {
6428
6615
  Image *image, *new_image;
6429
6616
  unsigned long columns, rows;
6430
- double scale;
6617
+ double scale, drows, dcols;
6431
6618
  ExceptionInfo exception;
6432
6619
 
6433
6620
  Data_Get_Struct(self, Image, image);
@@ -6437,9 +6624,9 @@ scale_image(int bang, int argc, VALUE *argv, VALUE self, scaler_t *scaler)
6437
6624
  case 2:
6438
6625
  columns = NUM2ULONG(argv[0]);
6439
6626
  rows = NUM2ULONG(argv[1]);
6440
- if (columns <= 0 || rows <= 0)
6627
+ if (columns == 0 || rows == 0)
6441
6628
  {
6442
- rb_raise(rb_eArgError, "invalid scale given (%dl, %dl given)", columns, rows);
6629
+ rb_raise(rb_eArgError, "invalid result dimension (%lu, %lu given)", columns, rows);
6443
6630
  }
6444
6631
  break;
6445
6632
  case 1:
@@ -6448,8 +6635,14 @@ scale_image(int bang, int argc, VALUE *argv, VALUE self, scaler_t *scaler)
6448
6635
  {
6449
6636
  rb_raise(rb_eArgError, "invalid scale value (%g given)", scale);
6450
6637
  }
6451
- rows = image->rows * scale;
6452
- columns = image->columns * scale;
6638
+ drows = scale * image->rows + 0.5;
6639
+ dcols = scale * image->columns + 0.5;
6640
+ if (drows > ULONG_MAX || dcols > ULONG_MAX)
6641
+ {
6642
+ rb_raise(rb_eRangeError, "resulting image too big");
6643
+ }
6644
+ rows = (unsigned long) drows;
6645
+ columns = (unsigned long) dcols;
6453
6646
  break;
6454
6647
  default:
6455
6648
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
@@ -7553,10 +7746,9 @@ VALUE threshold_image(
7553
7746
  static VALUE
7554
7747
  thumbnail(int bang, int argc, VALUE *argv, VALUE self)
7555
7748
  {
7556
- #ifdef HAVE_THUMBNAILIMAGE
7557
7749
  Image *image, *new_image;
7558
7750
  unsigned long columns, rows;
7559
- double scale;
7751
+ double scale, drows, dcols;
7560
7752
  ExceptionInfo exception;
7561
7753
 
7562
7754
  Data_Get_Struct(self, Image, image);
@@ -7566,11 +7758,25 @@ thumbnail(int bang, int argc, VALUE *argv, VALUE self)
7566
7758
  case 2:
7567
7759
  columns = NUM2ULONG(argv[0]);
7568
7760
  rows = NUM2ULONG(argv[1]);
7761
+ if (columns == 0 || rows == 0)
7762
+ {
7763
+ rb_raise(rb_eArgError, "invalid result dimension (%lu, %lu given)", columns, rows);
7764
+ }
7569
7765
  break;
7570
7766
  case 1:
7571
7767
  scale = NUM2DBL(argv[0]);
7572
- rows = scale * image->rows;
7573
- columns = scale * image->columns;
7768
+ if (scale < 0.0)
7769
+ {
7770
+ rb_raise(rb_eArgError, "invalid scale value (%g given)", scale);
7771
+ }
7772
+ drows = scale * image->rows + 0.5;
7773
+ dcols = scale * image->columns + 0.5;
7774
+ if (drows > ULONG_MAX || dcols > ULONG_MAX)
7775
+ {
7776
+ rb_raise(rb_eRangeError, "resulting image too big");
7777
+ }
7778
+ rows = (unsigned long) drows;
7779
+ columns = (unsigned long) dcols;
7574
7780
  break;
7575
7781
  default:
7576
7782
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
@@ -7589,10 +7795,6 @@ thumbnail(int bang, int argc, VALUE *argv, VALUE self)
7589
7795
  }
7590
7796
 
7591
7797
  return rm_image_new(new_image);
7592
- #else
7593
- rm_not_implemented();
7594
- return (VALUE)0;
7595
- #endif
7596
7798
  }
7597
7799
 
7598
7800
  VALUE
@@ -7772,6 +7974,7 @@ Image_to_blob(VALUE self)
7772
7974
  {
7773
7975
  Image *image;
7774
7976
  Info *info;
7977
+ const MagickInfo *magick_info;
7775
7978
  volatile VALUE info_obj;
7776
7979
  volatile VALUE blob_str;
7777
7980
  void *blob = NULL;
@@ -7807,6 +8010,20 @@ Image_to_blob(VALUE self)
7807
8010
  strncpy(image->magick, info->magick, sizeof(info->magick)-1);
7808
8011
  }
7809
8012
 
8013
+ // Fix #2844 - libjpeg exits when image is 0x0
8014
+ magick_info = GetMagickInfo(image->magick, &exception);
8015
+ HANDLE_ERROR
8016
+ if (magick_info)
8017
+ {
8018
+ if ( (!rm_strcasecmp(magick_info->name, "JPEG")
8019
+ || !rm_strcasecmp(magick_info->name, "JPG"))
8020
+ && (image->rows == 0 || image->columns == 0))
8021
+ {
8022
+ rb_raise(rb_eRuntimeError, "Can't convert %lux%lu %.4s image to a blob"
8023
+ , image->columns, image->rows, magick_info->name);
8024
+ }
8025
+ }
8026
+
7810
8027
  blob = ImageToBlob(info, image, &length, &exception);
7811
8028
  HANDLE_ERROR
7812
8029
  if (length == 0 || !blob)
@@ -8134,6 +8351,60 @@ Image_unsharp_mask_channel(int argc, VALUE *argv, VALUE self)
8134
8351
  }
8135
8352
 
8136
8353
 
8354
+ /*
8355
+ Method: Image#vignette(horz_radius, vert_radius, radius, sigma);
8356
+ Purpose: soften the edges of an image
8357
+ Notes: The outer edges of the image are replaced by the background color.
8358
+ */
8359
+ VALUE
8360
+ Image_vignette(int argc, VALUE *argv, VALUE self)
8361
+ {
8362
+ #if defined(HAVE_VIGNETTEIMAGE)
8363
+ Image *image, *new_image;
8364
+ long horz_radius, vert_radius;
8365
+ double radius = 0.0, sigma = 10.0;
8366
+ ExceptionInfo exception;
8367
+
8368
+ Data_Get_Struct(self, Image, image);
8369
+
8370
+ horz_radius = image->columns * 0.10 + 0.5;
8371
+ vert_radius = image->rows * 0.10 + 0.5;
8372
+
8373
+ switch (argc)
8374
+ {
8375
+ case 4:
8376
+ sigma = NUM2DBL(argv[3]);
8377
+ case 3:
8378
+ radius = NUM2DBL(argv[2]);
8379
+ case 2:
8380
+ vert_radius = NUM2INT(argv[1]);
8381
+ case 1:
8382
+ horz_radius = NUM2INT(argv[0]);
8383
+ case 0:
8384
+ break;
8385
+ default:
8386
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 to 4)", argc);
8387
+ break;
8388
+ }
8389
+
8390
+ GetExceptionInfo(&exception);
8391
+
8392
+ new_image = VignetteImage(image, radius, sigma, horz_radius, vert_radius, &exception);
8393
+ HANDLE_ERROR
8394
+ if (!new_image)
8395
+ {
8396
+ rb_raise(rb_eRuntimeError, "VignetteImage failed");
8397
+ }
8398
+
8399
+ return rm_image_new(new_image);
8400
+
8401
+ #else
8402
+ rm_not_implemented();
8403
+ return (VALUE)0;
8404
+ #endif
8405
+ }
8406
+
8407
+
8137
8408
  /*
8138
8409
  Method: Image#virtual_pixel_method
8139
8410
  Purpose: get the VirtualPixelMethod for the image
@@ -8532,12 +8803,14 @@ static ChannelType extract_channels(
8532
8803
  *argc -= 1;
8533
8804
  }
8534
8805
 
8535
- #if defined(HAVE_ALLCHANNELS)
8536
8806
  if (channels == 0)
8537
8807
  {
8808
+ #if defined(HAVE_ALLCHANNELS)
8538
8809
  channels = AllChannels;
8539
- }
8810
+ #else
8811
+ channels = 0xff;
8540
8812
  #endif
8813
+ }
8541
8814
 
8542
8815
  return channels;
8543
8816
  }