magickwand 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  require 'mkmf'
2
2
 
3
- MAGICKWAND_VERSION = "0.1.0"
3
+ MAGICKWAND_VERSION = "0.2.0"
4
4
  MIN_IM_VERS = "6.5.0"
5
5
  MIN_IM_VERS_NO = MIN_IM_VERS.tr(".","").to_i
6
6
 
@@ -50,7 +50,8 @@ unless have_library("MagickWand", "MagickWandGenesis", headers)
50
50
  end
51
51
 
52
52
  # ImageMagick features Release added
53
- ["MagickSetColorspace", # 6.5.1
53
+ ["DrawSetBorderColor", # 6.5.4
54
+ "MagickSetColorspace", # 6.5.1
54
55
  "MagickSetImageFuzz" # 6.5.1
55
56
  ].each do |func|
56
57
  have_func(func, headers)
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * magickwand.c
3
- * $Id: magickwand.c 146 2009-05-31 22:00:57Z rmagick $
3
+ * $Id: magickwand.c 164 2009-06-21 16:52:27Z rmagick $
4
4
  * Copyright (C) 2009 Timothy Paul Hunter
5
5
  */
6
6
 
@@ -145,7 +145,7 @@ void Init_magickwand(void)
145
145
  ImageMagick_config();
146
146
 
147
147
  mwr_init_Wand();
148
- mwr_init_GC();
148
+ mwr_init_Drawing();
149
149
  mwr_init_ImageMagickError();
150
150
  mwr_init_FatalImageMagickError();
151
151
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * magickwand.h
3
- * $Id: magickwand.h 25 2009-04-28 23:11:33Z rmagick $
3
+ * $Id: magickwand.h 285 2009-08-14 23:09:24Z rmagick $
4
4
  * Copyright (C) 2009 Timothy Paul Hunter
5
5
  */
6
6
 
@@ -32,8 +32,8 @@ typedef struct
32
32
 
33
33
  typedef struct
34
34
  {
35
- DrawingWand *drawingwand;
36
- } GC;
35
+ DrawingWand *wand;
36
+ } Drawing;
37
37
 
38
38
 
39
39
  // What to do when an option value is not in the list of defined option values
@@ -48,7 +48,7 @@ typedef enum {
48
48
  */
49
49
  VALUE mwr_mMagickWand;
50
50
  VALUE mwr_cWand;
51
- VALUE mwr_cGC;
51
+ VALUE mwr_cDrawing;
52
52
  VALUE mwr_eImageMagickError;
53
53
  VALUE mwr_eFatalImageMagickError;
54
54
 
@@ -56,7 +56,7 @@ VALUE mwr_eFatalImageMagickError;
56
56
  /*
57
57
  * Extern functions
58
58
  */
59
- extern void mwr_init_GC(void);
59
+ extern void mwr_init_Drawing(void);
60
60
  extern void mwr_init_Wand(void);
61
61
  extern void mwr_init_ImageMagickError(void);
62
62
  extern void mwr_init_FatalImageMagickError(void);
@@ -67,18 +67,24 @@ extern void mwr_check_error(ExceptionInfo *);
67
67
  extern MagickBooleanType mwr_get_option(VALUE, const char *, VALUE *);
68
68
  extern char *mwr_imagetype_to_s(ImageType);
69
69
  extern VALUE mwr_pixelpacket_to_hex(Image *, PixelPacket *);
70
+ extern VALUE mwr_pixelwand_to_hex(Image *, PixelWand *);
70
71
  extern void mwr_option_value_error(const char *, const char *);
71
72
  extern VALUE mwr_option_values_to_hash(char *);
72
73
  extern AlignType mwr_string_to_aligntype(VALUE, AlignType, OnUndefinedOption);
73
74
  extern ChannelType mwr_string_to_channeltype(VALUE, ChannelType, OnUndefinedOption);
75
+ extern ClipPathUnits mwr_string_to_clip_units(VALUE, ClipPathUnits, OnUndefinedOption);
74
76
  extern ColorspaceType mwr_string_to_colorspacetype(VALUE, ColorspaceType, OnUndefinedOption);
75
77
  extern CompositeOperator mwr_string_to_composetype(VALUE, CompositeOperator, OnUndefinedOption);
76
78
  extern CompressionType mwr_string_to_compressiontype(VALUE, CompressionType, OnUndefinedOption);
77
79
  extern DecorationType mwr_string_to_decorationtype(VALUE, DecorationType, OnUndefinedOption);
80
+ extern FillRule mwr_string_to_fillrule(VALUE, FillRule, OnUndefinedOption);
78
81
  extern FilterTypes mwr_string_to_filtertypes(VALUE, FilterTypes, OnUndefinedOption);
79
82
  extern GravityType mwr_string_to_gravitytype(VALUE, GravityType, OnUndefinedOption);
80
83
  extern ImageType mwr_string_to_imagetype(VALUE, ImageType, OnUndefinedOption);
84
+ extern LineCap mwr_string_to_line_cap(VALUE, LineCap, OnUndefinedOption);
85
+ extern LineJoin mwr_string_to_line_join(VALUE, LineJoin, OnUndefinedOption);
81
86
  extern MetricType mwr_string_to_metrictype(VALUE, MetricType, OnUndefinedOption);
87
+ extern PaintMethod mwr_string_to_paintmethod(VALUE, PaintMethod, OnUndefinedOption);
82
88
  extern StorageType mwr_string_to_storagetype(VALUE, StorageType, OnUndefinedOption);
83
89
  extern StretchType mwr_string_to_stretchtype(VALUE, StretchType, OnUndefinedOption);
84
90
  extern StyleType mwr_string_to_styletype(VALUE, StyleType, OnUndefinedOption);
@@ -87,5 +93,5 @@ extern char *mwr_format_size(const MagickSizeType, char *);
87
93
  extern void mwr_get_pixelpacket_from_pixelwand(PixelPacket *, PixelWand *);
88
94
  extern void mwr_get_pixelwand_from_pixelpacket(PixelWand *, PixelPacket *);
89
95
  extern void mwr_process_options(VALUE, VALUE);
90
- extern VALUE mwr_gc_new(void);
96
+ extern VALUE mwr_drawing_new(void);
91
97
  #endif
@@ -1,7 +1,7 @@
1
1
 
2
2
  /*
3
3
  * utility.c
4
- * $Id: utility.c 144 2009-05-31 20:51:53Z rmagick $
4
+ * $Id: utility.c 285 2009-08-14 23:09:24Z rmagick $
5
5
  * Copyright (C) 2009 Timothy Paul Hunter
6
6
  */
7
7
 
@@ -38,6 +38,7 @@ static ValueList align_types[] = {
38
38
  { "right", (long) RightAlign },
39
39
  { "start", (long) LeftAlign },
40
40
  { NULL, (long) UndefinedAlign } };
41
+
41
42
  static ValueList channel_types[] = {
42
43
  { "all", (long) AllChannels },
43
44
  { "alpha", (long) OpacityChannel },
@@ -59,6 +60,13 @@ static ValueList channel_types[] = {
59
60
  { "saturation", (long) GreenChannel },
60
61
  { "yellow", (long) YellowChannel },
61
62
  { NULL, (long) UndefinedChannel} };
63
+
64
+ static ValueList clip_units[] = {
65
+ { "objectboundingbox", (long) ObjectBoundingBox },
66
+ { "userspace", (long) UserSpace },
67
+ { "userspaceonuse", (long) UserSpaceOnUse } };
68
+
69
+
62
70
  static ValueList colorspace_types[] = {
63
71
  { "cmy", (long) CMYColorspace },
64
72
  { "cmyk", (long) CMYKColorspace },
@@ -83,6 +91,7 @@ static ValueList colorspace_types[] = {
83
91
  { "ypbpr", (long) YPbPrColorspace },
84
92
  { "yuv", (long) YUVColorspace },
85
93
  { NULL, (long) UndefinedColorspace } };
94
+
86
95
  static ValueList compose_types[] = {
87
96
  { "add", (long) AddCompositeOp },
88
97
  { "atop", (long) AtopCompositeOp },
@@ -142,6 +151,7 @@ static ValueList compose_types[] = {
142
151
  { "threshold", (long) ThresholdCompositeOp },
143
152
  { "xor", (long) XorCompositeOp },
144
153
  { NULL, (long) UndefinedCompositeOp } };
154
+
145
155
  static ValueList compression_types[] = {
146
156
  { "bzip", (long) BZipCompression },
147
157
  { "dxt1", (long) DXT1Compression },
@@ -159,12 +169,19 @@ static ValueList compression_types[] = {
159
169
  { "zip", (long) ZipCompression },
160
170
  { "runlengthencoded", (long) RLECompression },
161
171
  { NULL, (long) UndefinedCompression } };
172
+
162
173
  static ValueList decoration_types[] = {
163
174
  { "linethrough", (long) LineThroughDecoration },
164
175
  { "none", (long) NoDecoration },
165
176
  { "overline", (long) OverlineDecoration },
166
177
  { "underline", (long) UnderlineDecoration },
167
178
  { NULL, (long) UndefinedDecoration } };
179
+
180
+ static ValueList fill_rules[] = {
181
+ { "evenodd", (long) EvenOddRule },
182
+ { "nonzero", (long) NonZeroRule },
183
+ { NULL, (long) UndefinedRule } };
184
+
168
185
  static ValueList filter_types[] = {
169
186
  {"bartlett", (long) BartlettFilter},
170
187
  {"bessel", (long) BesselFilter},
@@ -217,6 +234,19 @@ static ValueList gravity_types[] = {
217
234
  { "west", (long) WestGravity },
218
235
  { "static", (long) StaticGravity },
219
236
  { NULL, (long) UndefinedGravity } };
237
+
238
+ static ValueList line_caps[] = {
239
+ { "butt", (long) ButtCap },
240
+ { "round", (long) RoundCap },
241
+ { "square", (long) SquareCap },
242
+ { NULL, (long) UndefinedCap } };
243
+
244
+ static ValueList line_joins[] = {
245
+ { "bevel", (long) BevelJoin },
246
+ { "miter", (long) MiterJoin },
247
+ { "round", (long) RoundJoin },
248
+ { NULL, (long) UndefinedJoin } };
249
+
220
250
  static ValueList metric_types[] = {
221
251
  { "ae", (long) AbsoluteErrorMetric },
222
252
  { "mae", (long) MeanAbsoluteErrorMetric },
@@ -226,6 +256,15 @@ static ValueList metric_types[] = {
226
256
  { "psnr", (long) PeakSignalToNoiseRatioMetric },
227
257
  { "rmse", (long) RootMeanSquaredErrorMetric },
228
258
  { NULL, (long) UndefinedMetric } };
259
+
260
+ static ValueList paint_methods[] = {
261
+ { "filltoborder", (long) FillToBorderMethod },
262
+ { "floodfill", (long) FloodfillMethod },
263
+ { "point", (long) PointMethod },
264
+ { "replace", (long) ReplaceMethod },
265
+ { "reset", (long) ResetMethod },
266
+ { NULL, (long) UndefinedMethod } };
267
+
229
268
  static ValueList storage_types[] = {
230
269
  { "char", (long) CharPixel },
231
270
  { "double", (long) DoublePixel },
@@ -235,6 +274,7 @@ static ValueList storage_types[] = {
235
274
  { "quantum", (long) QuantumPixel },
236
275
  { "short", (long) ShortPixel },
237
276
  { NULL, (long) UndefinedPixel } };
277
+
238
278
  static ValueList stretch_types[] = {
239
279
  { "any", (long) AnyStretch },
240
280
  { "condensed", (long) CondensedStretch },
@@ -247,12 +287,14 @@ static ValueList stretch_types[] = {
247
287
  { "ultracondensed", (long) UltraCondensedStretch },
248
288
  { "ultraexpanded", (long) UltraExpandedStretch },
249
289
  { NULL, (long) UndefinedStretch } };
290
+
250
291
  static ValueList style_types[] = {
251
- { "any", (long) AnyStyle },
292
+ { "any", (long) AnyStyle },
252
293
  { "italic", (long) ItalicStyle },
253
294
  { "normal", (long) NormalStyle },
254
295
  { "oblique", (long) ObliqueStyle },
255
296
  { NULL, (long) UndefinedStyle } };
297
+
256
298
  static ValueList weight_types[] = {
257
299
  { "any", 0L },
258
300
  { "light", 100L },
@@ -261,21 +303,26 @@ static ValueList weight_types[] = {
261
303
  { NULL, 0L } };
262
304
 
263
305
  static OptionList option_list[] = {
264
- {"align", align_types},
265
- {"channel", channel_types},
266
- {"colorspace", colorspace_types},
267
- {"compose", compose_types},
268
- {"compress", compression_types},
269
- {"decoration", decoration_types},
270
- {"filter", filter_types},
271
- {"gravity", gravity_types},
272
- {"metric", metric_types},
273
- {"type", image_types},
274
- {"storage_type", storage_types},
275
- {"stretch", stretch_types},
276
- {"style", style_types},
277
- {"weight", weight_types},
278
- {NULL, NULL} };
306
+ {"align", align_types},
307
+ {"channel", channel_types},
308
+ {"clip_units", clip_units},
309
+ {"colorspace", colorspace_types},
310
+ {"compose", compose_types},
311
+ {"compress", compression_types},
312
+ {"decoration", decoration_types},
313
+ {"fillrule", fill_rules},
314
+ {"filter", filter_types},
315
+ {"gravity", gravity_types},
316
+ {"metric", metric_types},
317
+ {"method", paint_methods},
318
+ {"type", image_types},
319
+ {"storage_type", storage_types},
320
+ {"line_cap", line_caps},
321
+ {"line_join", line_joins},
322
+ {"stretch", stretch_types},
323
+ {"style", style_types},
324
+ {"weight", weight_types},
325
+ {NULL, NULL} };
279
326
 
280
327
 
281
328
 
@@ -390,6 +437,11 @@ ChannelType mwr_string_to_channeltype(VALUE s, ChannelType defval, OnUndefinedOp
390
437
  return (ChannelType) string_to_enum("channel", channel_types, s, (long)defval, undef);
391
438
  }
392
439
 
440
+ ClipPathUnits mwr_string_to_clip_units(VALUE s, ClipPathUnits defval, OnUndefinedOption undef)
441
+ {
442
+ return (ClipPathUnits) string_to_enum("clip_units", clip_units, s, (long)defval, undef);
443
+ }
444
+
393
445
  ColorspaceType mwr_string_to_colorspacetype(VALUE s, ColorspaceType defval, OnUndefinedOption undef)
394
446
  {
395
447
  return (ColorspaceType) string_to_enum("colorspace", colorspace_types, s, (long)defval, undef);
@@ -410,6 +462,11 @@ DecorationType mwr_string_to_decorationtype(VALUE s, DecorationType defval, OnUn
410
462
  return (DecorationType) string_to_enum("decoration", decoration_types, s, (long)defval, undef);
411
463
  }
412
464
 
465
+ FillRule mwr_string_to_fillrule(VALUE s, FillRule defval, OnUndefinedOption undef)
466
+ {
467
+ return (FillRule) string_to_enum("fillrule", fill_rules, s, (long)defval, undef);
468
+ }
469
+
413
470
  FilterTypes mwr_string_to_filtertypes(VALUE s, FilterTypes defval, OnUndefinedOption undef)
414
471
  {
415
472
  return (FilterTypes) string_to_enum("filter", filter_types, s, (long)defval, undef);
@@ -425,11 +482,26 @@ ImageType mwr_string_to_imagetype(VALUE s, ImageType defval, OnUndefinedOption u
425
482
  return (ImageType) string_to_enum("type", image_types, s, (long)defval, undef);
426
483
  }
427
484
 
485
+ LineCap mwr_string_to_line_cap(VALUE s, LineCap defval, OnUndefinedOption undef)
486
+ {
487
+ return (LineCap) string_to_enum("line_cap", line_caps, s, (long)defval, undef);
488
+ }
489
+
490
+ LineJoin mwr_string_to_line_join(VALUE s, LineJoin defval, OnUndefinedOption undef)
491
+ {
492
+ return (LineCap) string_to_enum("line_join", line_joins, s, (long)defval, undef);
493
+ }
494
+
428
495
  MetricType mwr_string_to_metrictype(VALUE s, MetricType defval, OnUndefinedOption undef)
429
496
  {
430
497
  return (MetricType) string_to_enum("type", metric_types, s, (long)defval, undef);
431
498
  }
432
499
 
500
+ PaintMethod mwr_string_to_paintmethod(VALUE s, PaintMethod defval, OnUndefinedOption undef)
501
+ {
502
+ return (PaintMethod) string_to_enum("method", paint_methods, s, (long)defval, undef);
503
+ }
504
+
433
505
  StorageType mwr_string_to_storagetype(VALUE s, StorageType defval, OnUndefinedOption undef)
434
506
  {
435
507
  return (StretchType) string_to_enum("storage_type", storage_types, s, (long)defval, undef);
@@ -533,6 +605,21 @@ extern void mwr_get_pixelwand_from_pixelpacket(PixelWand *pixelwand, PixelPacket
533
605
 
534
606
 
535
607
 
608
+ /*
609
+ * Return the hex representation of the pixel as a Ruby string.
610
+ * (The PixelWand method always returns the rgb() representation.)
611
+ */
612
+ extern VALUE mwr_pixelwand_to_hex(Image *image, PixelWand *pixelwand)
613
+ {
614
+ PixelPacket pixelpacket;
615
+
616
+ mwr_get_pixelpacket_from_pixelwand(&pixelpacket, pixelwand);
617
+ return mwr_pixelpacket_to_hex(image, &pixelpacket);
618
+ }
619
+
620
+
621
+
622
+
536
623
  /*
537
624
  * Return the hex representation of the pixel as a Ruby string.
538
625
  * (The PixelWand method always returns the rgb() representation.)
@@ -659,16 +746,55 @@ static VALUE rescue_option(VALUE args, VALUE errinfo)
659
746
  * rescue NoMethodError
660
747
  * raise(ArgumentError, "undefined option :#{option}")
661
748
  * end
749
+ *
750
+ * Because the options hash is unordered in 1.8.*, we make two passes over the
751
+ * options. The :stroke_opacity and :fill_opacity options must succeed the
752
+ * :stroke and :fill options, otherwise the opacity specified by the colors
753
+ * overrides the opacity specified by the :xxx_opacity options. So the first
754
+ * pass specifically skips these two options, and the second pass skips over
755
+ * all but these two options.
662
756
  */
663
- static int begin_option(VALUE option, VALUE value, VALUE obj)
757
+
758
+ static int options_pass_1(VALUE option, VALUE value, VALUE obj)
664
759
  {
665
760
  VALUE args;
761
+ volatile VALUE fill_opacity, stroke_opacity;
762
+
763
+ fill_opacity = ID2SYM(rb_intern("fill_opacity"));
764
+ stroke_opacity = ID2SYM(rb_intern("stroke_opacity"));
765
+
766
+ if (!(option == fill_opacity || option == stroke_opacity))
767
+ {
768
+ args = rb_ary_new2(3);
769
+ rb_ary_push(args, option);
770
+ rb_ary_push(args, value);
771
+ rb_ary_push(args, obj);
772
+ (void) rb_rescue(call_option_setter, args, rescue_option, args);
773
+ }
774
+
775
+ return 0;
776
+ }
777
+
778
+
779
+
780
+
781
+ static int options_pass_2(VALUE option, VALUE value, VALUE obj)
782
+ {
783
+ VALUE args;
784
+ volatile VALUE fill_opacity, stroke_opacity;
785
+
786
+ fill_opacity = ID2SYM(rb_intern("fill_opacity"));
787
+ stroke_opacity = ID2SYM(rb_intern("stroke_opacity"));
788
+
789
+ if (option == fill_opacity || option == stroke_opacity)
790
+ {
791
+ args = rb_ary_new2(3);
792
+ rb_ary_push(args, option);
793
+ rb_ary_push(args, value);
794
+ rb_ary_push(args, obj);
795
+ (void) rb_rescue(call_option_setter, args, rescue_option, args);
796
+ }
666
797
 
667
- args = rb_ary_new2(3);
668
- rb_ary_push(args, option);
669
- rb_ary_push(args, value);
670
- rb_ary_push(args, obj);
671
- (void) rb_rescue(call_option_setter, args, rescue_option, args);
672
798
  return 0;
673
799
  }
674
800
 
@@ -682,7 +808,8 @@ void mwr_process_options(VALUE obj, VALUE options)
682
808
  {
683
809
  if (options != Qnil)
684
810
  {
685
- rb_hash_foreach(options, begin_option, obj);
811
+ rb_hash_foreach(options, options_pass_1, obj);
812
+ rb_hash_foreach(options, options_pass_2, obj);
686
813
  }
687
814
  }
688
815
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * wand.c
3
- * $Id: wand.c 147 2009-05-31 22:01:22Z rmagick $
3
+ * $Id: wand.c 275 2009-08-13 22:30:55Z rmagick $
4
4
  * Copyright (C) 2009 Timothy Paul Hunter
5
5
  */
6
6
 
@@ -253,7 +253,7 @@ leave:
253
253
  static VALUE wand_annotate(int argc, VALUE *argv, VALUE obj)
254
254
  {
255
255
  Wand *wand;
256
- GC *gc;
256
+ Drawing *drawing;
257
257
  double x, y, angle;
258
258
  volatile VALUE graphics_context;
259
259
  VALUE v, text, options;
@@ -271,11 +271,11 @@ static VALUE wand_annotate(int argc, VALUE *argv, VALUE obj)
271
271
  y = mwr_get_option(options, "y", &v) ? NUM2DBL(v) : 0.0;
272
272
  angle = mwr_get_option(options, "angle", &v) ? NUM2DBL(v) : 0.0;
273
273
 
274
- graphics_context = mwr_gc_new();
275
- Data_Get_Struct(graphics_context, GC, gc);
274
+ graphics_context = mwr_drawing_new();
275
+ Data_Get_Struct(graphics_context, Drawing, drawing);
276
276
 
277
277
  // Override default NorthWest gravity. It's useless.
278
- DrawSetGravity(gc->drawingwand, CenterGravity);
278
+ DrawSetGravity(drawing->wand, CenterGravity);
279
279
  mwr_process_options(graphics_context, options);
280
280
 
281
281
  Data_Get_Struct(obj, Wand, wand);
@@ -283,7 +283,7 @@ static VALUE wand_annotate(int argc, VALUE *argv, VALUE obj)
283
283
  MagickResetIterator(wand->magickwand);
284
284
  while (MagickNextImage(wand->magickwand) != MagickFalse)
285
285
  {
286
- MagickAnnotateImage(wand->magickwand, gc->drawingwand, x, y, angle, text_string);
286
+ MagickAnnotateImage(wand->magickwand, drawing->wand, x, y, angle, text_string);
287
287
  }
288
288
 
289
289
  return obj;
@@ -471,6 +471,72 @@ static VALUE wand_background(VALUE obj)
471
471
 
472
472
 
473
473
 
474
+ /*
475
+ * returns the border color property for the 0th image
476
+ */
477
+ static VALUE wand_bordercolor(VALUE obj)
478
+ {
479
+ Wand *wand;
480
+ PixelWand *bordercolor;
481
+ Image *image;
482
+ volatile VALUE color;
483
+
484
+ if (FIX2LONG(wand_length(obj)) == 0)
485
+ {
486
+ return Qnil;
487
+ }
488
+
489
+ Data_Get_Struct(obj, Wand, wand);
490
+
491
+ MagickResetIterator(wand->magickwand);
492
+ bordercolor = NewPixelWand();
493
+ MagickGetImageBorderColor(wand->magickwand, bordercolor);
494
+ mwr_check_magickwand_error(wand->magickwand);
495
+
496
+ image = GetImageFromMagickWand(wand->magickwand);
497
+ mwr_check_magickwand_error(wand->magickwand);
498
+
499
+ color = mwr_pixelwand_to_hex(image, bordercolor);
500
+ DestroyPixelWand(bordercolor);
501
+
502
+ return color;
503
+ }
504
+
505
+
506
+
507
+
508
+ /*
509
+ * sets the border color property for the 0th image
510
+ */
511
+ static VALUE wand_bordercolor_set(VALUE obj, VALUE color)
512
+ {
513
+ Wand *wand;
514
+ PixelWand *pixelwand;
515
+ char *bordercolor;
516
+
517
+ rb_check_frozen(obj);
518
+
519
+ Data_Get_Struct(obj, Wand, wand);
520
+
521
+ bordercolor = StringValuePtr(color);
522
+ pixelwand = NewPixelWand();
523
+ PixelSetColor(pixelwand, bordercolor);
524
+ mwr_check_pixelwand_error(pixelwand);
525
+
526
+ MagickResetIterator(wand->magickwand);
527
+ while (MagickNextImage(wand->magickwand) != MagickFalse)
528
+ {
529
+ (void) MagickSetImageBorderColor(wand->magickwand, pixelwand);
530
+ mwr_check_magickwand_error(wand->magickwand);
531
+ }
532
+ DestroyPixelWand(pixelwand);
533
+
534
+ return color;
535
+ }
536
+
537
+
538
+
539
+
474
540
  static VALUE convolve(int argc, VALUE *argv, VALUE obj,
475
541
  MagickBooleanType (*convolve)(MagickWand *, const ChannelType, const double, const double))
476
542
  {
@@ -520,17 +586,17 @@ static VALUE wand_border(int argc, VALUE *argv, VALUE obj)
520
586
  Wand *wand;
521
587
  PixelWand *pixelwand;
522
588
  VALUE color, wt, ht;
523
- char *border_color;
589
+ char *bordercolor;
524
590
  unsigned long width, height;
525
591
 
526
592
  rb_check_frozen(obj);
527
593
  (void) rb_scan_args(argc, argv, "12", &color, &wt, &ht);
528
- border_color = StringValuePtr(color);
594
+ bordercolor = StringValuePtr(color);
529
595
  width = wt != Qnil ? NUM2ULONG(wt) : 1UL;
530
596
  height = ht != Qnil ? NUM2ULONG(ht) : width;
531
597
 
532
598
  pixelwand = NewPixelWand();
533
- PixelSetColor(pixelwand, border_color);
599
+ PixelSetColor(pixelwand, bordercolor);
534
600
  mwr_check_pixelwand_error(pixelwand);
535
601
 
536
602
  Data_Get_Struct(obj, Wand, wand);
@@ -971,6 +1037,10 @@ static VALUE wand_display(VALUE obj)
971
1037
  Wand *wand;
972
1038
 
973
1039
  Data_Get_Struct(obj, Wand, wand);
1040
+ if (MagickGetNumberImages(wand->magickwand) == 0UL)
1041
+ {
1042
+ return Qnil;
1043
+ }
974
1044
  MagickDisplayImages(wand->magickwand, NULL);
975
1045
  mwr_check_magickwand_error(wand->magickwand);
976
1046
  return obj;
@@ -979,6 +1049,28 @@ static VALUE wand_display(VALUE obj)
979
1049
 
980
1050
 
981
1051
 
1052
+ static VALUE wand_draw(VALUE obj, VALUE drawing_obj)
1053
+ {
1054
+ Wand *wand;
1055
+ Drawing *drawing;
1056
+
1057
+ rb_check_frozen(obj);
1058
+ Data_Get_Struct(obj, Wand, wand);
1059
+ Data_Get_Struct(drawing_obj, Drawing, drawing);
1060
+
1061
+ MagickResetIterator(wand->magickwand);
1062
+ while (MagickNextImage(wand->magickwand) != MagickFalse)
1063
+ {
1064
+ MagickDrawImage(wand->magickwand, drawing->wand);
1065
+ mwr_check_magickwand_error(wand->magickwand);
1066
+ }
1067
+
1068
+ return obj;
1069
+ }
1070
+
1071
+
1072
+
1073
+
982
1074
  /*
983
1075
  * (>= 1.8.7) if no block return enumerator
984
1076
  */
@@ -2262,6 +2354,8 @@ void mwr_init_Wand(void)
2262
2354
  rb_define_method(mwr_cWand, "animate", wand_animate, -1);
2263
2355
  rb_define_method(mwr_cWand, "annotate", wand_annotate, -1);
2264
2356
  rb_define_method(mwr_cWand, "background", wand_background, 0);
2357
+ rb_define_method(mwr_cWand, "bordercolor", wand_bordercolor, 0);
2358
+ rb_define_method(mwr_cWand, "bordercolor=", wand_bordercolor_set, 1);
2265
2359
  rb_define_method(mwr_cWand, "blur", wand_blur, -1);
2266
2360
  rb_define_method(mwr_cWand, "border", wand_border, -1);
2267
2361
  rb_define_method(mwr_cWand, "colors", wand_colors, 0);
@@ -2273,6 +2367,7 @@ void mwr_init_Wand(void)
2273
2367
  rb_define_method(mwr_cWand, "depth", wand_depth, 0);
2274
2368
  rb_define_method(mwr_cWand, "dimensions", wand_dimensions, 0);
2275
2369
  rb_define_method(mwr_cWand, "display", wand_display, 0);
2370
+ rb_define_method(mwr_cWand, "draw", wand_draw, 1);
2276
2371
  rb_define_method(mwr_cWand, "export_pixels", wand_export_pixels, -1);
2277
2372
  rb_define_method(mwr_cWand, "filename", wand_filename, 0);
2278
2373
  rb_define_method(mwr_cWand, "format", wand_format, 0);