magickwand 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,152 @@
1
+ /*
2
+ * magickwand.c
3
+ * $Id: magickwand.c 146 2009-05-31 22:00:57Z rmagick $
4
+ * Copyright (C) 2009 Timothy Paul Hunter
5
+ */
6
+
7
+
8
+
9
+ #define MAIN 1
10
+ #include "magickwand.h"
11
+
12
+
13
+
14
+
15
+ /*
16
+ * Handle transferring ImageMagick memory allocations/frees to Ruby.
17
+ * These functions have the same signature as the equivalent C functions.
18
+ */
19
+ static void *mwr_malloc(size_t size)
20
+ {
21
+ return xmalloc((long)size);
22
+ }
23
+
24
+
25
+
26
+
27
+ static void *mwr_realloc(void *ptr, size_t size)
28
+ {
29
+ return xrealloc(ptr, (long)size);
30
+ }
31
+
32
+
33
+
34
+
35
+ static void mwr_free(void *ptr)
36
+ {
37
+ xfree(ptr);
38
+ }
39
+
40
+
41
+
42
+
43
+ /*
44
+ * Copy MagickWand configure options to a constant hash
45
+ */
46
+ static void ImageMagick_config(void)
47
+ {
48
+ volatile VALUE key, value;
49
+ volatile VALUE config_hash;
50
+ char **config;
51
+ char *option;
52
+ unsigned long n, n_config;
53
+ unsigned long qdepth, qrange;
54
+
55
+ config_hash = rb_hash_new();
56
+
57
+ config = MagickQueryConfigureOptions("*", &n_config);
58
+ for (n = 0; n < n_config; n++)
59
+ {
60
+ key = rb_str_new2(config[n]);
61
+ rb_obj_freeze(key);
62
+ option = MagickQueryConfigureOption(config[n]);
63
+ value = rb_str_new2(option);
64
+ rb_obj_freeze(value);
65
+ rb_hash_aset(config_hash, key, value);
66
+ }
67
+
68
+ rb_obj_freeze(config_hash);
69
+ rb_define_const(mwr_mMagickWand, "IMAGEMAGICK_CONFIG", config_hash);
70
+
71
+ (void) GetMagickQuantumDepth(&qdepth);
72
+ rb_define_const(mwr_mMagickWand, "QUANTUM_DEPTH", LONG2FIX((long)qdepth));
73
+
74
+ (void) GetMagickQuantumRange(&qrange);
75
+ rb_define_const(mwr_mMagickWand, "QUANTUM_RANGE", LONG2FIX((long)qrange));
76
+
77
+ rb_define_const(mwr_mMagickWand, "QUANTUM_SIZE", INT2FIX((int)sizeof(Quantum)));
78
+
79
+ }
80
+
81
+
82
+
83
+
84
+ static VALUE magickwand_list_fonts(VALUE mod)
85
+ {
86
+ unsigned long n, nfonts;
87
+ char **fonts;
88
+ volatile VALUE font_ary;
89
+
90
+ font_ary = rb_ary_new();
91
+ fonts = MagickQueryFonts("*", &nfonts);
92
+ for (n = 0; n < nfonts; n++)
93
+ {
94
+ rb_ary_push(font_ary, rb_str_new2(fonts[n]));
95
+ }
96
+ return font_ary;
97
+ mod = mod;
98
+ }
99
+
100
+
101
+
102
+
103
+ /*
104
+ * MagickWand.option_values(option-name)
105
+ * returns the valid values of the specified option, or all options
106
+ * if option-name is omitted. Values returned in a hash. The key
107
+ * is the option name and the value is an array of option values.
108
+ */
109
+ static VALUE magickwand_option_values(int argc, VALUE *argv, VALUE mod)
110
+ {
111
+ volatile VALUE option;
112
+ char *name = NULL;
113
+
114
+ (void) rb_scan_args(argc, argv, "01", &option);
115
+ if (option != Qnil)
116
+ {
117
+ option = rb_String(option);
118
+ name = StringValuePtr(option);
119
+ }
120
+ return mwr_option_values_to_hash(name);
121
+ mod = mod;
122
+ }
123
+
124
+
125
+
126
+
127
+ /*
128
+ * Initialize the MagickWand environment. Create the MagickWand module.
129
+ */
130
+ void Init_magickwand(void)
131
+ {
132
+ volatile VALUE version;
133
+
134
+ MagickWandGenesis();
135
+ SetMagickMemoryMethods(mwr_malloc, mwr_realloc, mwr_free);
136
+
137
+ mwr_mMagickWand = rb_define_module("MagickWand");
138
+
139
+ version = rb_str_new2(MAGICKWAND_VERSION);
140
+ rb_obj_freeze(version);
141
+ rb_define_const(mwr_mMagickWand, "VERSION", version);
142
+ rb_define_module_function(mwr_mMagickWand, "list_fonts", magickwand_list_fonts, 0);
143
+ rb_define_module_function(mwr_mMagickWand, "option_values", magickwand_option_values, -1);
144
+
145
+ ImageMagick_config();
146
+
147
+ mwr_init_Wand();
148
+ mwr_init_GC();
149
+ mwr_init_ImageMagickError();
150
+ mwr_init_FatalImageMagickError();
151
+
152
+ }
@@ -0,0 +1,91 @@
1
+ /*
2
+ * magickwand.h
3
+ * $Id: magickwand.h 25 2009-04-28 23:11:33Z rmagick $
4
+ * Copyright (C) 2009 Timothy Paul Hunter
5
+ */
6
+
7
+ #if !defined(MAGICKWAND_H)
8
+ #define MAGICKWAND_H 1
9
+
10
+ #include <stdio.h>
11
+ #include <stdlib.h>
12
+ #include "wand/MagickWand.h"
13
+ #include "ruby.h"
14
+
15
+ #undef EXTERN
16
+ #if defined(MAIN)
17
+ #define EXTERN
18
+ #else
19
+ #define EXTERN extern
20
+ #endif
21
+
22
+
23
+
24
+ /*
25
+ * Types
26
+ */
27
+ typedef struct
28
+ {
29
+ MagickWand *magickwand;
30
+ } Wand;
31
+
32
+
33
+ typedef struct
34
+ {
35
+ DrawingWand *drawingwand;
36
+ } GC;
37
+
38
+
39
+ // What to do when an option value is not in the list of defined option values
40
+ typedef enum {
41
+ IgnoreUndefinedOption,
42
+ RaiseUndefinedOption
43
+ } OnUndefinedOption;
44
+
45
+
46
+ /*
47
+ * Extern variables
48
+ */
49
+ VALUE mwr_mMagickWand;
50
+ VALUE mwr_cWand;
51
+ VALUE mwr_cGC;
52
+ VALUE mwr_eImageMagickError;
53
+ VALUE mwr_eFatalImageMagickError;
54
+
55
+
56
+ /*
57
+ * Extern functions
58
+ */
59
+ extern void mwr_init_GC(void);
60
+ extern void mwr_init_Wand(void);
61
+ extern void mwr_init_ImageMagickError(void);
62
+ extern void mwr_init_FatalImageMagickError(void);
63
+ extern void mwr_check_magickwand_error(MagickWand *);
64
+ extern void mwr_check_pixelwand_error(PixelWand *);
65
+ extern void mwr_check_drawingwand_error(DrawingWand *);
66
+ extern void mwr_check_error(ExceptionInfo *);
67
+ extern MagickBooleanType mwr_get_option(VALUE, const char *, VALUE *);
68
+ extern char *mwr_imagetype_to_s(ImageType);
69
+ extern VALUE mwr_pixelpacket_to_hex(Image *, PixelPacket *);
70
+ extern void mwr_option_value_error(const char *, const char *);
71
+ extern VALUE mwr_option_values_to_hash(char *);
72
+ extern AlignType mwr_string_to_aligntype(VALUE, AlignType, OnUndefinedOption);
73
+ extern ChannelType mwr_string_to_channeltype(VALUE, ChannelType, OnUndefinedOption);
74
+ extern ColorspaceType mwr_string_to_colorspacetype(VALUE, ColorspaceType, OnUndefinedOption);
75
+ extern CompositeOperator mwr_string_to_composetype(VALUE, CompositeOperator, OnUndefinedOption);
76
+ extern CompressionType mwr_string_to_compressiontype(VALUE, CompressionType, OnUndefinedOption);
77
+ extern DecorationType mwr_string_to_decorationtype(VALUE, DecorationType, OnUndefinedOption);
78
+ extern FilterTypes mwr_string_to_filtertypes(VALUE, FilterTypes, OnUndefinedOption);
79
+ extern GravityType mwr_string_to_gravitytype(VALUE, GravityType, OnUndefinedOption);
80
+ extern ImageType mwr_string_to_imagetype(VALUE, ImageType, OnUndefinedOption);
81
+ extern MetricType mwr_string_to_metrictype(VALUE, MetricType, OnUndefinedOption);
82
+ extern StorageType mwr_string_to_storagetype(VALUE, StorageType, OnUndefinedOption);
83
+ extern StretchType mwr_string_to_stretchtype(VALUE, StretchType, OnUndefinedOption);
84
+ extern StyleType mwr_string_to_styletype(VALUE, StyleType, OnUndefinedOption);
85
+ extern unsigned long mwr_string_to_weight(VALUE, unsigned long, OnUndefinedOption);
86
+ extern char *mwr_format_size(const MagickSizeType, char *);
87
+ extern void mwr_get_pixelpacket_from_pixelwand(PixelPacket *, PixelWand *);
88
+ extern void mwr_get_pixelwand_from_pixelpacket(PixelWand *, PixelPacket *);
89
+ extern void mwr_process_options(VALUE, VALUE);
90
+ extern VALUE mwr_gc_new(void);
91
+ #endif
@@ -0,0 +1,819 @@
1
+
2
+ /*
3
+ * utility.c
4
+ * $Id: utility.c 144 2009-05-31 20:51:53Z rmagick $
5
+ * Copyright (C) 2009 Timothy Paul Hunter
6
+ */
7
+
8
+ #include <math.h>
9
+ #include <ctype.h>
10
+ #include "magickwand.h"
11
+
12
+
13
+
14
+
15
+ #define ENUMERATOR_STR(type) case type: str = #type; break
16
+
17
+
18
+
19
+
20
+ typedef struct
21
+ {
22
+ const char *name;
23
+ long type;
24
+ } ValueList;
25
+
26
+
27
+ typedef struct {
28
+ char *name;
29
+ ValueList *value;
30
+ } OptionList;
31
+
32
+
33
+ static ValueList align_types[] = {
34
+ { "center", (long) CenterAlign },
35
+ { "end", (long) RightAlign },
36
+ { "left", (long) LeftAlign },
37
+ { "middle", (long) CenterAlign },
38
+ { "right", (long) RightAlign },
39
+ { "start", (long) LeftAlign },
40
+ { NULL, (long) UndefinedAlign } };
41
+ static ValueList channel_types[] = {
42
+ { "all", (long) AllChannels },
43
+ { "alpha", (long) OpacityChannel },
44
+ { "black", (long) BlackChannel },
45
+ { "blue", (long) BlueChannel },
46
+ { "cyan", (long) CyanChannel },
47
+ { "default", (long) DefaultChannels},
48
+ { "gray", (long) GrayChannel },
49
+ { "green", (long) GreenChannel },
50
+ { "hue", (long) RedChannel },
51
+ { "index", (long) IndexChannel },
52
+ { "lightness", (long) BlueChannel },
53
+ { "luminance", (long) BlueChannel },
54
+ { "luminosity", (long) BlueChannel }, /* deprecated */
55
+ { "magenta", (long) MagentaChannel },
56
+ { "matte", (long) OpacityChannel },
57
+ { "opacity", (long) OpacityChannel },
58
+ { "red", (long) RedChannel },
59
+ { "saturation", (long) GreenChannel },
60
+ { "yellow", (long) YellowChannel },
61
+ { NULL, (long) UndefinedChannel} };
62
+ static ValueList colorspace_types[] = {
63
+ { "cmy", (long) CMYColorspace },
64
+ { "cmyk", (long) CMYKColorspace },
65
+ { "gray", (long) GRAYColorspace },
66
+ { "hsb", (long) HSBColorspace },
67
+ { "hsl", (long) HSLColorspace },
68
+ { "hwb", (long) HWBColorspace },
69
+ { "lab", (long) LabColorspace },
70
+ { "log", (long) LogColorspace },
71
+ { "ohta", (long) OHTAColorspace },
72
+ { "rec601luma", (long) Rec601LumaColorspace },
73
+ { "rec601ycbcr", (long) Rec601YCbCrColorspace },
74
+ { "rec709luma", (long) Rec709LumaColorspace },
75
+ { "rec709ycbcr", (long) Rec709YCbCrColorspace },
76
+ { "rgb", (long) RGBColorspace },
77
+ { "srgb", (long) sRGBColorspace },
78
+ { "transparent", (long) TransparentColorspace },
79
+ { "xyz", (long) XYZColorspace },
80
+ { "ycbcr", (long) YCbCrColorspace },
81
+ { "ycc", (long) YCCColorspace },
82
+ { "yiq", (long) YIQColorspace },
83
+ { "ypbpr", (long) YPbPrColorspace },
84
+ { "yuv", (long) YUVColorspace },
85
+ { NULL, (long) UndefinedColorspace } };
86
+ static ValueList compose_types[] = {
87
+ { "add", (long) AddCompositeOp },
88
+ { "atop", (long) AtopCompositeOp },
89
+ { "blend", (long) BlendCompositeOp },
90
+ { "bumpmap", (long) BumpmapCompositeOp },
91
+ { "changemask", (long) ChangeMaskCompositeOp },
92
+ { "clear", (long) ClearCompositeOp },
93
+ { "colorburn", (long) ColorBurnCompositeOp },
94
+ { "colordodge", (long) ColorDodgeCompositeOp },
95
+ { "colorize", (long) ColorizeCompositeOp },
96
+ { "copyblack", (long) CopyBlackCompositeOp },
97
+ { "copyblue", (long) CopyBlueCompositeOp },
98
+ { "copycyan", (long) CopyCyanCompositeOp },
99
+ { "copygreen", (long) CopyGreenCompositeOp },
100
+ { "copy", (long) CopyCompositeOp },
101
+ { "copymagenta", (long) CopyMagentaCompositeOp },
102
+ { "copyopacity", (long) CopyOpacityCompositeOp },
103
+ { "copyred", (long) CopyRedCompositeOp },
104
+ { "copyyellow", (long) CopyYellowCompositeOp },
105
+ { "darken", (long) DarkenCompositeOp },
106
+ { "divide", (long) DivideCompositeOp },
107
+ { "dst", (long) DstCompositeOp },
108
+ { "difference", (long) DifferenceCompositeOp },
109
+ { "displace", (long) DisplaceCompositeOp },
110
+ { "dissolve", (long) DissolveCompositeOp },
111
+ { "dstatop", (long) DstAtopCompositeOp },
112
+ { "dstin", (long) DstInCompositeOp },
113
+ { "dstout", (long) DstOutCompositeOp },
114
+ { "dstover", (long) DstOverCompositeOp },
115
+ { "dst", (long) DstCompositeOp },
116
+ { "exclusion", (long) ExclusionCompositeOp },
117
+ { "hardlight", (long) HardLightCompositeOp },
118
+ { "hue", (long) HueCompositeOp },
119
+ { "in", (long) InCompositeOp },
120
+ { "lighten", (long) LightenCompositeOp },
121
+ { "linearlight", (long) LinearLightCompositeOp },
122
+ { "luminize", (long) LuminizeCompositeOp },
123
+ { "minus", (long) MinusCompositeOp },
124
+ { "modulate", (long) ModulateCompositeOp },
125
+ { "multiply", (long) MultiplyCompositeOp },
126
+ { "none", (long) NoCompositeOp },
127
+ { "out", (long) OutCompositeOp },
128
+ { "overlay", (long) OverlayCompositeOp },
129
+ { "over", (long) OverCompositeOp },
130
+ { "plus", (long) PlusCompositeOp },
131
+ { "replace", (long) ReplaceCompositeOp },
132
+ { "saturate", (long) SaturateCompositeOp },
133
+ { "screen", (long) ScreenCompositeOp },
134
+ { "softlight", (long) SoftLightCompositeOp },
135
+ { "src", (long) SrcCompositeOp },
136
+ { "srcatop", (long) SrcAtopCompositeOp },
137
+ { "srcin", (long) SrcInCompositeOp },
138
+ { "srcout", (long) SrcOutCompositeOp },
139
+ { "srcover", (long) SrcOverCompositeOp },
140
+ { "src", (long) SrcCompositeOp },
141
+ { "subtract", (long) SubtractCompositeOp },
142
+ { "threshold", (long) ThresholdCompositeOp },
143
+ { "xor", (long) XorCompositeOp },
144
+ { NULL, (long) UndefinedCompositeOp } };
145
+ static ValueList compression_types[] = {
146
+ { "bzip", (long) BZipCompression },
147
+ { "dxt1", (long) DXT1Compression },
148
+ { "dxt3", (long) DXT3Compression },
149
+ { "dxt5", (long) DXT5Compression },
150
+ { "fax", (long) FaxCompression },
151
+ { "group4", (long) Group4Compression },
152
+ { "jpeg", (long) JPEGCompression },
153
+ { "jpeg2000", (long) JPEG2000Compression },
154
+ { "lossless", (long) LosslessJPEGCompression },
155
+ { "losslessjpeg", (long) LosslessJPEGCompression },
156
+ { "lzw", (long) LZWCompression },
157
+ { "none", (long) NoCompression },
158
+ { "rle", (long) RLECompression },
159
+ { "zip", (long) ZipCompression },
160
+ { "runlengthencoded", (long) RLECompression },
161
+ { NULL, (long) UndefinedCompression } };
162
+ static ValueList decoration_types[] = {
163
+ { "linethrough", (long) LineThroughDecoration },
164
+ { "none", (long) NoDecoration },
165
+ { "overline", (long) OverlineDecoration },
166
+ { "underline", (long) UnderlineDecoration },
167
+ { NULL, (long) UndefinedDecoration } };
168
+ static ValueList filter_types[] = {
169
+ {"bartlett", (long) BartlettFilter},
170
+ {"bessel", (long) BesselFilter},
171
+ {"blackman", (long) BlackmanFilter},
172
+ {"bohman", (long) BohmanFilter},
173
+ {"box", (long) BoxFilter},
174
+ {"catrom", (long) CatromFilter},
175
+ {"cubic", (long) CubicFilter},
176
+ {"gaussian", (long) GaussianFilter},
177
+ {"hamming", (long) HammingFilter},
178
+ {"hanning", (long) HanningFilter},
179
+ {"hermite", (long) HermiteFilter},
180
+ {"kaiser", (long) KaiserFilter},
181
+ {"lagrange", (long) LagrangeFilter},
182
+ {"lanczos", (long) LanczosFilter},
183
+ {"mitchell", (long) MitchellFilter},
184
+ {"parzen", (long) ParzenFilter},
185
+ {"point", (long) PointFilter},
186
+ {"quadratic", (long) QuadraticFilter},
187
+ {"sinc", (long) SincFilter},
188
+ {"triangle", (long) TriangleFilter},
189
+ {"welsh", (long) WelshFilter},
190
+ {NULL, (long) UndefinedFilter} };
191
+
192
+ static ValueList image_types[] = {
193
+ { "bilevel", (long) BilevelType },
194
+ { "colorseparation", (long) ColorSeparationType },
195
+ { "colorseparationmatte", (long) ColorSeparationMatteType },
196
+ { "grayscale", (long) GrayscaleType },
197
+ { "grayscalematte", (long) GrayscaleMatteType },
198
+ { "optimize", (long) OptimizeType },
199
+ { "palette", (long) PaletteType },
200
+ { "palettebilevelmatte", (long) PaletteBilevelMatteType },
201
+ { "palettematte", (long) PaletteMatteType },
202
+ { "truecolormatte", (long) TrueColorMatteType },
203
+ { "truecolor", (long) TrueColorType },
204
+ { NULL, (long) UndefinedType } };
205
+
206
+ static ValueList gravity_types[] = {
207
+ { "none", (long) UndefinedGravity },
208
+ { "center", (long) CenterGravity },
209
+ { "east", (long) EastGravity },
210
+ { "forget", (long) ForgetGravity },
211
+ { "northeast", (long) NorthEastGravity },
212
+ { "north", (long) NorthGravity },
213
+ { "northwest", (long) NorthWestGravity },
214
+ { "southeast", (long) SouthEastGravity },
215
+ { "south", (long) SouthGravity },
216
+ { "southwest", (long) SouthWestGravity },
217
+ { "west", (long) WestGravity },
218
+ { "static", (long) StaticGravity },
219
+ { NULL, (long) UndefinedGravity } };
220
+ static ValueList metric_types[] = {
221
+ { "ae", (long) AbsoluteErrorMetric },
222
+ { "mae", (long) MeanAbsoluteErrorMetric },
223
+ { "mepp", (long) MeanErrorPerPixelMetric },
224
+ { "mse", (long) MeanSquaredErrorMetric },
225
+ { "pae", (long) PeakAbsoluteErrorMetric },
226
+ { "psnr", (long) PeakSignalToNoiseRatioMetric },
227
+ { "rmse", (long) RootMeanSquaredErrorMetric },
228
+ { NULL, (long) UndefinedMetric } };
229
+ static ValueList storage_types[] = {
230
+ { "char", (long) CharPixel },
231
+ { "double", (long) DoublePixel },
232
+ { "float", (long) FloatPixel },
233
+ { "integer", (long) IntegerPixel },
234
+ { "long", (long) LongPixel },
235
+ { "quantum", (long) QuantumPixel },
236
+ { "short", (long) ShortPixel },
237
+ { NULL, (long) UndefinedPixel } };
238
+ static ValueList stretch_types[] = {
239
+ { "any", (long) AnyStretch },
240
+ { "condensed", (long) CondensedStretch },
241
+ { "expanded", (long) ExpandedStretch },
242
+ { "extracondensed", (long) ExtraCondensedStretch },
243
+ { "extraexpanded", (long) ExtraExpandedStretch },
244
+ { "normal", (long) NormalStretch },
245
+ { "semicondensed", (long) SemiCondensedStretch },
246
+ { "semiexpanded", (long) SemiExpandedStretch },
247
+ { "ultracondensed", (long) UltraCondensedStretch },
248
+ { "ultraexpanded", (long) UltraExpandedStretch },
249
+ { NULL, (long) UndefinedStretch } };
250
+ static ValueList style_types[] = {
251
+ { "any", (long) AnyStyle },
252
+ { "italic", (long) ItalicStyle },
253
+ { "normal", (long) NormalStyle },
254
+ { "oblique", (long) ObliqueStyle },
255
+ { NULL, (long) UndefinedStyle } };
256
+ static ValueList weight_types[] = {
257
+ { "any", 0L },
258
+ { "light", 100L },
259
+ { "normal", 400L },
260
+ { "bold", 700L },
261
+ { NULL, 0L } };
262
+
263
+ 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} };
279
+
280
+
281
+
282
+
283
+ /*
284
+ * lowercase up to 'lim' characters in a string
285
+ */
286
+ static void downcase(char *out, size_t lim, const char *in)
287
+ {
288
+ char c;
289
+ size_t n;
290
+
291
+ for (n = 0; (n < lim) && (c = *in++); n++)
292
+ {
293
+ *out++ = tolower(c);
294
+ }
295
+ *out = '\0';
296
+ }
297
+
298
+
299
+
300
+ VALUE mwr_option_values_to_hash(char *option_name)
301
+ {
302
+ volatile VALUE option_values_hash;
303
+ volatile VALUE option_sym, values;
304
+ volatile VALUE value;
305
+ OptionList *o;
306
+ ValueList *v;
307
+ char name[100];
308
+
309
+ if (option_name != NULL)
310
+ {
311
+ downcase(name, sizeof(name), option_name);
312
+ }
313
+
314
+ option_values_hash = rb_hash_new();
315
+ for (o = option_list; o->name != NULL; o++)
316
+ {
317
+ if (!option_name || strcmp(name, o->name) == 0)
318
+ {
319
+ option_sym = ID2SYM(rb_intern(o->name));
320
+ values = rb_ary_new();
321
+ for (v = o->value; v->name != NULL; v++)
322
+ {
323
+ value = rb_str_new2(v->name);
324
+ rb_obj_freeze(value);
325
+ rb_ary_push(values, value);
326
+ }
327
+ rb_obj_freeze(values);
328
+ rb_hash_aset(option_values_hash, option_sym, values);
329
+ }
330
+ }
331
+
332
+ rb_obj_freeze(option_values_hash);
333
+ return option_values_hash;
334
+ }
335
+
336
+
337
+
338
+
339
+
340
+ /*
341
+ * Raise an undefined option value exception
342
+ */
343
+ void mwr_option_value_error(const char *option, const char *value)
344
+ {
345
+ rb_raise(rb_eArgError, "invalid value for :%s '%s'", option, value);
346
+ }
347
+
348
+
349
+
350
+
351
+ /*
352
+ * return the enum that matches the name. Return last enum in list if no match.
353
+ */
354
+ static long string_to_enum(const char *option, ValueList *elist, VALUE s, long defval, OnUndefinedOption undef)
355
+ {
356
+ char ns[100];
357
+ ValueList *e;
358
+
359
+ if (s == Qnil)
360
+ {
361
+ return defval;
362
+ }
363
+
364
+ downcase(ns, sizeof(ns), StringValuePtr(s));
365
+ for (e = elist; e->name != NULL; e++)
366
+ {
367
+ if (strcmp(ns, e->name) == 0)
368
+ {
369
+ break;
370
+ }
371
+ }
372
+
373
+ if (e->name == NULL && undef == RaiseUndefinedOption)
374
+ {
375
+ mwr_option_value_error(option, StringValuePtr(s));
376
+ }
377
+ return e->type;
378
+ }
379
+
380
+
381
+
382
+
383
+ AlignType mwr_string_to_aligntype(VALUE s, AlignType defval, OnUndefinedOption undef)
384
+ {
385
+ return (AlignType) string_to_enum("align", align_types, s, (long)defval, undef);
386
+ }
387
+
388
+ ChannelType mwr_string_to_channeltype(VALUE s, ChannelType defval, OnUndefinedOption undef)
389
+ {
390
+ return (ChannelType) string_to_enum("channel", channel_types, s, (long)defval, undef);
391
+ }
392
+
393
+ ColorspaceType mwr_string_to_colorspacetype(VALUE s, ColorspaceType defval, OnUndefinedOption undef)
394
+ {
395
+ return (ColorspaceType) string_to_enum("colorspace", colorspace_types, s, (long)defval, undef);
396
+ }
397
+
398
+ CompositeOperator mwr_string_to_composetype(VALUE s, CompositeOperator defval, OnUndefinedOption undef)
399
+ {
400
+ return (CompositeOperator) string_to_enum("compose", compose_types, s, (long)defval, undef);
401
+ }
402
+
403
+ CompressionType mwr_string_to_compressiontype(VALUE s, CompressionType defval, OnUndefinedOption undef)
404
+ {
405
+ return (CompressionType) string_to_enum("compress", compression_types, s, (long)defval, undef);
406
+ }
407
+
408
+ DecorationType mwr_string_to_decorationtype(VALUE s, DecorationType defval, OnUndefinedOption undef)
409
+ {
410
+ return (DecorationType) string_to_enum("decoration", decoration_types, s, (long)defval, undef);
411
+ }
412
+
413
+ FilterTypes mwr_string_to_filtertypes(VALUE s, FilterTypes defval, OnUndefinedOption undef)
414
+ {
415
+ return (FilterTypes) string_to_enum("filter", filter_types, s, (long)defval, undef);
416
+ }
417
+
418
+ GravityType mwr_string_to_gravitytype(VALUE s, GravityType defval, OnUndefinedOption undef)
419
+ {
420
+ return (GravityType) string_to_enum("gravity", gravity_types, s, (long)defval, undef);
421
+ }
422
+
423
+ ImageType mwr_string_to_imagetype(VALUE s, ImageType defval, OnUndefinedOption undef)
424
+ {
425
+ return (ImageType) string_to_enum("type", image_types, s, (long)defval, undef);
426
+ }
427
+
428
+ MetricType mwr_string_to_metrictype(VALUE s, MetricType defval, OnUndefinedOption undef)
429
+ {
430
+ return (MetricType) string_to_enum("type", metric_types, s, (long)defval, undef);
431
+ }
432
+
433
+ StorageType mwr_string_to_storagetype(VALUE s, StorageType defval, OnUndefinedOption undef)
434
+ {
435
+ return (StretchType) string_to_enum("storage_type", storage_types, s, (long)defval, undef);
436
+ }
437
+
438
+ StretchType mwr_string_to_stretchtype(VALUE s, StretchType defval, OnUndefinedOption undef)
439
+ {
440
+ return (StretchType) string_to_enum("stretch", stretch_types, s, (long)defval, undef);
441
+ }
442
+
443
+ StyleType mwr_string_to_styletype(VALUE s, StyleType defval, OnUndefinedOption undef)
444
+ {
445
+ return (StyleType) string_to_enum("style", style_types, s, (long)defval, undef);
446
+ }
447
+
448
+ unsigned long mwr_string_to_weight(VALUE s, unsigned long defval, OnUndefinedOption undef)
449
+ {
450
+ return (unsigned long) string_to_enum("weight", weight_types, s, (long)defval, undef);
451
+ }
452
+
453
+
454
+
455
+ /*
456
+ * return ImageType enum as string (for #inspect)
457
+ */
458
+ char *mwr_imagetype_to_s(ImageType type)
459
+ {
460
+ char *str;
461
+
462
+ switch (type)
463
+ {
464
+ ENUMERATOR_STR(UndefinedType);
465
+ ENUMERATOR_STR(BilevelType);
466
+ ENUMERATOR_STR(GrayscaleType);
467
+ ENUMERATOR_STR(GrayscaleMatteType);
468
+ ENUMERATOR_STR(PaletteType);
469
+ ENUMERATOR_STR(PaletteMatteType);
470
+ ENUMERATOR_STR(TrueColorType);
471
+ ENUMERATOR_STR(TrueColorMatteType);
472
+ ENUMERATOR_STR(ColorSeparationType);
473
+ ENUMERATOR_STR(ColorSeparationMatteType);
474
+ ENUMERATOR_STR(OptimizeType);
475
+ ENUMERATOR_STR(PaletteBilevelMatteType);
476
+ default:
477
+ str = "UndefinedType";
478
+ break;
479
+ }
480
+
481
+ return str;
482
+ }
483
+
484
+
485
+
486
+
487
+ /*
488
+ * If the option is present store its value in *value and return
489
+ * MagickTrue, otherwise store Qnil and return MagickFalse.
490
+ *
491
+ * Do _not_ delete keys from the options hash. We don't own it!
492
+ */
493
+ MagickBooleanType mwr_get_option(VALUE options, const char *name, VALUE *value)
494
+ {
495
+ volatile VALUE key;
496
+
497
+ if (options != Qnil)
498
+ {
499
+ key = ID2SYM(rb_intern(name));
500
+ if (rb_funcall(options, rb_intern("has_key?"), 1, key) == Qtrue)
501
+ {
502
+ *value = rb_hash_aref(options, key);
503
+ return MagickTrue;
504
+ }
505
+ }
506
+
507
+ *value = Qnil;
508
+ return MagickFalse;
509
+ }
510
+
511
+
512
+
513
+
514
+ extern void mwr_get_pixelpacket_from_pixelwand(PixelPacket *pixelpacket, PixelWand *pixelwand)
515
+ {
516
+ pixelpacket->red = PixelGetRedQuantum(pixelwand);
517
+ pixelpacket->green = PixelGetGreenQuantum(pixelwand);
518
+ pixelpacket->blue = PixelGetBlueQuantum(pixelwand);
519
+ pixelpacket->opacity = PixelGetOpacityQuantum(pixelwand);
520
+ }
521
+
522
+
523
+
524
+
525
+ extern void mwr_get_pixelwand_from_pixelpacket(PixelWand *pixelwand, PixelPacket *pixelpacket)
526
+ {
527
+ PixelSetRedQuantum(pixelwand, pixelpacket->red);
528
+ PixelSetGreenQuantum(pixelwand, pixelpacket->green);
529
+ PixelSetBlueQuantum(pixelwand, pixelpacket->blue);
530
+ PixelSetOpacityQuantum(pixelwand, pixelpacket->opacity);
531
+ }
532
+
533
+
534
+
535
+
536
+ /*
537
+ * Return the hex representation of the pixel as a Ruby string.
538
+ * (The PixelWand method always returns the rgb() representation.)
539
+ */
540
+ extern VALUE mwr_pixelpacket_to_hex(Image *image, PixelPacket *pixelpacket)
541
+ {
542
+ char name[MaxTextExtent];
543
+ MagickPixelPacket mpp;
544
+
545
+ memset(&mpp, 0, sizeof(mpp));
546
+ if (image)
547
+ {
548
+ mpp.depth = image->depth;
549
+ mpp.matte = image->matte;
550
+ mpp.colorspace = image->colorspace;
551
+ }
552
+ else
553
+ {
554
+ mpp.depth = QuantumDepth;
555
+ mpp.matte = MagickFalse;
556
+ mpp.colorspace = RGBColorspace;
557
+ }
558
+ mpp.red = (MagickRealType) pixelpacket->red;
559
+ mpp.green = (MagickRealType) pixelpacket->green;
560
+ mpp.blue = (MagickRealType) pixelpacket->blue;
561
+ mpp.opacity = (MagickRealType) pixelpacket->opacity;
562
+ mpp.index = 0.0;
563
+ (void) GetColorTuple(&mpp, MagickTrue, name);
564
+ return rb_str_new2(name);
565
+ }
566
+
567
+
568
+
569
+
570
+
571
+ /*
572
+ * Similar but not identical to FormatMagickSize
573
+ */
574
+ extern char *mwr_format_size(const MagickSizeType size, char *buff)
575
+ {
576
+ double d;
577
+
578
+ if (size >= 1073741824)
579
+ {
580
+ d = size / 1073741824.0;
581
+ sprintf(buff, "%ggb", d);
582
+ }
583
+ else if (size >= 1048576)
584
+ {
585
+ d = size / 1048576.0;
586
+ sprintf(buff, "%gmb", d);
587
+ }
588
+ else if (size >= 1024)
589
+ {
590
+ d = size / 1024.0;
591
+ sprintf(buff, "%gkb", d);
592
+ }
593
+ else
594
+ {
595
+ sprintf(buff, "%g", (double)size);
596
+ }
597
+
598
+ return buff;
599
+ }
600
+
601
+
602
+
603
+
604
+ /*
605
+ * Calls the set_<option> private method.
606
+ */
607
+ static VALUE call_option_setter(VALUE args)
608
+ {
609
+ volatile VALUE option, value, obj;
610
+ char setter[100];
611
+
612
+ option = rb_ary_entry(args, 0);
613
+ value = rb_ary_entry(args, 1);
614
+ obj = rb_ary_entry(args, 2);
615
+
616
+ (void) sprintf(setter, "set_%.90s", rb_id2name(SYM2ID(option)));
617
+
618
+ return rb_funcall(obj, rb_intern(setter), 1, value);
619
+ }
620
+
621
+
622
+
623
+
624
+ /*
625
+ * Called if an exception was raised by call_option_setter (above).
626
+ */
627
+ static VALUE rescue_option(VALUE args, VALUE errinfo)
628
+ {
629
+ volatile VALUE option;
630
+ volatile VALUE err_class;
631
+ volatile VALUE msg;
632
+
633
+ option = rb_ary_entry(args, 0);
634
+ err_class = CLASS_OF(errinfo);
635
+ if (err_class == rb_eNoMethodError)
636
+ {
637
+ /* Do not diagnose undefined options. */
638
+ #if 0
639
+ rb_raise(rb_eArgError, "undefined option :%s", rb_id2name(SYM2ID(option)));
640
+ #else
641
+ return Qnil;
642
+ #endif
643
+ }
644
+
645
+ msg = rb_funcall(errinfo, rb_intern("message"), 0, 0);
646
+ rb_raise(err_class, "%s", StringValuePtr(msg));
647
+ return Qnil; // dummy
648
+ }
649
+
650
+
651
+
652
+
653
+ /*
654
+ * Called with each key, value pair in the options hash.
655
+ * The key is the option to be set. The value is the option value.
656
+ * If the option setter needs > 1 argument, the value s/b an array.
657
+ * begin
658
+ * __send__(set_option, value)
659
+ * rescue NoMethodError
660
+ * raise(ArgumentError, "undefined option :#{option}")
661
+ * end
662
+ */
663
+ static int begin_option(VALUE option, VALUE value, VALUE obj)
664
+ {
665
+ VALUE args;
666
+
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
+ return 0;
673
+ }
674
+
675
+
676
+
677
+
678
+ /*
679
+ * Iterate over the options hash.
680
+ */
681
+ void mwr_process_options(VALUE obj, VALUE options)
682
+ {
683
+ if (options != Qnil)
684
+ {
685
+ rb_hash_foreach(options, begin_option, obj);
686
+ }
687
+ }
688
+
689
+
690
+
691
+
692
+ /*
693
+ * issue warning or raise appropriate exception
694
+ */
695
+ static void raise_wand_error(ExceptionType severity, char *exception)
696
+ {
697
+ if (severity < ErrorException)
698
+ {
699
+ rb_warning("MagickWand: %s", exception);
700
+ }
701
+ else if (severity < FatalErrorException)
702
+ {
703
+
704
+ rb_raise(mwr_eImageMagickError, "%s", exception);
705
+ }
706
+ else
707
+ {
708
+ rb_raise(mwr_eFatalImageMagickError, "%s", exception);
709
+ }
710
+ }
711
+
712
+
713
+
714
+
715
+ /*
716
+ * The exception strings are allocated out of Ruby managed memory and will
717
+ * be GC'd normally.
718
+ */
719
+ void mwr_check_magickwand_error(MagickWand *magickwand)
720
+ {
721
+ ExceptionType severity;
722
+ char *exception;
723
+
724
+ severity = MagickGetExceptionType(magickwand);
725
+
726
+ if (severity > UndefinedException)
727
+ {
728
+ exception = MagickGetException(magickwand, &severity);
729
+ MagickClearException(magickwand);
730
+ raise_wand_error(severity, exception);
731
+ }
732
+ }
733
+
734
+
735
+
736
+
737
+ void mwr_check_pixelwand_error(PixelWand *pixelwand)
738
+ {
739
+ ExceptionType severity;
740
+ char *exception;
741
+
742
+ severity = PixelGetExceptionType(pixelwand);
743
+
744
+ if (severity > UndefinedException)
745
+ {
746
+ exception = PixelGetException(pixelwand, &severity);
747
+ PixelClearException(pixelwand);
748
+ raise_wand_error(severity, exception);
749
+ }
750
+ }
751
+
752
+
753
+
754
+
755
+ void mwr_check_drawingwand_error(DrawingWand *drawingwand)
756
+ {
757
+ ExceptionType severity;
758
+ char *exception;
759
+
760
+ severity = DrawGetExceptionType(drawingwand);
761
+
762
+ if (severity > UndefinedException)
763
+ {
764
+ exception = DrawGetException(drawingwand, &severity);
765
+ DrawClearException(drawingwand);
766
+ raise_wand_error(severity, exception);
767
+ }
768
+ }
769
+
770
+
771
+
772
+
773
+ void mwr_check_error(ExceptionInfo *exception)
774
+ {
775
+ char buffer[2010];
776
+
777
+ if (exception->severity > UndefinedException)
778
+ {
779
+ buffer[0] = '\0';
780
+ if (exception->reason)
781
+ {
782
+ strncpy(buffer, GetLocaleExceptionMessage(exception->severity, exception->reason), 1000);
783
+ }
784
+ if (exception->description)
785
+ {
786
+ sprintf(buffer+strlen(buffer), " (%.1000s)", GetLocaleExceptionMessage(exception->severity, exception->description));
787
+ }
788
+
789
+ if (exception->severity < ErrorException)
790
+ {
791
+ rb_warning("MagickWand: %s", buffer);
792
+ }
793
+ else if (exception->severity < FatalErrorException)
794
+ {
795
+
796
+ rb_raise(mwr_eImageMagickError, "%s", buffer);
797
+ }
798
+ else
799
+ {
800
+ rb_raise(mwr_eFatalImageMagickError, "%s", buffer);
801
+ }
802
+ }
803
+ }
804
+
805
+
806
+
807
+
808
+ void mwr_init_ImageMagickError(void)
809
+ {
810
+ mwr_eImageMagickError = rb_define_class_under(mwr_mMagickWand, "ImageMagickError", rb_eStandardError);
811
+ }
812
+
813
+
814
+
815
+
816
+ void mwr_init_FatalImageMagickError(void)
817
+ {
818
+ mwr_eFatalImageMagickError = rb_define_class_under(mwr_mMagickWand, "FatalImageMagickError", rb_eStandardError);
819
+ }