rmagick 1.9.0 → 1.9.1
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.
- data/ChangeLog +20 -0
- data/README.html +8 -8
- data/README.txt +6 -6
- data/configure +263 -11
- data/configure.ac +39 -2
- data/doc/constants.html +8 -4
- data/doc/draw.html +0 -4
- data/doc/ex/smile.rb +5 -4
- data/doc/ilist.html +17 -12
- data/doc/image1.html +121 -165
- data/doc/image2.html +185 -65
- data/doc/image3.html +67 -64
- data/doc/imageattrs.html +10 -17
- data/doc/usage.html +6 -12
- data/examples/identify.rb +187 -0
- data/ext/RMagick/MANIFEST +2 -3
- data/ext/RMagick/rmagick.h +6 -2
- data/ext/RMagick/rmagick_config.h.in +5 -0
- data/ext/RMagick/rmilist.c +16 -13
- data/ext/RMagick/rmimage.c +514 -264
- data/ext/RMagick/rmmain.c +25 -5
- data/ext/RMagick/rmutil.c +268 -10
- data/install.rb +5 -2
- data/lib/RMagick.rb +121 -66
- data/rmagick.gemspec +1 -1
- metadata +3 -4
- data/doc/ex/channel_threshold.rb +0 -48
- data/doc/ex/random_channel_threshold.rb +0 -17
data/ext/RMagick/MANIFEST
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
MANIFEST for RMagick-1.9.
|
1
|
+
MANIFEST for RMagick-1.9.1 - 18:06:01 09/07/05
|
2
2
|
|
3
3
|
configure
|
4
4
|
README.html
|
@@ -23,6 +23,7 @@ examples/rotating_text.rb
|
|
23
23
|
examples/pattern_fill.rb
|
24
24
|
examples/import_export.rb
|
25
25
|
examples/image_opacity.rb
|
26
|
+
examples/identify.rb
|
26
27
|
examples/histogram.rb
|
27
28
|
examples/describe.rb
|
28
29
|
uninstall.rb
|
@@ -134,7 +135,6 @@ doc/ex/rectangle.rb
|
|
134
135
|
doc/ex/rect02.rb
|
135
136
|
doc/ex/rect01.rb
|
136
137
|
doc/ex/random_threshold_channel.rb
|
137
|
-
doc/ex/random_channel_threshold.rb
|
138
138
|
doc/ex/raise.rb
|
139
139
|
doc/ex/radial_blur.rb
|
140
140
|
doc/ex/quantize-m.rb
|
@@ -219,7 +219,6 @@ doc/ex/circle01.rb
|
|
219
219
|
doc/ex/circle.rb
|
220
220
|
doc/ex/chop.rb
|
221
221
|
doc/ex/charcoal.rb
|
222
|
-
doc/ex/channel_threshold.rb
|
223
222
|
doc/ex/channel.rb
|
224
223
|
doc/ex/cbezier6.rb
|
225
224
|
doc/ex/cbezier5.rb
|
data/ext/RMagick/rmagick.h
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/* $Id: rmagick.h,v 1.
|
1
|
+
/* $Id: rmagick.h,v 1.92 2005/09/05 20:27:27 rmagick Exp $ */
|
2
2
|
/*=============================================================================
|
3
3
|
| Copyright (C) 2005 by Timothy P. Hunter
|
4
4
|
| Name: rmagick.h
|
@@ -272,6 +272,7 @@ EXTERN VALUE Class_PaintMethod;
|
|
272
272
|
EXTERN VALUE Class_PreviewType;
|
273
273
|
EXTERN VALUE Class_RenderingIntent;
|
274
274
|
EXTERN VALUE Class_ResolutionType;
|
275
|
+
EXTERN VALUE Class_StorageType;
|
275
276
|
EXTERN VALUE Class_StretchType;
|
276
277
|
EXTERN VALUE Class_StyleType;
|
277
278
|
EXTERN VALUE Class_WeightType;
|
@@ -774,7 +775,7 @@ extern VALUE Image_get_pixels(VALUE, VALUE, VALUE, VALUE, VALUE);
|
|
774
775
|
extern VALUE Image_gray_q(VALUE);
|
775
776
|
extern VALUE Image_grayscale_pseudo_class(int, VALUE *, VALUE);
|
776
777
|
extern VALUE Image_implode(int, VALUE *, VALUE);
|
777
|
-
extern VALUE Image_import_pixels(
|
778
|
+
extern VALUE Image_import_pixels(int, VALUE *, VALUE);
|
778
779
|
extern VALUE Image_init_copy(VALUE, VALUE);
|
779
780
|
extern VALUE Image_inspect(VALUE);
|
780
781
|
extern VALUE Image_level(int, VALUE *, VALUE);
|
@@ -893,7 +894,9 @@ extern VALUE Color_to_s(VALUE);
|
|
893
894
|
extern VALUE Color_from_ColorInfo(const ColorInfo *);
|
894
895
|
extern VALUE ClassType_new(ClassType);
|
895
896
|
extern VALUE ColorspaceType_new(ColorspaceType);
|
897
|
+
extern VALUE CompositeOperator_new(CompositeOperator);
|
896
898
|
extern VALUE CompressionType_new(CompressionType);
|
899
|
+
extern VALUE DisposeType_new(DisposeType);
|
897
900
|
extern VALUE EndianType_new(EndianType);
|
898
901
|
extern VALUE FilterTypes_new(FilterTypes);
|
899
902
|
extern VALUE Font_to_s(VALUE);
|
@@ -955,6 +958,7 @@ extern VALUE Statistics_new(ImageStatistics *);
|
|
955
958
|
#if defined(HAVE_IMAGE_ORIENTATION)
|
956
959
|
extern VALUE OrientationType_new(OrientationType);
|
957
960
|
#endif
|
961
|
+
extern const char *StorageType_name(StorageType);
|
958
962
|
|
959
963
|
#if defined(HAVE_RB_DEFINE_ALLOC_FUNC)
|
960
964
|
extern VALUE Enum_alloc(VALUE);
|
@@ -81,6 +81,7 @@
|
|
81
81
|
#undef HAVE_GETMULTILINETYPEMETRICS
|
82
82
|
/* API changed in IM 6.1.3 */
|
83
83
|
#undef HAVE_OLD_GETMAGICKINFOLIST
|
84
|
+
#undef HAVE_GETNEXTIMAGEATTRIBUTE
|
84
85
|
#undef HAVE_GETNEXTIMAGEINLIST
|
85
86
|
/* Introduced in IM 6.0.0 */
|
86
87
|
#undef HAVE_GETNEXTIMAGEPROFILE
|
@@ -88,6 +89,7 @@
|
|
88
89
|
#undef HAVE_GETTYPEINFOLIST
|
89
90
|
/* API changed in IM 6.1.3 */
|
90
91
|
#undef HAVE_OLD_GETTYPEINFOLIST
|
92
|
+
#undef HAVE_GRAYCHANNEL
|
91
93
|
/* Introduced in GM 1.0 */
|
92
94
|
#undef HAVE_GRAYSCALEPSEUDOCLASSIMAGE
|
93
95
|
/* Introduced in IM 6.0.0 */
|
@@ -104,6 +106,7 @@
|
|
104
106
|
#undef HAVE_IMAGE_QUALITY
|
105
107
|
/* Introduced in IM 6.0.0 */
|
106
108
|
#undef HAVE_IMAGE_ORIENTATION
|
109
|
+
#undef HAVE_IMAGE_STORAGE_CLASS
|
107
110
|
/* Introduced in IM 5.5.6 */
|
108
111
|
#undef HAVE_IMAGEINFO_NUMBER_SCENES
|
109
112
|
/* Introduced in IM 5.5.7, GM 1.1 */
|
@@ -136,6 +139,8 @@
|
|
136
139
|
/* Introduced in IM 5.5.1, GM 1.0 */
|
137
140
|
#undef HAVE_PREVIEWIMAGE
|
138
141
|
#undef HAVE_QUANTUMOPERATORREGIONIMAGE
|
142
|
+
/* Introduced in IM 6.2.0 */
|
143
|
+
#undef HAVE_QUANTUMPIXEL
|
139
144
|
#undef HAVE_RADIALBLURIMAGE
|
140
145
|
#undef HAVE_RANDOMCHANNELTHRESHOLDIMAGE
|
141
146
|
#undef HAVE_RANDOMTHRESHOLDIMAGECHANNEL
|
data/ext/RMagick/rmilist.c
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/* $Id: rmilist.c,v 1.
|
1
|
+
/* $Id: rmilist.c,v 1.25 2005/08/07 21:21:08 rmagick Exp $ */
|
2
2
|
/*============================================================================\
|
3
3
|
| Copyright (C) 2005 by Timothy P. Hunter
|
4
4
|
| Name: rmilist.c
|
@@ -75,8 +75,8 @@ ImageList_append(VALUE self, VALUE stack_arg)
|
|
75
75
|
|
76
76
|
GetExceptionInfo(&exception);
|
77
77
|
result = AppendImages(images, stack, &exception);
|
78
|
-
HANDLE_ERROR
|
79
78
|
rm_split(images);
|
79
|
+
HANDLE_ERROR
|
80
80
|
|
81
81
|
return rm_image_new(result);
|
82
82
|
}
|
@@ -122,8 +122,8 @@ ImageList_coalesce(VALUE self)
|
|
122
122
|
|
123
123
|
GetExceptionInfo(&exception);
|
124
124
|
results = CoalesceImages(images, &exception);
|
125
|
-
HANDLE_ERROR
|
126
125
|
rm_split(images);
|
126
|
+
HANDLE_ERROR
|
127
127
|
|
128
128
|
return rm_imagelist_from_images(results);
|
129
129
|
}
|
@@ -145,8 +145,8 @@ ImageList_deconstruct(VALUE self)
|
|
145
145
|
images = rm_images_from_imagelist(self);
|
146
146
|
GetExceptionInfo(&exception);
|
147
147
|
new_images = DeconstructImages(images, &exception);
|
148
|
-
HANDLE_ERROR
|
149
148
|
rm_split(images);
|
149
|
+
HANDLE_ERROR
|
150
150
|
|
151
151
|
return rm_imagelist_from_images(new_images);
|
152
152
|
}
|
@@ -195,8 +195,8 @@ ImageList_flatten_images(VALUE self)
|
|
195
195
|
images = rm_images_from_imagelist(self);
|
196
196
|
GetExceptionInfo(&exception);
|
197
197
|
new_image = FlattenImages(images, &exception);
|
198
|
-
HANDLE_ERROR
|
199
198
|
rm_split(images);
|
199
|
+
HANDLE_ERROR
|
200
200
|
|
201
201
|
return rm_image_new(new_image);
|
202
202
|
}
|
@@ -228,8 +228,8 @@ ImageList_map(VALUE self, VALUE map_image, VALUE dither_arg)
|
|
228
228
|
images = rm_images_from_imagelist(self);
|
229
229
|
GetExceptionInfo(&exception);
|
230
230
|
clone_images = CloneImageList(images, &exception);
|
231
|
-
HANDLE_ERROR
|
232
231
|
rm_split(images);
|
232
|
+
HANDLE_ERROR
|
233
233
|
|
234
234
|
// Call ImageMagick
|
235
235
|
dither = !(dither_arg == Qfalse || dither_arg == Qnil);
|
@@ -285,8 +285,8 @@ ImageList_montage(VALUE self)
|
|
285
285
|
|
286
286
|
// MontageImage can return more than one image.
|
287
287
|
montage_seq = MontageImages(image_list, montage->info, &exception);
|
288
|
-
HANDLE_ERROR
|
289
288
|
rm_split(image_list);
|
289
|
+
HANDLE_ERROR
|
290
290
|
|
291
291
|
return rm_imagelist_from_images(montage_seq);
|
292
292
|
}
|
@@ -304,13 +304,15 @@ ImageList_morph(VALUE self, VALUE nimages)
|
|
304
304
|
{
|
305
305
|
Image *images, *new_images;
|
306
306
|
ExceptionInfo exception;
|
307
|
-
|
307
|
+
long number_images;
|
308
308
|
|
309
309
|
if (rm_imagelist_length(self) < 1)
|
310
310
|
{
|
311
311
|
rb_raise(rb_eArgError, "no images in this image list");
|
312
312
|
}
|
313
|
-
|
313
|
+
|
314
|
+
// Use a signed long so we can test for a negative argument.
|
315
|
+
number_images = NUM2LONG(nimages);
|
314
316
|
if (number_images <= 0)
|
315
317
|
{
|
316
318
|
rb_raise(rb_eArgError, "number of intervening images must be > 0");
|
@@ -318,7 +320,7 @@ ImageList_morph(VALUE self, VALUE nimages)
|
|
318
320
|
|
319
321
|
images = rm_images_from_imagelist(self);
|
320
322
|
GetExceptionInfo(&exception);
|
321
|
-
new_images = MorphImages(images, number_images, &exception);
|
323
|
+
new_images = MorphImages(images, (unsigned long)number_images, &exception);
|
322
324
|
HANDLE_ERROR
|
323
325
|
|
324
326
|
return rm_imagelist_from_images(new_images);
|
@@ -338,8 +340,8 @@ ImageList_mosaic(VALUE self)
|
|
338
340
|
images = rm_images_from_imagelist(self);
|
339
341
|
GetExceptionInfo(&exception);
|
340
342
|
new_image = MosaicImages(images, &exception);
|
341
|
-
HANDLE_ERROR
|
342
343
|
rm_split(images);
|
344
|
+
HANDLE_ERROR
|
343
345
|
|
344
346
|
return rm_image_new(new_image);
|
345
347
|
}
|
@@ -523,8 +525,8 @@ ImageList_quantize(int argc, VALUE *argv, VALUE self)
|
|
523
525
|
GetExceptionInfo(&exception);
|
524
526
|
images = rm_images_from_imagelist(self);
|
525
527
|
new_images = CloneImageList(images, &exception);
|
526
|
-
HANDLE_ERROR
|
527
528
|
rm_split(images);
|
529
|
+
HANDLE_ERROR
|
528
530
|
|
529
531
|
QuantizeImages(&quantize_info, new_images);
|
530
532
|
|
@@ -583,8 +585,8 @@ ImageList_to_blob(VALUE self)
|
|
583
585
|
info->adjoin = True;
|
584
586
|
GetExceptionInfo(&exception);
|
585
587
|
blob = ImageToBlob(info, images, &length, &exception);
|
586
|
-
HANDLE_ERROR
|
587
588
|
rm_split(images);
|
589
|
+
HANDLE_ERROR
|
588
590
|
|
589
591
|
return (blob && length) ? rb_str_new(blob, length) : Qnil;
|
590
592
|
}
|
@@ -673,6 +675,7 @@ ImageList_write(VALUE self, VALUE file)
|
|
673
675
|
for (img = images; img; img = GET_NEXT_IMAGE(img))
|
674
676
|
{
|
675
677
|
(void) WriteImage(info, img);
|
678
|
+
// images will be split before raising an exception
|
676
679
|
rm_handle_all_errors(images);
|
677
680
|
if (info->adjoin)
|
678
681
|
{
|
data/ext/RMagick/rmimage.c
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/* $Id: rmimage.c,v 1.
|
1
|
+
/* $Id: rmimage.c,v 1.118 2005/09/07 21:51:45 rmagick Exp $ */
|
2
2
|
/*============================================================================\
|
3
3
|
| Copyright (C) 2005 by Timothy P. Hunter
|
4
4
|
| Name: rmimage.c
|
@@ -239,52 +239,6 @@ Image_aset(VALUE self, VALUE key_arg, VALUE attr_arg)
|
|
239
239
|
return self;
|
240
240
|
}
|
241
241
|
|
242
|
-
/*
|
243
|
-
Method: Image#properties [{ |k,v| block }]
|
244
|
-
Purpose: Traverse the attributes and yield to the block.
|
245
|
-
If no block, return a hash of all the attribute
|
246
|
-
keys & values
|
247
|
-
Notes: I use the word "properties" to distinguish between
|
248
|
-
these "user-added" attribute strings and Image
|
249
|
-
object attributes.
|
250
|
-
*/
|
251
|
-
VALUE
|
252
|
-
Image_properties(VALUE self)
|
253
|
-
{
|
254
|
-
Image *image;
|
255
|
-
const ImageAttribute *attr;
|
256
|
-
volatile VALUE attr_hash;
|
257
|
-
|
258
|
-
Data_Get_Struct(self, Image, image);
|
259
|
-
|
260
|
-
// If block, iterate over attributes
|
261
|
-
if (rb_block_given_p())
|
262
|
-
{
|
263
|
-
volatile VALUE ary = rb_ary_new2(2);
|
264
|
-
for (attr = image->attributes; attr; attr = Next_Attribute)
|
265
|
-
{
|
266
|
-
// Store the next ptr where Image#aset can see it.
|
267
|
-
// The app may decide to delete that attribute.
|
268
|
-
Next_Attribute = attr->next;
|
269
|
-
rb_ary_store(ary, 0, rb_str_new2(attr->key));
|
270
|
-
rb_ary_store(ary, 1, rb_str_new2(attr->value));
|
271
|
-
rb_yield(ary);
|
272
|
-
}
|
273
|
-
|
274
|
-
return self;
|
275
|
-
}
|
276
|
-
|
277
|
-
// otherwise return properties hash
|
278
|
-
else
|
279
|
-
{
|
280
|
-
attr_hash = rb_hash_new();
|
281
|
-
for (attr = image->attributes; attr; attr = attr->next)
|
282
|
-
{
|
283
|
-
rb_hash_aset(attr_hash, rb_str_new2(attr->key), rb_str_new2(attr->value));
|
284
|
-
}
|
285
|
-
return attr_hash;
|
286
|
-
}
|
287
|
-
}
|
288
242
|
|
289
243
|
/*
|
290
244
|
Method: Image#background_color
|
@@ -374,9 +328,13 @@ Image_bilevel_channel(int argc, VALUE *argv, VALUE self)
|
|
374
328
|
|
375
329
|
channels = extract_channels(&argc, argv);
|
376
330
|
|
331
|
+
if (argc > 1)
|
332
|
+
{
|
333
|
+
raise_ChannelType_error(argv[argc-1]);
|
334
|
+
}
|
377
335
|
if (argc == 0)
|
378
336
|
{
|
379
|
-
rb_raise(rb_eArgError, "
|
337
|
+
rb_raise(rb_eArgError, "no threshold specified");
|
380
338
|
}
|
381
339
|
|
382
340
|
GetExceptionInfo(&exception);
|
@@ -396,32 +354,21 @@ Image_bilevel_channel(int argc, VALUE *argv, VALUE self)
|
|
396
354
|
|
397
355
|
|
398
356
|
/*
|
399
|
-
|
400
|
-
|
357
|
+
* Method: Image#black_threshold(red_channel [, green_channel
|
358
|
+
* [, blue_channel [, opacity_channel]]]);
|
359
|
+
* Purpose: Call BlackThresholdImage
|
401
360
|
*/
|
402
361
|
VALUE
|
403
|
-
|
362
|
+
Image_black_threshold(int argc, VALUE *argv, VALUE self)
|
404
363
|
{
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
364
|
+
#if defined(HAVE_BLACKTHRESHOLDIMAGE)
|
365
|
+
return threshold_image(argc, argv, self, BlackThresholdImage);
|
366
|
+
#else
|
367
|
+
rm_not_implemented();
|
368
|
+
return (VALUE)0;
|
369
|
+
#endif
|
409
370
|
}
|
410
371
|
|
411
|
-
/*
|
412
|
-
Method: Image#border_color=
|
413
|
-
Purpose: Set the the border color
|
414
|
-
*/
|
415
|
-
VALUE
|
416
|
-
Image_border_color_eq(VALUE self, VALUE color)
|
417
|
-
{
|
418
|
-
Image *image;
|
419
|
-
|
420
|
-
rm_check_frozen(self);
|
421
|
-
Data_Get_Struct(self, Image, image);
|
422
|
-
Color_to_PixelPacket(&image->border_color, color);
|
423
|
-
return self;
|
424
|
-
}
|
425
372
|
|
426
373
|
DEF_ATTR_ACCESSOR(Image, blur, dbl)
|
427
374
|
|
@@ -467,6 +414,7 @@ Image_blur_channel(int argc, VALUE *argv, VALUE self)
|
|
467
414
|
#endif
|
468
415
|
}
|
469
416
|
|
417
|
+
|
470
418
|
/*
|
471
419
|
Method: Image#blur_image(radius=0.0, sigma=1.0)
|
472
420
|
Purpose: Blur the image
|
@@ -478,6 +426,7 @@ Image_blur_image(int argc, VALUE *argv, VALUE self)
|
|
478
426
|
return effect_image(self, argc, argv, BlurImage);
|
479
427
|
}
|
480
428
|
|
429
|
+
|
481
430
|
/*
|
482
431
|
Method: Image#border(width, height, color)
|
483
432
|
Image#border!(width, height, color)
|
@@ -543,6 +492,36 @@ Image_border(
|
|
543
492
|
return border(False, self, width, height, color);
|
544
493
|
}
|
545
494
|
|
495
|
+
|
496
|
+
/*
|
497
|
+
Method: Image#border_color
|
498
|
+
Purpose: Return the name of the border color as a String.
|
499
|
+
*/
|
500
|
+
VALUE
|
501
|
+
Image_border_color(VALUE self)
|
502
|
+
{
|
503
|
+
Image *image;
|
504
|
+
|
505
|
+
Data_Get_Struct(self, Image, image);
|
506
|
+
return PixelPacket_to_Color_Name(image, &image->border_color);
|
507
|
+
}
|
508
|
+
|
509
|
+
/*
|
510
|
+
Method: Image#border_color=
|
511
|
+
Purpose: Set the the border color
|
512
|
+
*/
|
513
|
+
VALUE
|
514
|
+
Image_border_color_eq(VALUE self, VALUE color)
|
515
|
+
{
|
516
|
+
Image *image;
|
517
|
+
|
518
|
+
rm_check_frozen(self);
|
519
|
+
Data_Get_Struct(self, Image, image);
|
520
|
+
Color_to_PixelPacket(&image->border_color, color);
|
521
|
+
return self;
|
522
|
+
}
|
523
|
+
|
524
|
+
|
546
525
|
/*
|
547
526
|
Method: Image#bounding_box
|
548
527
|
Purpose: returns the bounding box of an image canvas
|
@@ -560,6 +539,7 @@ VALUE Image_bounding_box(VALUE self)
|
|
560
539
|
return Rectangle_from_RectangleInfo(&box);
|
561
540
|
}
|
562
541
|
|
542
|
+
|
563
543
|
/*
|
564
544
|
Method: Image.capture(silent=false,
|
565
545
|
frame=false,
|
@@ -689,6 +669,7 @@ Image_change_geometry(VALUE self, VALUE geom_arg)
|
|
689
669
|
#endif
|
690
670
|
}
|
691
671
|
|
672
|
+
|
692
673
|
/*
|
693
674
|
Method: Image#changed?
|
694
675
|
Purpose: Return true if any pixel in the image has been altered since
|
@@ -733,66 +714,6 @@ Image_channel(VALUE self, VALUE channel_arg)
|
|
733
714
|
}
|
734
715
|
|
735
716
|
|
736
|
-
/*
|
737
|
-
Method: Image#compare_channel(ref_image, metric [, channel...])
|
738
|
-
Purpose: compares one or more channels in two images and returns
|
739
|
-
the specified distortion metric and a comparison image.
|
740
|
-
Notes: If no channels are specified, the default is AllChannels.
|
741
|
-
That case is the equivalent of the CompareImages method in
|
742
|
-
ImageMagick.
|
743
|
-
|
744
|
-
Originally this method was called channel_compare, but
|
745
|
-
that doesn't match the general naming convention that
|
746
|
-
methods which accept multiple optional ChannelType
|
747
|
-
arguments have names that end in _channel. So I renamed
|
748
|
-
the method to compare_channel but kept channel_compare as
|
749
|
-
an alias.
|
750
|
-
*/
|
751
|
-
VALUE Image_compare_channel(
|
752
|
-
int argc,
|
753
|
-
VALUE *argv,
|
754
|
-
VALUE self)
|
755
|
-
{
|
756
|
-
#if defined(HAVE_COMPAREIMAGECHANNELS)
|
757
|
-
|
758
|
-
Image *image, *r_image, *difference_image;
|
759
|
-
double distortion;
|
760
|
-
volatile VALUE ary;
|
761
|
-
MetricType metric_type;
|
762
|
-
ChannelType channels;
|
763
|
-
ExceptionInfo exception;
|
764
|
-
|
765
|
-
channels = extract_channels(&argc, argv);
|
766
|
-
if (argc < 2)
|
767
|
-
{
|
768
|
-
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or more)", argc);
|
769
|
-
}
|
770
|
-
|
771
|
-
Data_Get_Struct(self, Image, image);
|
772
|
-
Data_Get_Struct(ImageList_cur_image(argv[0]), Image, r_image);
|
773
|
-
VALUE_TO_ENUM(argv[1], metric_type, MetricType);
|
774
|
-
|
775
|
-
GetExceptionInfo(&exception);
|
776
|
-
difference_image = CompareImageChannels(image
|
777
|
-
, r_image
|
778
|
-
, channels
|
779
|
-
, metric_type
|
780
|
-
, &distortion
|
781
|
-
, &exception);
|
782
|
-
HANDLE_ERROR
|
783
|
-
|
784
|
-
ary = rb_ary_new2(2);
|
785
|
-
rb_ary_store(ary, 0, rm_image_new(difference_image));
|
786
|
-
rb_ary_store(ary, 1, rb_float_new(distortion));
|
787
|
-
|
788
|
-
return ary;
|
789
|
-
#else
|
790
|
-
rm_not_implemented();
|
791
|
-
return (VALUE)0;
|
792
|
-
#endif
|
793
|
-
}
|
794
|
-
|
795
|
-
|
796
717
|
/*
|
797
718
|
Method: Image#channel_depth(channel_depth=AllChannels)
|
798
719
|
Purpose: GetImageChannelDepth
|
@@ -1064,22 +985,6 @@ Image_channel_mean(int argc, VALUE *argv, VALUE self)
|
|
1064
985
|
#endif
|
1065
986
|
}
|
1066
987
|
|
1067
|
-
/*
|
1068
|
-
* Method: Image#black_threshold(red_channel [, green_channel
|
1069
|
-
* [, blue_channel [, opacity_channel]]]);
|
1070
|
-
* Purpose: Call BlackThresholdImage
|
1071
|
-
*/
|
1072
|
-
VALUE
|
1073
|
-
Image_black_threshold(int argc, VALUE *argv, VALUE self)
|
1074
|
-
{
|
1075
|
-
#if defined(HAVE_BLACKTHRESHOLDIMAGE)
|
1076
|
-
return threshold_image(argc, argv, self, BlackThresholdImage);
|
1077
|
-
#else
|
1078
|
-
rm_not_implemented();
|
1079
|
-
return (VALUE)0;
|
1080
|
-
#endif
|
1081
|
-
}
|
1082
|
-
|
1083
988
|
|
1084
989
|
|
1085
990
|
/*
|
@@ -1091,6 +996,8 @@ Image_black_threshold(int argc, VALUE *argv, VALUE self)
|
|
1091
996
|
VALUE
|
1092
997
|
Image_channel_threshold(int argc, VALUE *argv, VALUE self)
|
1093
998
|
{
|
999
|
+
rb_warning("This method is deprecated in this release of " Q(MAGICKNAME)
|
1000
|
+
". Use bilevel_channel instead.");
|
1094
1001
|
return threshold_image(argc, argv, self,
|
1095
1002
|
#if defined(HAVE_THRESHOLDIMAGECHANNEL)
|
1096
1003
|
ThresholdImageChannel
|
@@ -1651,7 +1558,7 @@ Image_colormap(int argc, VALUE *argv, VALUE self)
|
|
1651
1558
|
return PixelPacket_to_Color_Name(image, &color);
|
1652
1559
|
}
|
1653
1560
|
|
1654
|
-
DEF_ATTR_READER(Image, colors,
|
1561
|
+
DEF_ATTR_READER(Image, colors, ulong)
|
1655
1562
|
|
1656
1563
|
/*
|
1657
1564
|
Method: Image#colorspace
|
@@ -1725,8 +1632,87 @@ Image_colorspace_eq(VALUE self, VALUE colorspace)
|
|
1725
1632
|
return self;
|
1726
1633
|
}
|
1727
1634
|
|
1635
|
+
|
1728
1636
|
DEF_ATTR_READER(Image, columns, int)
|
1729
|
-
|
1637
|
+
|
1638
|
+
|
1639
|
+
/*
|
1640
|
+
Method: Image#compare_channel(ref_image, metric [, channel...])
|
1641
|
+
Purpose: compares one or more channels in two images and returns
|
1642
|
+
the specified distortion metric and a comparison image.
|
1643
|
+
Notes: If no channels are specified, the default is AllChannels.
|
1644
|
+
That case is the equivalent of the CompareImages method in
|
1645
|
+
ImageMagick.
|
1646
|
+
|
1647
|
+
Originally this method was called channel_compare, but
|
1648
|
+
that doesn't match the general naming convention that
|
1649
|
+
methods which accept multiple optional ChannelType
|
1650
|
+
arguments have names that end in _channel. So I renamed
|
1651
|
+
the method to compare_channel but kept channel_compare as
|
1652
|
+
an alias.
|
1653
|
+
*/
|
1654
|
+
VALUE Image_compare_channel(
|
1655
|
+
int argc,
|
1656
|
+
VALUE *argv,
|
1657
|
+
VALUE self)
|
1658
|
+
{
|
1659
|
+
#if defined(HAVE_COMPAREIMAGECHANNELS)
|
1660
|
+
|
1661
|
+
Image *image, *r_image, *difference_image;
|
1662
|
+
double distortion;
|
1663
|
+
volatile VALUE ary;
|
1664
|
+
MetricType metric_type;
|
1665
|
+
ChannelType channels;
|
1666
|
+
ExceptionInfo exception;
|
1667
|
+
|
1668
|
+
channels = extract_channels(&argc, argv);
|
1669
|
+
if (argc > 2)
|
1670
|
+
{
|
1671
|
+
raise_ChannelType_error(argv[argc-1]);
|
1672
|
+
}
|
1673
|
+
if (argc != 2)
|
1674
|
+
{
|
1675
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or more)", argc);
|
1676
|
+
}
|
1677
|
+
|
1678
|
+
Data_Get_Struct(self, Image, image);
|
1679
|
+
Data_Get_Struct(ImageList_cur_image(argv[0]), Image, r_image);
|
1680
|
+
VALUE_TO_ENUM(argv[1], metric_type, MetricType);
|
1681
|
+
|
1682
|
+
GetExceptionInfo(&exception);
|
1683
|
+
difference_image = CompareImageChannels(image
|
1684
|
+
, r_image
|
1685
|
+
, channels
|
1686
|
+
, metric_type
|
1687
|
+
, &distortion
|
1688
|
+
, &exception);
|
1689
|
+
HANDLE_ERROR
|
1690
|
+
|
1691
|
+
ary = rb_ary_new2(2);
|
1692
|
+
rb_ary_store(ary, 0, rm_image_new(difference_image));
|
1693
|
+
rb_ary_store(ary, 1, rb_float_new(distortion));
|
1694
|
+
|
1695
|
+
return ary;
|
1696
|
+
#else
|
1697
|
+
rm_not_implemented();
|
1698
|
+
return (VALUE)0;
|
1699
|
+
#endif
|
1700
|
+
}
|
1701
|
+
|
1702
|
+
|
1703
|
+
/*
|
1704
|
+
Method: Image#compose -> composite_op
|
1705
|
+
Purpose: Return the composite operator attribute
|
1706
|
+
*/
|
1707
|
+
VALUE Image_compose(VALUE self)
|
1708
|
+
{
|
1709
|
+
Image *image;
|
1710
|
+
|
1711
|
+
Data_Get_Struct(self, Image, image);
|
1712
|
+
|
1713
|
+
return CompositeOperator_new(image->compose);
|
1714
|
+
}
|
1715
|
+
|
1730
1716
|
|
1731
1717
|
/*
|
1732
1718
|
Method: Image#compose=composite_op
|
@@ -1773,11 +1759,11 @@ static VALUE composite(
|
|
1773
1759
|
long y_offset;
|
1774
1760
|
|
1775
1761
|
Data_Get_Struct(self, Image, image);
|
1776
|
-
Data_Get_Struct(ImageList_cur_image(argv[0]), Image, comp_image);
|
1777
1762
|
|
1778
1763
|
switch (argc)
|
1779
1764
|
{
|
1780
1765
|
case 3: // argv[1] is gravity, argv[2] is composite_op
|
1766
|
+
Data_Get_Struct(ImageList_cur_image(argv[0]), Image, comp_image);
|
1781
1767
|
VALUE_TO_ENUM(argv[1], gravity, GravityType);
|
1782
1768
|
VALUE_TO_ENUM(argv[2], operator, CompositeOperator);
|
1783
1769
|
|
@@ -1828,12 +1814,14 @@ static VALUE composite(
|
|
1828
1814
|
|
1829
1815
|
case 4: // argv[1], argv[2] is x_off, y_off,
|
1830
1816
|
// argv[3] is composite_op
|
1817
|
+
Data_Get_Struct(ImageList_cur_image(argv[0]), Image, comp_image);
|
1831
1818
|
x_offset = NUM2LONG(argv[1]);
|
1832
1819
|
y_offset = NUM2LONG(argv[2]);
|
1833
1820
|
VALUE_TO_ENUM(argv[3], operator, CompositeOperator);
|
1834
1821
|
break;
|
1835
1822
|
|
1836
1823
|
case 5:
|
1824
|
+
Data_Get_Struct(ImageList_cur_image(argv[0]), Image, comp_image);
|
1837
1825
|
VALUE_TO_ENUM(argv[1], gravity, GravityType);
|
1838
1826
|
x_offset = NUM2LONG(argv[2]);
|
1839
1827
|
y_offset = NUM2LONG(argv[3]);
|
@@ -1877,6 +1865,7 @@ static VALUE composite(
|
|
1877
1865
|
|
1878
1866
|
if (bang)
|
1879
1867
|
{
|
1868
|
+
rm_check_frozen(self);
|
1880
1869
|
(void) CompositeImage(image, operator, comp_image, x_offset, y_offset);
|
1881
1870
|
HANDLE_ERROR_IMG(image)
|
1882
1871
|
return self;
|
@@ -2216,6 +2205,10 @@ Image_convolve_channel(
|
|
2216
2205
|
channels = extract_channels(&argc, argv);
|
2217
2206
|
|
2218
2207
|
// There are 2 required arguments.
|
2208
|
+
if (argc > 2)
|
2209
|
+
{
|
2210
|
+
raise_ChannelType_error(argv[argc-1]);
|
2211
|
+
}
|
2219
2212
|
if (argc != 2)
|
2220
2213
|
{
|
2221
2214
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or more)", argc);
|
@@ -2480,8 +2473,10 @@ VALUE Image_difference(VALUE self, VALUE other)
|
|
2480
2473
|
return rb_ary_new3(3, mean, nmean, nmax);
|
2481
2474
|
}
|
2482
2475
|
|
2476
|
+
|
2483
2477
|
DEF_ATTR_READER(Image, directory, str)
|
2484
2478
|
|
2479
|
+
|
2485
2480
|
/*
|
2486
2481
|
Method: Image#dispatch(x, y, columns, rows, map <, float>)
|
2487
2482
|
Purpose: Extracts pixel data from the image and returns it as an
|
@@ -2608,8 +2603,33 @@ VALUE Image_display(VALUE self)
|
|
2608
2603
|
return self;
|
2609
2604
|
}
|
2610
2605
|
|
2611
|
-
|
2606
|
+
/*
|
2607
|
+
Method: Image#dispose
|
2608
|
+
Purpose: Return the dispose attribute as a DisposeType enum
|
2609
|
+
*/
|
2610
|
+
VALUE
|
2611
|
+
Image_dispose(VALUE self)
|
2612
|
+
{
|
2613
|
+
Image *image;
|
2614
|
+
|
2615
|
+
Data_Get_Struct(self, Image, image);
|
2616
|
+
return DisposeType_new(image->dispose);
|
2617
|
+
}
|
2618
|
+
|
2619
|
+
/*
|
2620
|
+
Method: Image#dispose=
|
2621
|
+
Purpose: Set the dispose attribute
|
2622
|
+
*/
|
2623
|
+
VALUE
|
2624
|
+
Image_dispose_eq(VALUE self, VALUE dispose)
|
2625
|
+
{
|
2626
|
+
Image *image;
|
2612
2627
|
|
2628
|
+
rm_check_frozen(self);
|
2629
|
+
Data_Get_Struct(self, Image, image);
|
2630
|
+
VALUE_TO_ENUM(dispose, image->dispose, DisposeType);
|
2631
|
+
return self;
|
2632
|
+
}
|
2613
2633
|
|
2614
2634
|
/*
|
2615
2635
|
Method: Image#_dump(aDepth)
|
@@ -2785,9 +2805,9 @@ effect_image(
|
|
2785
2805
|
}
|
2786
2806
|
|
2787
2807
|
Data_Get_Struct(self, Image, image);
|
2788
|
-
if (sigma
|
2808
|
+
if (sigma == 0.0)
|
2789
2809
|
{
|
2790
|
-
rb_raise(rb_eArgError, "sigma must be
|
2810
|
+
rb_raise(rb_eArgError, "sigma must be != 0.0");
|
2791
2811
|
}
|
2792
2812
|
|
2793
2813
|
GetExceptionInfo(&exception);
|
@@ -3007,6 +3027,7 @@ Image_extract_info_eq(VALUE self, VALUE rect)
|
|
3007
3027
|
|
3008
3028
|
DEF_ATTR_READER(Image, filename, str)
|
3009
3029
|
|
3030
|
+
|
3010
3031
|
/*
|
3011
3032
|
Method: Image#filesize
|
3012
3033
|
Purpose: Return the image filesize
|
@@ -3019,6 +3040,7 @@ VALUE Image_filesize(VALUE self)
|
|
3019
3040
|
return INT2FIX(GetBlobSize(image));
|
3020
3041
|
}
|
3021
3042
|
|
3043
|
+
|
3022
3044
|
/*
|
3023
3045
|
Method: Image#filter, filter=
|
3024
3046
|
Purpose: Get/set filter type
|
@@ -3043,6 +3065,7 @@ Image_filter_eq(VALUE self, VALUE filter)
|
|
3043
3065
|
return self;
|
3044
3066
|
}
|
3045
3067
|
|
3068
|
+
|
3046
3069
|
/*
|
3047
3070
|
Method: Image#flip
|
3048
3071
|
Image#flip!
|
@@ -3285,6 +3308,7 @@ VALUE Image_fuzz_eq(VALUE self, VALUE fuzz)
|
|
3285
3308
|
return self;
|
3286
3309
|
}
|
3287
3310
|
|
3311
|
+
|
3288
3312
|
DEF_ATTR_ACCESSOR(Image, gamma, dbl)
|
3289
3313
|
|
3290
3314
|
|
@@ -3475,7 +3499,7 @@ Image_geometry_eq(
|
|
3475
3499
|
geom = STRING_PTR(geom_str);
|
3476
3500
|
if (!IsGeometry(geom))
|
3477
3501
|
{
|
3478
|
-
rb_raise(
|
3502
|
+
rb_raise(rb_eTypeError, "invalid geometry: %s", geom);
|
3479
3503
|
}
|
3480
3504
|
magick_clone_string(&image->geometry, geom);
|
3481
3505
|
return self;
|
@@ -3665,77 +3689,145 @@ Image_implode(int argc, VALUE *argv, VALUE self)
|
|
3665
3689
|
Notes: See Image#export_pixels
|
3666
3690
|
*/
|
3667
3691
|
VALUE
|
3668
|
-
Image_import_pixels(
|
3669
|
-
VALUE self,
|
3670
|
-
VALUE x_arg,
|
3671
|
-
VALUE y_arg,
|
3672
|
-
VALUE cols_arg,
|
3673
|
-
VALUE rows_arg,
|
3674
|
-
VALUE map_arg,
|
3675
|
-
VALUE pixel_ary)
|
3692
|
+
Image_import_pixels(int argc, VALUE *argv, VALUE self)
|
3676
3693
|
{
|
3677
3694
|
#if defined(HAVE_IMPORTIMAGEPIXELS)
|
3678
3695
|
Image *image, *clone_image;
|
3679
3696
|
long x_off, y_off;
|
3680
3697
|
unsigned long cols, rows;
|
3681
3698
|
unsigned long npixels;
|
3682
|
-
long n;
|
3699
|
+
long n, buffer_l;
|
3683
3700
|
char *map;
|
3684
|
-
volatile
|
3701
|
+
volatile VALUE pixel_arg, pixel_ary;
|
3702
|
+
StorageType stg_type = CharPixel;
|
3703
|
+
size_t type_sz, map_l;
|
3704
|
+
volatile int *pixels = NULL;
|
3705
|
+
volatile void *buffer;
|
3685
3706
|
unsigned int okay;
|
3686
3707
|
ExceptionInfo exception;
|
3687
3708
|
|
3688
3709
|
rm_check_frozen(self);
|
3710
|
+
|
3711
|
+
switch (argc)
|
3712
|
+
{
|
3713
|
+
case 7:
|
3714
|
+
VALUE_TO_ENUM(argv[6], stg_type, StorageType);
|
3715
|
+
case 6:
|
3716
|
+
x_off = NUM2LONG(argv[0]);
|
3717
|
+
y_off = NUM2LONG(argv[1]);
|
3718
|
+
cols = NUM2ULONG(argv[2]);
|
3719
|
+
rows = NUM2ULONG(argv[3]);
|
3720
|
+
map = STRING_PTR(argv[4]);
|
3721
|
+
pixel_arg = argv[5];
|
3722
|
+
break;
|
3723
|
+
default:
|
3724
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 6 or 7)", argc);
|
3725
|
+
break;
|
3726
|
+
}
|
3727
|
+
|
3689
3728
|
Data_Get_Struct(self, Image, image);
|
3690
3729
|
|
3691
|
-
|
3692
|
-
|
3693
|
-
|
3694
|
-
|
3695
|
-
|
3730
|
+
if (x_off < 0 || y_off < 0 || cols <= 0 || rows <= 0)
|
3731
|
+
{
|
3732
|
+
rb_raise(rb_eArgError, "invalid import geometry");
|
3733
|
+
}
|
3734
|
+
|
3735
|
+
map_l = strlen(map);
|
3736
|
+
npixels = cols * rows * map_l;
|
3737
|
+
|
3738
|
+
// Assume that any object that responds to :to_str is a string buffer containing
|
3739
|
+
// binary pixel data.
|
3740
|
+
if (rb_respond_to(pixel_arg, rb_intern("to_str")))
|
3741
|
+
{
|
3742
|
+
buffer = (void *)STRING_PTR_LEN(pixel_arg, buffer_l);
|
3743
|
+
switch (stg_type)
|
3744
|
+
{
|
3745
|
+
case CharPixel:
|
3746
|
+
type_sz = 1;
|
3747
|
+
break;
|
3748
|
+
case ShortPixel:
|
3749
|
+
type_sz = sizeof(unsigned short);
|
3750
|
+
break;
|
3751
|
+
case IntegerPixel:
|
3752
|
+
type_sz = sizeof(unsigned int);
|
3753
|
+
break;
|
3754
|
+
case LongPixel:
|
3755
|
+
type_sz = sizeof(unsigned long);
|
3756
|
+
break;
|
3757
|
+
#if defined(HAVE_QUANTUMPIXEL)
|
3758
|
+
case QuantumPixel:
|
3759
|
+
type_sz = sizeof(Quantum);
|
3760
|
+
break;
|
3761
|
+
#endif
|
3762
|
+
default:
|
3763
|
+
rb_raise(rb_eArgError, "unsupported storage type %s", StorageType_name(stg_type));
|
3764
|
+
break;
|
3765
|
+
}
|
3696
3766
|
|
3697
|
-
|
3698
|
-
|
3699
|
-
|
3767
|
+
if (buffer_l % type_sz != 0)
|
3768
|
+
{
|
3769
|
+
rb_raise(rb_eArgError, "pixel buffer must be an exact multiple of the storage type size");
|
3770
|
+
}
|
3771
|
+
if ((buffer_l / type_sz) % map_l != 0)
|
3772
|
+
{
|
3773
|
+
rb_raise(rb_eArgError, "pixel buffer must contain an exact multiple of the map length");
|
3774
|
+
}
|
3775
|
+
if (buffer_l/type_sz < npixels)
|
3776
|
+
{
|
3777
|
+
rb_raise(rb_eArgError, "pixel buffer too small (need %lu channel values, got %ld)"
|
3778
|
+
, npixels, buffer_l/type_sz);
|
3779
|
+
}
|
3700
3780
|
}
|
3781
|
+
// Otherwise convert the argument to an array and convert the array elements
|
3782
|
+
// to binary pixel data.
|
3783
|
+
else
|
3784
|
+
{
|
3785
|
+
// rb_Array converts an object that is not an array to an array if possible,
|
3786
|
+
// and raises TypeError if it can't. It usually is possible.
|
3787
|
+
pixel_ary = rb_Array(pixel_arg);
|
3701
3788
|
|
3702
|
-
|
3703
|
-
|
3704
|
-
|
3705
|
-
|
3706
|
-
|
3789
|
+
if (RARRAY(pixel_ary)->len % map_l != 0)
|
3790
|
+
{
|
3791
|
+
rb_raise(rb_eArgError, "pixel array must contain an exact multiple of the map length");
|
3792
|
+
}
|
3793
|
+
if (RARRAY(pixel_ary)->len < npixels)
|
3794
|
+
{
|
3795
|
+
rb_raise(rb_eArgError, "pixel array too small (need %lu elements, got %ld)"
|
3796
|
+
, npixels, RARRAY(pixel_ary)->len);
|
3797
|
+
}
|
3707
3798
|
|
3708
|
-
|
3709
|
-
|
3710
|
-
|
3711
|
-
|
3712
|
-
|
3799
|
+
// Get array for integer pixels. Use Ruby's memory so GC will clean up after us
|
3800
|
+
// in case of an exception.
|
3801
|
+
pixels = ALLOC_N(int, npixels);
|
3802
|
+
if (!pixels) // app recovered from exception...
|
3803
|
+
{
|
3804
|
+
return self;
|
3805
|
+
}
|
3713
3806
|
|
3714
|
-
|
3715
|
-
|
3716
|
-
|
3717
|
-
|
3718
|
-
|
3719
|
-
|
3807
|
+
for (n = 0; n < npixels; n++)
|
3808
|
+
{
|
3809
|
+
volatile VALUE p = rb_ary_entry(pixel_ary, n);
|
3810
|
+
long q = ScaleQuantumToLong(NUM2LONG(p));
|
3811
|
+
pixels[n] = (int) q;
|
3812
|
+
}
|
3813
|
+
buffer = (void *) pixels;
|
3814
|
+
stg_type = IntegerPixel;
|
3720
3815
|
}
|
3721
3816
|
|
3722
|
-
for (n = 0; n < npixels; n++)
|
3723
|
-
{
|
3724
|
-
volatile VALUE p = rb_ary_entry(pixel_ary, n);
|
3725
|
-
long q = ScaleQuantumToLong(NUM2LONG(p));
|
3726
|
-
pixels[n] = (int) q;
|
3727
|
-
}
|
3728
3817
|
|
3729
3818
|
// Import into a clone - ImportImagePixels destroys the input image if an error occurs.
|
3730
3819
|
GetExceptionInfo(&exception);
|
3731
3820
|
clone_image = CloneImage(image, 0, 0, True, &exception);
|
3732
3821
|
HANDLE_ERROR
|
3733
3822
|
|
3734
|
-
okay = ImportImagePixels(clone_image, x_off, y_off, cols, rows, map,
|
3823
|
+
okay = ImportImagePixels(clone_image, x_off, y_off, cols, rows, map, stg_type, (const void *)buffer);
|
3735
3824
|
|
3736
3825
|
// Free pixel array before checking for errors. If an error occurred, ImportImagePixels
|
3737
3826
|
// destroyed the clone image, so we don't have to.
|
3738
|
-
|
3827
|
+
if (pixels)
|
3828
|
+
{
|
3829
|
+
xfree((void *)pixels);
|
3830
|
+
}
|
3739
3831
|
|
3740
3832
|
if (!okay)
|
3741
3833
|
{
|
@@ -3782,7 +3874,11 @@ Image_inspect(VALUE self)
|
|
3782
3874
|
// Print current filename.
|
3783
3875
|
x += sprintf(buffer+x, "%s", image->filename);
|
3784
3876
|
// Print scene number.
|
3877
|
+
#if defined(HAVE_GETNEXTIMAGEINLIST)
|
3878
|
+
if ((GetPreviousImageInList(image) != NULL) && (GetNextImageInList(image) != NULL) && image->scene > 0)
|
3879
|
+
#else
|
3785
3880
|
if ((image->previous || image->next) && image->scene > 0)
|
3881
|
+
#endif
|
3786
3882
|
{
|
3787
3883
|
x += sprintf(buffer+x, "[%lu]", image->scene);
|
3788
3884
|
}
|
@@ -4568,6 +4664,7 @@ Image_monitor_eq(VALUE self, VALUE monitor)
|
|
4568
4664
|
#if defined(HAVE_SETIMAGEPROGRESSMONITOR)
|
4569
4665
|
Image *image;
|
4570
4666
|
|
4667
|
+
rm_check_frozen(self);
|
4571
4668
|
Data_Get_Struct(self, Image, image);
|
4572
4669
|
|
4573
4670
|
if (NIL_P(monitor))
|
@@ -4663,9 +4760,9 @@ Image_motion_blur(
|
|
4663
4760
|
sigma = NUM2DBL(sigma_arg);
|
4664
4761
|
angle = NUM2DBL(angle_arg);
|
4665
4762
|
|
4666
|
-
if (sigma
|
4763
|
+
if (sigma == 0.0)
|
4667
4764
|
{
|
4668
|
-
rb_raise(rb_eArgError, "sigma must be
|
4765
|
+
rb_raise(rb_eArgError, "sigma must be != 0.0");
|
4669
4766
|
}
|
4670
4767
|
|
4671
4768
|
GetExceptionInfo(&exception);
|
@@ -4996,14 +5093,14 @@ Image_number_colors(VALUE self)
|
|
4996
5093
|
{
|
4997
5094
|
Image *image;
|
4998
5095
|
ExceptionInfo exception;
|
4999
|
-
unsigned
|
5096
|
+
unsigned long n = 0;
|
5000
5097
|
|
5001
5098
|
Data_Get_Struct(self, Image, image);
|
5002
5099
|
GetExceptionInfo(&exception);
|
5003
5100
|
|
5004
|
-
n = GetNumberColors(image, NULL, &exception);
|
5101
|
+
n = (unsigned long) GetNumberColors(image, NULL, &exception);
|
5005
5102
|
HANDLE_ERROR
|
5006
|
-
return
|
5103
|
+
return ULONG2NUM(n);
|
5007
5104
|
}
|
5008
5105
|
|
5009
5106
|
DEF_ATTR_ACCESSOR(Image, offset, long)
|
@@ -5238,7 +5335,11 @@ Image_pixel_color(
|
|
5238
5335
|
HANDLE_ERROR
|
5239
5336
|
|
5240
5337
|
// PseudoClass
|
5338
|
+
#if defined(HAVE_IMAGE_STORAGE_CLASS)
|
5339
|
+
if (image->storage_class == PseudoClass)
|
5340
|
+
#else
|
5241
5341
|
if (image->class == PseudoClass)
|
5342
|
+
#endif
|
5242
5343
|
{
|
5243
5344
|
IndexPacket *indexes = GetIndexes(image);
|
5244
5345
|
old_color = image->colormap[*indexes];
|
@@ -5259,12 +5360,20 @@ Image_pixel_color(
|
|
5259
5360
|
|
5260
5361
|
// Set the color of a pixel. Return previous color.
|
5261
5362
|
// Convert to DirectClass
|
5363
|
+
#if defined(HAVE_IMAGE_STORAGE_CLASS)
|
5364
|
+
if (image->storage_class == PseudoClass)
|
5365
|
+
#else
|
5262
5366
|
if (image->class == PseudoClass)
|
5367
|
+
#endif
|
5263
5368
|
{
|
5264
5369
|
SyncImage(image);
|
5265
5370
|
magick_free(image->colormap);
|
5266
5371
|
image->colormap = NULL;
|
5372
|
+
#if defined(HAVE_IMAGE_STORAGE_CLASS)
|
5373
|
+
image->storage_class = DirectClass;
|
5374
|
+
#else
|
5267
5375
|
image->class = DirectClass;
|
5376
|
+
#endif
|
5268
5377
|
}
|
5269
5378
|
|
5270
5379
|
pixel = GetImagePixels(image, x, y, 1, 1);
|
@@ -5437,6 +5546,12 @@ Image_profile_bang(
|
|
5437
5546
|
}
|
5438
5547
|
|
5439
5548
|
|
5549
|
+
#if defined(HAVE_IMAGE_QUALITY)
|
5550
|
+
DEF_ATTR_READER(Image, quality, ulong)
|
5551
|
+
#endif
|
5552
|
+
|
5553
|
+
|
5554
|
+
|
5440
5555
|
/*
|
5441
5556
|
Method: Image#quantum_depth -> 8, 16, or 32
|
5442
5557
|
Purpose: Return image depth to nearest quantum
|
@@ -5642,38 +5757,6 @@ Image_quantum_operator(int argc, VALUE *argv, VALUE self)
|
|
5642
5757
|
}
|
5643
5758
|
|
5644
5759
|
|
5645
|
-
|
5646
|
-
/*
|
5647
|
-
Method: Image#radial_blur(angle)
|
5648
|
-
Purpose: Call RadialBlurImage
|
5649
|
-
Notes: Angle is in degrees
|
5650
|
-
*/
|
5651
|
-
VALUE
|
5652
|
-
Image_radial_blur(VALUE self, VALUE angle)
|
5653
|
-
{
|
5654
|
-
#if defined(HAVE_RADIALBLURIMAGE)
|
5655
|
-
Image *image, *new_image;
|
5656
|
-
ExceptionInfo exception;
|
5657
|
-
|
5658
|
-
Data_Get_Struct(self, Image, image);
|
5659
|
-
GetExceptionInfo(&exception);
|
5660
|
-
|
5661
|
-
new_image = RadialBlurImage(image, NUM2DBL(angle), &exception);
|
5662
|
-
HANDLE_ERROR
|
5663
|
-
|
5664
|
-
return rm_image_new(new_image);
|
5665
|
-
#else
|
5666
|
-
rm_not_implemented();
|
5667
|
-
return (VALUE)0;
|
5668
|
-
#endif
|
5669
|
-
}
|
5670
|
-
|
5671
|
-
|
5672
|
-
#if defined(HAVE_IMAGE_QUALITY)
|
5673
|
-
DEF_ATTR_READER(Image, quality, ulong)
|
5674
|
-
#endif
|
5675
|
-
|
5676
|
-
|
5677
5760
|
/*
|
5678
5761
|
Method: Image#quantize(<number_colors<, colorspace<, dither<, tree_depth<, measure_error>>>>>)
|
5679
5762
|
defaults: 256, Magick::RGBColorspace, true, 0, false
|
@@ -5716,6 +5799,33 @@ Image_quantize(int argc, VALUE *argv, VALUE self)
|
|
5716
5799
|
}
|
5717
5800
|
|
5718
5801
|
|
5802
|
+
|
5803
|
+
/*
|
5804
|
+
Method: Image#radial_blur(angle)
|
5805
|
+
Purpose: Call RadialBlurImage
|
5806
|
+
Notes: Angle is in degrees
|
5807
|
+
*/
|
5808
|
+
VALUE
|
5809
|
+
Image_radial_blur(VALUE self, VALUE angle)
|
5810
|
+
{
|
5811
|
+
#if defined(HAVE_RADIALBLURIMAGE)
|
5812
|
+
Image *image, *new_image;
|
5813
|
+
ExceptionInfo exception;
|
5814
|
+
|
5815
|
+
Data_Get_Struct(self, Image, image);
|
5816
|
+
GetExceptionInfo(&exception);
|
5817
|
+
|
5818
|
+
new_image = RadialBlurImage(image, NUM2DBL(angle), &exception);
|
5819
|
+
HANDLE_ERROR
|
5820
|
+
|
5821
|
+
return rm_image_new(new_image);
|
5822
|
+
#else
|
5823
|
+
rm_not_implemented();
|
5824
|
+
return (VALUE)0;
|
5825
|
+
#endif
|
5826
|
+
}
|
5827
|
+
|
5828
|
+
|
5719
5829
|
/*
|
5720
5830
|
Method: Image#random_channel_threshold
|
5721
5831
|
Purpose: changes the value of individual pixels based on the intensity of
|
@@ -6443,6 +6553,77 @@ Image_opacity_eq(VALUE self, VALUE opacity_arg)
|
|
6443
6553
|
return self;
|
6444
6554
|
}
|
6445
6555
|
|
6556
|
+
|
6557
|
+
/*
|
6558
|
+
Method: Image#properties [{ |k,v| block }]
|
6559
|
+
Purpose: Traverse the attributes and yield to the block.
|
6560
|
+
If no block, return a hash of all the attribute
|
6561
|
+
keys & values
|
6562
|
+
Notes: I use the word "properties" to distinguish between
|
6563
|
+
these "user-added" attribute strings and Image
|
6564
|
+
object attributes.
|
6565
|
+
*/
|
6566
|
+
VALUE
|
6567
|
+
Image_properties(VALUE self)
|
6568
|
+
{
|
6569
|
+
Image *image;
|
6570
|
+
const ImageAttribute *attr;
|
6571
|
+
volatile VALUE attr_hash;
|
6572
|
+
|
6573
|
+
Data_Get_Struct(self, Image, image);
|
6574
|
+
|
6575
|
+
// If block, iterate over attributes
|
6576
|
+
if (rb_block_given_p())
|
6577
|
+
{
|
6578
|
+
volatile VALUE ary = rb_ary_new2(2);
|
6579
|
+
|
6580
|
+
#if defined(HAVE_GETNEXTIMAGEATTRIBUTE)
|
6581
|
+
ResetImageAttributeIterator(image);
|
6582
|
+
attr = GetNextImageAttribute(image);
|
6583
|
+
while (attr)
|
6584
|
+
{
|
6585
|
+
rb_ary_store(ary, 0, rb_str_new2(attr->key));
|
6586
|
+
rb_ary_store(ary, 1, rb_str_new2(attr->value));
|
6587
|
+
rb_yield(ary);
|
6588
|
+
attr = GetNextImageAttribute(image);
|
6589
|
+
}
|
6590
|
+
#else
|
6591
|
+
for (attr = image->attributes; attr; attr = Next_Attribute)
|
6592
|
+
{
|
6593
|
+
// Store the next ptr where Image#aset can see it.
|
6594
|
+
// The app may decide to delete that attribute.
|
6595
|
+
Next_Attribute = attr->next;
|
6596
|
+
rb_ary_store(ary, 0, rb_str_new2(attr->key));
|
6597
|
+
rb_ary_store(ary, 1, rb_str_new2(attr->value));
|
6598
|
+
rb_yield(ary);
|
6599
|
+
}
|
6600
|
+
#endif
|
6601
|
+
return self;
|
6602
|
+
}
|
6603
|
+
|
6604
|
+
// otherwise return properties hash
|
6605
|
+
else
|
6606
|
+
{
|
6607
|
+
attr_hash = rb_hash_new();
|
6608
|
+
#if defined(HAVE_GETNEXTIMAGEATTRIBUTE)
|
6609
|
+
ResetImageAttributeIterator(image);
|
6610
|
+
attr = GetNextImageAttribute(image);
|
6611
|
+
while (attr)
|
6612
|
+
{
|
6613
|
+
rb_hash_aset(attr_hash, rb_str_new2(attr->key), rb_str_new2(attr->value));
|
6614
|
+
attr = GetNextImageAttribute(image);
|
6615
|
+
}
|
6616
|
+
#else
|
6617
|
+
for (attr = image->attributes; attr; attr = attr->next)
|
6618
|
+
{
|
6619
|
+
rb_hash_aset(attr_hash, rb_str_new2(attr->key), rb_str_new2(attr->value));
|
6620
|
+
}
|
6621
|
+
#endif
|
6622
|
+
return attr_hash;
|
6623
|
+
}
|
6624
|
+
}
|
6625
|
+
|
6626
|
+
|
6446
6627
|
/*
|
6447
6628
|
Method: Image#shade(shading=false, azimuth=30, elevation=30)
|
6448
6629
|
Purpose: shines a distant light on an image to create a three-dimensional
|
@@ -6545,33 +6726,6 @@ Image_shadow(int argc, VALUE *argv, VALUE self)
|
|
6545
6726
|
#endif
|
6546
6727
|
}
|
6547
6728
|
|
6548
|
-
/*
|
6549
|
-
Method: Image#shave(width, height)
|
6550
|
-
Image#shave!(width, height)
|
6551
|
-
Purpose: shaves pixels from the image edges, leaving a rectangle
|
6552
|
-
of the specified width & height in the center
|
6553
|
-
Returns: shave: a new image
|
6554
|
-
shave!: self, shaved
|
6555
|
-
*/
|
6556
|
-
VALUE
|
6557
|
-
Image_shave(
|
6558
|
-
VALUE self,
|
6559
|
-
VALUE width,
|
6560
|
-
VALUE height)
|
6561
|
-
{
|
6562
|
-
return xform_image(False, self, INT2FIX(0), INT2FIX(0), width, height, ShaveImage);
|
6563
|
-
}
|
6564
|
-
|
6565
|
-
VALUE
|
6566
|
-
Image_shave_bang(
|
6567
|
-
VALUE self,
|
6568
|
-
VALUE width,
|
6569
|
-
VALUE height)
|
6570
|
-
{
|
6571
|
-
rm_check_frozen(self);
|
6572
|
-
return xform_image(True, self, INT2FIX(0), INT2FIX(0), width, height, ShaveImage);
|
6573
|
-
}
|
6574
|
-
|
6575
6729
|
/*
|
6576
6730
|
Method: Image#sharpen(radius=0, sigma=1)
|
6577
6731
|
Purpose: sharpens an image
|
@@ -6630,6 +6784,36 @@ Image_sharpen_channel(int argc, VALUE *argv, VALUE self)
|
|
6630
6784
|
#endif
|
6631
6785
|
}
|
6632
6786
|
|
6787
|
+
|
6788
|
+
/*
|
6789
|
+
Method: Image#shave(width, height)
|
6790
|
+
Image#shave!(width, height)
|
6791
|
+
Purpose: shaves pixels from the image edges, leaving a rectangle
|
6792
|
+
of the specified width & height in the center
|
6793
|
+
Returns: shave: a new image
|
6794
|
+
shave!: self, shaved
|
6795
|
+
*/
|
6796
|
+
VALUE
|
6797
|
+
Image_shave(
|
6798
|
+
VALUE self,
|
6799
|
+
VALUE width,
|
6800
|
+
VALUE height)
|
6801
|
+
{
|
6802
|
+
return xform_image(False, self, INT2FIX(0), INT2FIX(0), width, height, ShaveImage);
|
6803
|
+
}
|
6804
|
+
|
6805
|
+
|
6806
|
+
VALUE
|
6807
|
+
Image_shave_bang(
|
6808
|
+
VALUE self,
|
6809
|
+
VALUE width,
|
6810
|
+
VALUE height)
|
6811
|
+
{
|
6812
|
+
rm_check_frozen(self);
|
6813
|
+
return xform_image(True, self, INT2FIX(0), INT2FIX(0), width, height, ShaveImage);
|
6814
|
+
}
|
6815
|
+
|
6816
|
+
|
6633
6817
|
/*
|
6634
6818
|
Method: Image#shear(x_shear, y_shear)
|
6635
6819
|
Purpose: Calls ShearImage
|
@@ -6799,6 +6983,7 @@ Image_spaceship(VALUE self, VALUE other)
|
|
6799
6983
|
}
|
6800
6984
|
|
6801
6985
|
res = memcmp(sigA->value, sigB->value, 64);
|
6986
|
+
res = res > 0 ? 1 : (res < 0 ? -1 : 0); // reduce to 1, -1, 0
|
6802
6987
|
|
6803
6988
|
return INT2FIX(res);
|
6804
6989
|
}
|
@@ -7002,7 +7187,11 @@ Image_class_type(VALUE self)
|
|
7002
7187
|
Image *image;
|
7003
7188
|
Data_Get_Struct(self, Image, image);
|
7004
7189
|
|
7190
|
+
#if defined(HAVE_IMAGE_STORAGE_CLASS)
|
7191
|
+
return ClassType_new(image->storage_class);
|
7192
|
+
#else
|
7005
7193
|
return ClassType_new(image->class);
|
7194
|
+
#endif
|
7006
7195
|
}
|
7007
7196
|
|
7008
7197
|
/*
|
@@ -7021,20 +7210,32 @@ Image_class_type_eq(VALUE self, VALUE new_class_type)
|
|
7021
7210
|
Data_Get_Struct(self, Image, image);
|
7022
7211
|
VALUE_TO_ENUM(new_class_type, class_type, ClassType);
|
7023
7212
|
|
7213
|
+
#if defined(HAVE_IMAGE_STORAGE_CLASS)
|
7214
|
+
if (image->storage_class == PseudoClass && class_type == DirectClass)
|
7215
|
+
#else
|
7024
7216
|
if (image->class == PseudoClass && class_type == DirectClass)
|
7217
|
+
#endif
|
7025
7218
|
{
|
7026
7219
|
SyncImage(image);
|
7027
7220
|
magick_free(image->colormap);
|
7028
7221
|
image->colormap = NULL;
|
7029
7222
|
}
|
7223
|
+
#if defined(HAVE_IMAGE_STORAGE_CLASS)
|
7224
|
+
else if (image->storage_class == DirectClass && class_type == PseudoClass)
|
7225
|
+
#else
|
7030
7226
|
else if (image->class == DirectClass && class_type == PseudoClass)
|
7227
|
+
#endif
|
7031
7228
|
{
|
7032
7229
|
GetQuantizeInfo(&qinfo);
|
7033
7230
|
qinfo.number_colors = MaxRGB+1;
|
7034
7231
|
QuantizeImage(&qinfo, image);
|
7035
7232
|
}
|
7036
7233
|
|
7234
|
+
#if defined(HAVE_IMAGE_STORAGE_CLASS)
|
7235
|
+
image->storage_class = class_type;
|
7236
|
+
#else
|
7037
7237
|
image->class = class_type;
|
7238
|
+
#endif
|
7038
7239
|
return self;
|
7039
7240
|
}
|
7040
7241
|
|
@@ -7074,6 +7275,9 @@ Image_store_pixels(
|
|
7074
7275
|
, cols, rows, x, y);
|
7075
7276
|
}
|
7076
7277
|
|
7278
|
+
size = cols * rows;
|
7279
|
+
rm_check_ary_len(new_pixels, size);
|
7280
|
+
|
7077
7281
|
SetImageType(image, TrueColorType);
|
7078
7282
|
|
7079
7283
|
// Get a pointer to the pixels. Replace the values with the PixelPackets
|
@@ -7081,7 +7285,6 @@ Image_store_pixels(
|
|
7081
7285
|
pixels = GetImagePixels(image, x, y, cols, rows);
|
7082
7286
|
if (pixels)
|
7083
7287
|
{
|
7084
|
-
size = cols * rows;
|
7085
7288
|
for (n = 0; n < size; n++)
|
7086
7289
|
{
|
7087
7290
|
new_pixel = rb_ary_entry(new_pixels, n);
|
@@ -7570,7 +7773,17 @@ Image_to_color(VALUE self, VALUE pixel_arg)
|
|
7570
7773
|
|
7571
7774
|
}
|
7572
7775
|
|
7573
|
-
|
7776
|
+
/*
|
7777
|
+
Method: Image#total_colors
|
7778
|
+
Purpose: alias for Image#number_colors
|
7779
|
+
Notes: This used to be a direct reference to the `total_colors' field in Image
|
7780
|
+
but that field is not reliable.
|
7781
|
+
*/
|
7782
|
+
VALUE
|
7783
|
+
Image_total_colors(VALUE self)
|
7784
|
+
{
|
7785
|
+
return Image_number_colors(self);
|
7786
|
+
}
|
7574
7787
|
|
7575
7788
|
/*
|
7576
7789
|
Method: Image#transparent(color-name<, opacity>)
|
@@ -7674,6 +7887,8 @@ Image_trim_bang(VALUE self)
|
|
7674
7887
|
Method: Image#image_type=(type)
|
7675
7888
|
Purpose: Call SetImageType to set the type of the image
|
7676
7889
|
Note: Can't use type & type= b/c of Object#type.
|
7890
|
+
This setter is useless. Leave for backward compatibility
|
7891
|
+
but don't document it.
|
7677
7892
|
*/
|
7678
7893
|
VALUE Image_image_type_eq(VALUE self, VALUE type)
|
7679
7894
|
{
|
@@ -7966,6 +8181,9 @@ DEF_ATTR_ACCESSOR(Image, x_resolution, dbl)
|
|
7966
8181
|
gravity, x, y, width, height
|
7967
8182
|
If the 2nd or 3rd, compute new x, y values.
|
7968
8183
|
|
8184
|
+
The argument list can have a trailing true, false, or nil argument.
|
8185
|
+
If present and true, after cropping reset the page fields in the image.
|
8186
|
+
|
7969
8187
|
Call xform_image to do the cropping.
|
7970
8188
|
*/
|
7971
8189
|
static VALUE
|
@@ -7974,9 +8192,27 @@ cropper(int bang, int argc, VALUE *argv, VALUE self)
|
|
7974
8192
|
volatile VALUE x, y, width, height;
|
7975
8193
|
unsigned long nx = 0, ny = 0;
|
7976
8194
|
unsigned long columns, rows;
|
8195
|
+
int reset_page = 0;
|
7977
8196
|
GravityType gravity;
|
7978
8197
|
MagickEnum *magick_enum;
|
7979
8198
|
Image *image;
|
8199
|
+
VALUE cropped;
|
8200
|
+
|
8201
|
+
// Check for a "reset page" trailing argument.
|
8202
|
+
if (argc >= 1)
|
8203
|
+
{
|
8204
|
+
switch (TYPE(argv[argc-1]))
|
8205
|
+
{
|
8206
|
+
case T_TRUE:
|
8207
|
+
reset_page = 1;
|
8208
|
+
// fall thru
|
8209
|
+
case T_FALSE:
|
8210
|
+
case T_NIL:
|
8211
|
+
argc -= 1;
|
8212
|
+
default:
|
8213
|
+
break;
|
8214
|
+
}
|
8215
|
+
}
|
7980
8216
|
|
7981
8217
|
switch (argc)
|
7982
8218
|
{
|
@@ -8083,11 +8319,25 @@ cropper(int bang, int argc, VALUE *argv, VALUE self)
|
|
8083
8319
|
y = ULONG2NUM(ny);
|
8084
8320
|
break;
|
8085
8321
|
default:
|
8086
|
-
|
8322
|
+
if (reset_page)
|
8323
|
+
{
|
8324
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 4, 5, or 6)", argc);
|
8325
|
+
}
|
8326
|
+
else
|
8327
|
+
{
|
8328
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 3, 4, or 5)", argc);
|
8329
|
+
}
|
8087
8330
|
break;
|
8088
8331
|
}
|
8089
8332
|
|
8090
|
-
|
8333
|
+
cropped = xform_image(bang, self, x, y, width, height, CropImage);
|
8334
|
+
if (reset_page)
|
8335
|
+
{
|
8336
|
+
Data_Get_Struct(cropped, Image, image);
|
8337
|
+
image->page.x = image->page.y = 0L;
|
8338
|
+
image->page.width = image->page.height = 0UL;
|
8339
|
+
}
|
8340
|
+
return cropped;
|
8091
8341
|
}
|
8092
8342
|
|
8093
8343
|
|
@@ -8183,12 +8433,12 @@ static ChannelType extract_channels(
|
|
8183
8433
|
|
8184
8434
|
/*
|
8185
8435
|
Static: raise_ChannelType_error
|
8186
|
-
Purpose: raise
|
8436
|
+
Purpose: raise TypeError when an non-ChannelType object
|
8187
8437
|
is unexpectedly encountered
|
8188
8438
|
*/
|
8189
8439
|
static void
|
8190
8440
|
raise_ChannelType_error(VALUE arg)
|
8191
8441
|
{
|
8192
|
-
rb_raise(
|
8442
|
+
rb_raise(rb_eTypeError, "argument needs to be a ChannelType (%s given)"
|
8193
8443
|
, rb_class2name(CLASS_OF(arg)));
|
8194
8444
|
}
|