1 /*
2 % Copyright (C) 2003 - 2018 GraphicsMagick Group
3 % Copyright (C) 2002 ImageMagick Studio
4 % Copyright (C) 1991-1999 E. I. du Pont de Nemours and Company
5 %
6 % This program is covered by multiple licenses, which are described in
7 % Copyright.txt. You should have received a copy of Copyright.txt with this
8 % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9 %
10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11 % %
12 % %
13 % PPPP EEEEE RRRR L %
14 % P P E R R L %
15 % PPPP EEE RRRR L %
16 % P E R R L %
17 % P EEEEE R R LLLLL %
18 % %
19 % M M AAA GGGG IIIII CCCC K K %
20 % MM MM A A G I C K K %
21 % M M M AAAAA G GGG I C KKK %
22 % M M A A G G I C K K %
23 % M M A A GGGG IIIII CCCC K K %
24 % %
25 % %
26 % Object-oriented Perl interface to GraphicsMagick %
27 % %
28 % %
29 % Software Design %
30 % Kyle Shorter %
31 % John Cristy %
32 % February 1997 %
33 % %
34 % %
35 % %
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 %
38 % PerlMagick is an objected-oriented Perl interface to GraphicsMagick. Use
39 % the module to read, manipulate, or write an image or image sequence from
40 % within a Perl script. This makes PerlMagick suitable for Web CGI scripts.
41 %
42 */
43
44 /*
45 Include declarations.
46 */
47 #define MAGICK_IMPLEMENTATION 1
48 #if !defined(WIN32)
49 #define MagickExport
50 #endif
51
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55 #define PERL_NO_GET_CONTEXT /* faster */
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #define MAGICK_IMPLEMENTATION 1
61 #include <magick/api.h>
62 #include <magick/locale_c.h>
63 #undef tainted
64 #if !defined(WIN32)
65 #include <setjmp.h>
66 #else
67 #undef setjmp
68 #undef longjmp
69 #include <setjmpex.h>
70 #endif
71
72 #ifdef __cplusplus
73 }
74 #endif
75
76 /*
77 Define declarations.
78 */
79 #define ArrayReference (char **) 4
80 #ifndef aTHX_
81 #define aTHX_
82 #define pTHX_
83 #define dTHX
84 #endif
85 #define DegreesToRadians(x) ((x)*3.14159265358979323846/180.0)
86 #define DoubleReference (char **) 2
87 #define EndOf(array) (&array[NumberOf(array)])
88 #define False 0
89 #define NullReference (char **) 0
90 #define ImageReference (char **) 3
91 #define IntegerReference (char **) 1
92 #define MaxArguments 28
93 #define MY_CXT_KEY PackageName "::ContextKey_" XS_VERSION
94 #ifndef START_MY_CXT
95 #define MY_CXT_INIT
96 #define MY_CXT my_cxt
97 #define dMY_CXT
98 #endif
99 #ifndef na
100 #define na PL_na
101 #endif
102 #define NumberOf(array) (sizeof(array)/sizeof(*array))
103 #define PackageName "Graphics::Magick"
104 #ifndef PerlIO_findFILE
105 #define PerlIO_findFILE(f) (FILE *) (f)
106 #endif
107 #define StringReference (char **) 0
108 #ifndef sv_undef
109 #define sv_undef PL_sv_undef
110 #endif
111 #define True 1
112
113 /*
114 Typedef and structure declarations.
115 */
116 typedef struct _Arguments
117 {
118 char
119 *method,
120 **type;
121 } Arguments;
122
123 struct ArgumentList
124 {
125 long
126 int_reference;
127
128 double
129 double_reference;
130
131 char
132 *string_reference;
133
134 Image
135 *image_reference;
136
137 SV
138 *array_reference;
139
140 size_t
141 length;
142 };
143
144 typedef struct _my_cxt_t
145 {
146 jmp_buf
147 *error_jump; /* long jump return for FATAL errors */
148
149 SV
150 *error_list; /* Perl variable for storing messages */
151 } my_cxt_t;
152
153 struct PackageInfo
154 {
155 ImageInfo
156 *image_info;
157
158 DrawInfo
159 *draw_info;
160
161 QuantizeInfo
162 *quantize_info;
163 };
164
165 typedef void
166 *Graphics__Magick; /* data type for the Graphics::Magick package */
167
168 /*
169 Static declarations. The strings in this list must be expressed
170 in the exact same order as the equivalent enumeration.
171 */
172 static char
173 *AlignTypes[] =
174 {
175 "Undefined", "Left", "Center", "Right", (char *) NULL
176 },
177 *BooleanTypes[] =
178 {
179 "False", "True", (char *) NULL
180 },
181 *ChannelTypes[] =
182 {
183 "Undefined", "Red", "Cyan", "Green", "Magenta", "Blue", "Yellow",
184 "Opacity", "Black", "Matte", "All", "Gray", (char *) NULL
185 },
186 *ClassTypes[] =
187 {
188 "Undefined", "DirectClass", "PseudoClass", (char *) NULL
189 },
190 *ColorspaceTypes[] =
191 {
192 "Undefined", "RGB", "Gray", "Transparent", "OHTA", "XYZ", "YCC",
193 "YIQ", "YPbPr", "YUV", "CMYK", "sRGB", "HSL", "HWB", "LAB", "CineonLog",
194 "Rec601Luma", "Rec601YCbCr", "Rec709Luma", "Rec709YCbCr", (char *) NULL
195 },
196 *CompositeTypes[] =
197 {
198 "Undefined", "Over", "In", "Out", "Atop", "Xor", "Plus", "Minus",
199 "Add", "Subtract", "Difference", "Multiply", "Bumpmap", "Copy",
200 "CopyRed", "CopyGreen", "CopyBlue", "CopyOpacity", "Clear", "Dissolve",
201 "Displace", "Modulate", "Threshold", "No", "Darken", "Lighten",
202 "Hue", "Saturate", "Colorize", "Luminize", "Screen", "Overlay",
203 "CopyCyan", "CopyMagenta", "CopyYellow", "CopyBlack", "Divide",
204 "HardLight", "Exclusion", "ColorDodge", "ColorBurn", "SoftLight",
205 "LinearBurn", "LinearDodge", "LinearLight", "VividLight", "PinLight",
206 "HardMix",
207 (char *) NULL
208 },
209 *CompressionTypes[] =
210 {
211 "Undefined", "None", "BZip", "Fax", "Group4", "JPEG", "LosslessJPEG",
212 "LZW", "RLE", "Zip", "LZMA", "JPEG2000", "JBIG1", "JBIG2", "ZSTD",
213 "WebP",
214 (char *) NULL
215 },
216 *DecorationTypes[] =
217 {
218 "None", "Underline", "Overline", "LineThrough",
219 (char *) NULL
220 },
221 *DisposeTypes[] =
222 {
223 "Undefined", "None", "Background", "Previous", (char *) NULL
224 },
225 *EndianTypes[] =
226 {
227 "Undefined", "LSB", "MSB", "Native", (char *) NULL
228 },
229 *FilterTypess[] =
230 {
231 "Undefined", "Point", "Box", "Triangle", "Hermite", "Hanning",
232 "Hamming", "Blackman", "Gaussian", "Quadratic", "Cubic", "Catrom",
233 "Mitchell", "Lanczos", "Bessel", "Sinc", (char *) NULL
234 },
235 *GravityTypes[] =
236 {
237 "Forget", "NorthWest", "North", "NorthEast", "West", "Center",
238 "East", "SouthWest", "South", "SouthEast", "Static", (char *) NULL
239 },
240 *ImageTypes[] =
241 {
242 "Undefined", "Bilevel", "Grayscale", "GrayscaleMatte", "Palette",
243 "PaletteMatte", "TrueColor", "TrueColorMatte", "ColorSeparation",
244 "ColorSeparationMatte", "Optimize", (char *) NULL
245 },
246 *IntentTypes[] =
247 {
248 "Undefined", "Saturation", "Perceptual", "Absolute", "Relative",
249 (char *) NULL
250 },
251 *InterlaceTypes[] =
252 {
253 "Undefined", "None", "Line", "Plane", "Partition", (char *) NULL
254 },
255 *LogEventTypes[] =
256 {
257 "No", "Configure", "Annotate", "Render", "Transform", "Locale",
258 "Coder", "X11", "Cache", "Blob", "Deprecate", "User", "Resource",
259 "TemporaryFile", "Exception", "All", (char *) NULL
260 },
261 *MethodTypes[] =
262 {
263 "Point", "Replace", "Floodfill", "FillToBorder", "Reset", (char *) NULL
264 },
265 *ModeTypes[] =
266 {
267 "Undefined", "Frame", "Unframe", "Concatenate", (char *) NULL
268 },
269 *NoiseTypes[] =
270 {
271 "Uniform", "Gaussian", "Multiplicative", "Impulse", "Laplacian",
272 "Poisson", "Random", (char *) NULL
273 },
274 *PreviewTypes[] =
275 {
276 "Undefined", "Rotate", "Shear", "Roll", "Hue", "Saturation",
277 "Brightness", "Gamma", "Spiff", "Dull", "Grayscale", "Quantize",
278 "Despeckle", "ReduceNoise", "AddNoise", "Sharpen", "Blur",
279 "Threshold", "EdgeDetect", "Spread", "Solarize", "Shade", "Raise",
280 "Segment", "Swirl", "Implode", "Wave", "OilPaint", "Charcoal",
281 "JPEG", (char *) NULL
282 },
283 *PrimitiveTypes[] =
284 {
285 "Undefined", "point", "line", "rectangle", "roundRectangle", "arc",
286 "ellipse", "circle", "polyline", "polygon", "bezier", "path", "color",
287 "matte", "text", "image", (char *) NULL
288 },
289 *ResolutionTypes[] =
290 {
291 "Undefined", "PixelsPerInch", "PixelsPerCentimeter", (char *) NULL
292 },
293 *StretchTypes[] =
294 {
295 "Normal", "UltraCondensed", "ExtraCondensed", "Condensed",
296 "SemiCondensed", "SemiExpanded", "Expanded", "ExtraExpanded",
297 "UltraExpanded", "Any", (char *) NULL
298 },
299 *StyleTypes[] =
300 {
301 "Normal", "Italic", "Oblique", "Any", (char *) NULL
302 },
303 *VirtualPixelMethods[] =
304 {
305 "Undefined", "", "Constant", "Edge", "Mirror", "Tile",
306 (char *) NULL
307 };
308
309 static struct
310 Methods
311 {
312 char
313 *name;
314
315 Arguments
316 arguments[MaxArguments];
317 } Methods[] =
318 {
319 { "comment", { {"comment", StringReference} } },
320 { "label", { {"label", StringReference} } },
321 { "AddNoise", { {"noise", NoiseTypes} } },
322 { "Colorize", { {"fill", StringReference}, {"opacity", StringReference} } },
323 { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
324 {"height", IntegerReference}, {"fill", StringReference},
325 {"color", StringReference} } },
326 { "Blur", { {"geometry", StringReference}, {"radius", DoubleReference},
327 {"sigma", DoubleReference} } },
328 { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
329 {"height", IntegerReference}, {"x", IntegerReference},
330 {"y", IntegerReference} } },
331 { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
332 {"height", IntegerReference}, {"x", IntegerReference},
333 {"y", IntegerReference} } },
334 { "Despeckle", { { NULL, NullReference } } },
335 { "Edge", { {"radius", DoubleReference} } },
336 { "Emboss", { {"geometry", StringReference}, {"radius", DoubleReference},
337 {"sigma", DoubleReference} } },
338 { "Enhance", { { NULL, NullReference } } },
339 { "Flip", { { NULL, NullReference } } },
340 { "Flop", { { NULL, NullReference } } },
341 { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
342 {"height", IntegerReference}, {"inner", IntegerReference},
343 {"outer", IntegerReference}, {"fill", StringReference},
344 {"color", StringReference} } },
345 { "Implode", { {"amount", DoubleReference} } },
346 { "Magnify", { { NULL, NullReference } } },
347 { "MedianFilter", { {"radius", DoubleReference} } },
348 { "Minify", { { NULL, NullReference } } },
349 { "OilPaint", { {"radius", DoubleReference} } },
350 { "ReduceNoise", { {"radius", DoubleReference} } },
351 { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
352 {"y", IntegerReference} } },
353 { "Rotate", { {"degrees", DoubleReference},
354 {"color", StringReference} } },
355 { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
356 {"height", IntegerReference} } },
357 { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
358 {"height", IntegerReference} } },
359 { "Shade", { {"geometry", StringReference}, {"azimuth", DoubleReference},
360 {"elevation", DoubleReference}, {"gray", BooleanTypes} } },
361 { "Sharpen", { {"geometry", StringReference}, {"radius", DoubleReference},
362 {"sigma", DoubleReference} } },
363 { "Shear", { {"geometry", StringReference}, {"x", IntegerReference},
364 {"y", DoubleReference}, {"color", StringReference} } },
365 { "Spread", { {"radius", IntegerReference} } },
366 { "Swirl", { {"degrees", DoubleReference} } },
367 { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
368 {"height", IntegerReference}, {"filter", FilterTypess},
369 {"blur", DoubleReference } } },
370 { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
371 {"height", IntegerReference}, {"filter", FilterTypess},
372 {"blur", DoubleReference } } },
373 { "Annotate", { {"text", StringReference}, {"font", StringReference},
374 {"point", DoubleReference}, {"density", StringReference},
375 {"undercolor", StringReference}, {"stroke", StringReference},
376 {"fill", StringReference}, {"geometry", StringReference},
377 {"sans", StringReference}, {"x", IntegerReference},
378 {"y", IntegerReference}, {"gravity", GravityTypes},
379 {"translate", StringReference}, {"scale", StringReference},
380 {"rotate", DoubleReference}, {"skewX", DoubleReference},
381 {"skewY", DoubleReference}, {"strokewidth", IntegerReference},
382 {"antialias", BooleanTypes}, {"family", StringReference},
383 {"style", StyleTypes}, {"stretch", StretchTypes},
384 {"weight", IntegerReference}, {"align", AlignTypes},
385 {"encoding", StringReference}, {"affine", ArrayReference},
386 {"decorate", DecorationTypes}} },
387 { "ColorFloodfill", { {"geometry", StringReference},
388 {"x", IntegerReference}, {"y", IntegerReference},
389 {"fill", StringReference}, {"bordercolor", StringReference},
390 {"fuzz", DoubleReference} } },
391 { "Composite", { {"image", ImageReference}, {"compose", CompositeTypes},
392 {"geometry", StringReference}, {"x", IntegerReference},
393 {"y", IntegerReference}, {"gravity", GravityTypes},
394 {"opacity", DoubleReference}, {"tile", BooleanTypes},
395 {"rotate", DoubleReference}, {"color", StringReference},
396 {"mask", ImageReference} } },
397 { "Contrast", { {"sharp", BooleanTypes} } },
398 { "CycleColormap", { {"display", IntegerReference} } },
399 { "Draw", { {"primitive", PrimitiveTypes}, {"points", StringReference},
400 {"method", MethodTypes}, {"stroke", StringReference},
401 {"fill", StringReference}, {"strokewidth", DoubleReference},
402 {"font", StringReference}, {"bordercolor", StringReference},
403 {"x", DoubleReference}, {"y", DoubleReference},
404 {"translate", StringReference}, {"scale", StringReference},
405 {"rotate", DoubleReference}, {"skewX", DoubleReference},
406 {"skewY", DoubleReference}, {"tile", ImageReference},
407 {"pointsize", DoubleReference}, {"antialias", BooleanTypes},
408 {"density", StringReference}, {"linewidth", DoubleReference},
409 {"affine", ArrayReference} } },
410 { "Equalize", { { NULL, NullReference } } },
411 { "Gamma", { {"gamma", StringReference}, {"red", DoubleReference},
412 {"green", DoubleReference}, {"blue", DoubleReference} } },
413 { "Map", { {"image", ImageReference}, {"dither", BooleanTypes} } },
414 { "MatteFloodfill", { {"geometry", StringReference},
415 {"x", IntegerReference}, {"y", IntegerReference},
416 {"opacity", IntegerReference}, {"bordercolor", StringReference},
417 {"fuzz", DoubleReference} } },
418 { "Modulate", { {"factor", StringReference}, {"bright", DoubleReference},
419 {"saturation", DoubleReference}, {"hue", DoubleReference} } },
420 { "Negate", { {"gray", BooleanTypes} } },
421 { "Normalize", { { NULL, NullReference } } },
422 { "NumberColors", { { NULL, NullReference } } },
423 { "Opaque", { {"color", StringReference}, {"fill", StringReference},
424 {"fuzz", DoubleReference} } },
425 { "Quantize", { {"colors", IntegerReference}, {"tree", IntegerReference},
426 {"colorspace", ColorspaceTypes}, {"dither", BooleanTypes},
427 {"measure", BooleanTypes}, {"global", BooleanTypes} } },
428 { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
429 {"height", IntegerReference}, {"raise", BooleanTypes} } },
430 { "Segment", { {"geometry", StringReference}, {"cluster", DoubleReference},
431 {"smooth", DoubleReference}, {"colorspace", ColorspaceTypes},
432 {"verbose", BooleanTypes} } },
433 { "Signature", { { NULL, NullReference } } },
434 { "Solarize", { {"threshold", DoubleReference} } },
435 { "Sync", { { NULL, NullReference } } },
436 { "Texture", { {"texture", ImageReference} } },
437 { "Sans", { {"geometry", StringReference}, {"crop", StringReference},
438 {"filter", FilterTypess} } },
439 { "Transparent", { {"color", StringReference},
440 {"opacity", IntegerReference}, {"fuzz", DoubleReference} } },
441 { "Threshold", { {"threshold", StringReference} } },
442 { "Charcoal", { {"geometry", StringReference}, {"radius", DoubleReference},
443 {"sigma", DoubleReference} } },
444 { "Trim", { {"fuzz", DoubleReference} } },
445 { "Wave", { {"geometry", StringReference}, {"amplitude", DoubleReference},
446 {"wavelength", DoubleReference} } },
447 { "Channel", { {"channel", ChannelTypes} } },
448 { "Condense", { { NULL, NullReference } } },
449 { "Stereo", { {"image", ImageReference} } },
450 { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
451 { "Deconstruct", { { NULL, NullReference } } },
452 { "GaussianBlur", { {"geometry", StringReference},
453 {"radius", DoubleReference}, {"sigma", DoubleReference} } },
454 { "Convolve", { {"coefficients", ArrayReference} } },
455 { "Profile", { {"name", StringReference}, {"profile", StringReference} } },
456 { "UnsharpMask", { {"geometry", StringReference},
457 {"radius", DoubleReference}, {"sigma", DoubleReference},
458 {"amount", DoubleReference}, {"threshold", DoubleReference} } },
459 { "MotionBlur", { {"geometry", StringReference},
460 {"radius", DoubleReference}, {"sigma", DoubleReference},
461 {"angle", DoubleReference} } },
462 { "OrderedDither", { { NULL, NullReference } } },
463 { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
464 {"height", IntegerReference} } },
465 { "Level", { {"level", StringReference}, {"black-point", DoubleReference},
466 {"mid-point", DoubleReference}, {"white-point", DoubleReference} } },
467 { "Clip", { { NULL, NullReference } } },
468 { "AffineTransform", { {"affine", ArrayReference},
469 {"translate", StringReference}, {"scale", StringReference},
470 {"rotate", DoubleReference}, {"skewX", DoubleReference},
471 {"skewY", DoubleReference} } },
472 { "Compare", { {"image", ImageReference} } },
473 { "AdaptiveThreshold", { {"geometry", StringReference},
474 {"width", IntegerReference}, {"height", IntegerReference},
475 {"offset", IntegerReference} } },
476 };
477
478 #ifdef START_MY_CXT
479 START_MY_CXT
480 #else
481 static my_cxt_t
482 my_cxt = { (jmp_buf *) NULL, (SV *) NULL };
483 #endif
484
485 /*
486 Forward declarations.
487 */
488 static Image
489 *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***);
490
491 static int
492 strEQcase(const char *,const char *);
493
494 /*
495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
496 % %
497 % %
498 % %
499 % C l o n e P a c k a g e I n f o %
500 % %
501 % %
502 % %
503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504 %
505 % Method ClonePackageInfo makes a duplicate of the given info, or if info is
506 % NULL, a new one.
507 %
508 % The format of the ClonePackageInfo routine is:
509 %
510 % struct PackageInfo *ClonePackageInfo(struct PackageInfo *info)
511 %
512 % A description of each parameter follows:
513 %
514 % o clone_info: Method ClonePackageInfo returns a duplicate of the given
515 % info, or if info is NULL, a new one.
516 %
517 % o info: a structure of type info.
518 %
519 %
520 */
ClonePackageInfo(struct PackageInfo * info)521 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info)
522 {
523 struct PackageInfo
524 *clone_info;
525
526 clone_info=MagickAllocateMemory(struct PackageInfo *,sizeof(struct PackageInfo));
527 if (!info)
528 {
529 clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
530 clone_info->draw_info=
531 CloneDrawInfo(clone_info->image_info,(DrawInfo *) NULL);
532 clone_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
533 return(clone_info);
534 }
535 *clone_info=(*info);
536 clone_info->image_info=CloneImageInfo(info->image_info);
537 clone_info->draw_info=CloneDrawInfo(info->image_info,info->draw_info);
538 clone_info->quantize_info=CloneQuantizeInfo(info->quantize_info);
539 return(clone_info);
540 }
541
542 /*
543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544 % %
545 % %
546 % %
547 % c o n s t a n t %
548 % %
549 % %
550 % %
551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
552 %
553 % Method constant returns a double value for the specified name.
554 %
555 % The format of the constant routine is:
556 %
557 % double constant(char *name,int sans)
558 %
559 % A description of each parameter follows:
560 %
561 % o value: Method constant returns a double value for the specified name.
562 %
563 % o name: The name of the constant.
564 %
565 % o sans: This integer value is not used.
566 %
567 %
568 */
constant(char * name,int sans)569 static double constant(char *name,int sans)
570 {
571 (void) sans;
572
573 errno=0;
574 switch (*name)
575 {
576 case 'B':
577 {
578 if (strEQ(name,"BlobError"))
579 return(BlobError);
580 if (strEQ(name,"BlobWarning"))
581 return(BlobWarning);
582 break;
583 }
584 case 'C':
585 {
586 if (strEQ(name,"CacheError"))
587 return(CacheError);
588 if (strEQ(name,"CacheWarning"))
589 return(CacheWarning);
590 if (strEQ(name,"CoderError"))
591 return(CoderError);
592 if (strEQ(name,"CoderWarning"))
593 return(CoderWarning);
594 if (strEQ(name,"ConfigureError"))
595 return(ConfigureError);
596 if (strEQ(name,"ConfigureWarning"))
597 return(ConfigureWarning);
598 if (strEQ(name,"CorruptImageError"))
599 return(CorruptImageError);
600 if (strEQ(name,"CorruptImageWarning"))
601 return(CorruptImageWarning);
602 break;
603 }
604 case 'D':
605 {
606 if (strEQ(name,"DelegateError"))
607 return(DelegateError);
608 if (strEQ(name,"DelegateWarning"))
609 return(DelegateWarning);
610 if (strEQ(name,"DrawError"))
611 return(DrawError);
612 if (strEQ(name,"DrawWarning"))
613 return(DrawWarning);
614 break;
615 }
616 case 'E':
617 {
618 if (strEQ(name,"ErrorException"))
619 return(ErrorException);
620 break;
621 }
622 case 'F':
623 {
624 if (strEQ(name,"FatalErrorException"))
625 return(FatalErrorException);
626 if (strEQ(name,"FileOpenError"))
627 return(FileOpenError);
628 if (strEQ(name,"FileOpenWarning"))
629 return(FileOpenWarning);
630 break;
631 }
632 case 'I':
633 {
634 if (strEQ(name,"ImageError"))
635 return(ImageError);
636 if (strEQ(name,"ImageWarning"))
637 return(ImageWarning);
638 break;
639 }
640 case 'M':
641 {
642 if (strEQ(name,"MaxRGB"))
643 return(MaxRGB);
644 if (strEQ(name,"MissingDelegateError"))
645 return(MissingDelegateError);
646 if (strEQ(name,"MissingDelegateWarning"))
647 return(MissingDelegateWarning);
648 if (strEQ(name,"ModuleError"))
649 return(ModuleError);
650 if (strEQ(name,"ModuleWarning"))
651 return(ModuleWarning);
652 break;
653 }
654 case 'O':
655 {
656 if (strEQ(name,"Opaque"))
657 return(OpaqueOpacity);
658 if (strEQ(name,"OptionError"))
659 return(OptionError);
660 if (strEQ(name,"OptionWarning"))
661 return(OptionWarning);
662 break;
663 }
664 case 'R':
665 {
666 if (strEQ(name,"ResourceLimitError"))
667 return(ResourceLimitError);
668 if (strEQ(name,"ResourceLimitWarning"))
669 return(ResourceLimitWarning);
670 if (strEQ(name,"RegistryError"))
671 return(RegistryError);
672 if (strEQ(name,"RegistryWarning"))
673 return(RegistryWarning);
674 break;
675 }
676 case 'S':
677 {
678 if (strEQ(name,"StreamError"))
679 return(StreamError);
680 if (strEQ(name,"StreamWarning"))
681 return(StreamWarning);
682 if (strEQ(name,"Success"))
683 return(0);
684 break;
685 }
686 case 'T':
687 {
688 if (strEQ(name,"Transparent"))
689 return(TransparentOpacity);
690 if (strEQ(name,"TypeError"))
691 return(TypeError);
692 if (strEQ(name,"TypeWarning"))
693 return(TypeWarning);
694 break;
695 }
696 case 'W':
697 {
698 if (strEQ(name,"WarningException"))
699 return(WarningException);
700 break;
701 }
702 case 'X':
703 {
704 if (strEQ(name,"XServerError"))
705 return(XServerError);
706 if (strEQ(name,"XServerWarning"))
707 return(XServerWarning);
708 break;
709 }
710 }
711 errno=EINVAL;
712 return(0);
713 }
714
715 /*
716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717 % %
718 % %
719 % %
720 % D e s t r o y P a c k a g e I n f o %
721 % %
722 % %
723 % %
724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
725 %
726 % Method DestroyPackageInfo frees a previously created info structure.
727 %
728 % The format of the DestroyPackageInfo routine is:
729 %
730 % DestroyPackageInfo(struct PackageInfo *info)
731 %
732 % A description of each parameter follows:
733 %
734 % o info: a structure of type info.
735 %
736 %
737 */
DestroyPackageInfo(struct PackageInfo * info)738 static void DestroyPackageInfo(struct PackageInfo *info)
739 {
740 DestroyImageInfo(info->image_info);
741 DestroyDrawInfo(info->draw_info);
742 DestroyQuantizeInfo(info->quantize_info);
743 MagickFreeMemory(info);
744 }
745
746 /*
747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748 % %
749 % %
750 % %
751 % G e t L i s t %
752 % %
753 % %
754 % %
755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
756 %
757 % Method GetList is recursively called by SetupList to traverse the
758 % Graphics__Magick reference. If building an reference_vector (see SetupList),
759 % *current is the current position in *reference_vector and *last is the final
760 % entry in *reference_vector.
761 %
762 % The format of the GetList routine is:
763 %
764 % GetList(info)
765 %
766 % A description of each parameter follows:
767 %
768 % o info: a structure of type info.
769 %
770 %
771 */
GetList(pTHX_ SV * reference,SV *** reference_vector,int * current,int * last)772 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,int *current,
773 int *last)
774 {
775 Image
776 *image;
777
778 if (!reference)
779 return(NULL);
780 switch (SvTYPE(reference))
781 {
782 case SVt_PVAV:
783 {
784 AV
785 *av;
786
787 Image
788 *head,
789 *previous;
790
791 int
792 n;
793
794 register int
795 i;
796
797 /*
798 Array of images.
799 */
800 previous=(Image *) NULL;
801 head=(Image *) NULL;
802 av=(AV *) reference;
803 n=av_len(av);
804 for (i=0; i <= n; i++)
805 {
806 SV
807 **rv;
808
809 rv=av_fetch(av,i,0);
810 if (rv && *rv && sv_isobject(*rv))
811 {
812 image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last);
813 if (!image)
814 continue;
815 if (image == previous)
816 {
817 ExceptionInfo
818 exception;
819
820 GetExceptionInfo(&exception);
821 image=CloneImage(image,0,0,True,&exception);
822 if (exception.severity != UndefinedException)
823 CatchException(&exception);
824 DestroyExceptionInfo(&exception);
825 if (image == (Image *) NULL)
826 return(NULL);
827 }
828 image->previous=previous;
829 *(previous ? &previous->next : &head)=image;
830 for (previous=image; previous->next; previous=previous->next);
831 }
832 }
833 return(head);
834 }
835 case SVt_PVMG:
836 {
837 /*
838 Blessed scalar, one image.
839 */
840 image=(Image *) (magick_uintptr_t)SvIV(reference);
841 if (!image)
842 return(NULL);
843 image->previous=(Image *) NULL;
844 image->next=(Image *) NULL;
845 if (reference_vector)
846 {
847 if (*current == *last)
848 {
849 *last+=256;
850 if (*reference_vector)
851 {
852 MagickReallocMemory(SV **,*reference_vector,*last*sizeof(*reference_vector));
853 }
854 else
855 {
856 *reference_vector=
857 MagickAllocateMemory(SV **,*last*sizeof(*reference_vector));
858 }
859 }
860 if (*reference_vector)
861 {
862 (*reference_vector)[*current]=reference;
863 (*reference_vector)[++(*current)]=NULL;
864 }
865 }
866 return(image);
867 }
868 }
869 (void) fprintf(stderr,"GetList: UnrecognizedType %ld\n",
870 (long) SvTYPE(reference));
871 return((Image *) NULL);
872 }
873
874 /*
875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
876 % %
877 % %
878 % %
879 % G e t P a c k a g e I n f o %
880 % %
881 % %
882 % %
883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
884 %
885 % Method GetPackageInfo looks up or creates an info structure for the given
886 % Graphics__Magick reference. If it does create a new one, the information in
887 % package_info is used to initialize it.
888 %
889 % The format of the GetPackageInfo routine is:
890 %
891 % struct PackageInfo *GetPackageInfo(void *reference,
892 % struct PackageInfo *package_info)
893 %
894 % A description of each parameter follows:
895 %
896 % o info: a structure of type info.
897 %
898 %
899 */
GetPackageInfo(pTHX_ void * reference,struct PackageInfo * package_info)900 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
901 struct PackageInfo *package_info)
902 {
903 char
904 message[MaxTextExtent];
905
906 struct PackageInfo
907 *clone_info;
908
909 SV
910 *sv;
911
912 FormatString(message,"%s::Ref%lx_%s",PackageName,(long) reference,
913 XS_VERSION);
914 sv=perl_get_sv(message,(TRUE | 0x02));
915 if (!sv)
916 {
917 MagickError(ResourceLimitError,UnableToGetPackageInfo,message);
918 return(package_info);
919 }
920 if (SvREFCNT(sv) == 0)
921 (void) SvREFCNT_inc(sv);
922 if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) (magick_uintptr_t)SvIV(sv)))
923 return(clone_info);
924 clone_info=ClonePackageInfo(package_info);
925 sv_setiv(sv,(IV) (magick_uintptr_t)clone_info);
926 return(clone_info);
927 }
928
929 /*
930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
931 % %
932 % %
933 % %
934 % L o o k u p S t r %
935 % %
936 % %
937 % %
938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
939 %
940 % Method LookupStr searches through a list of strings matching it to string
941 % and return its index in the list, or -1 for not found .
942 %
943 % The format of the LookupStr routine is:
944 %
945 % int LookupStr(char **list,const char *string)
946 %
947 % A description of each parameter follows:
948 %
949 % o status: Method LookupStr returns the index of string in the list
950 % otherwise -1.
951 %
952 % o list: a list of strings.
953 %
954 % o string: a character string.
955 %
956 %
957 */
LookupStr(char ** list,const char * string)958 static int LookupStr(char **list,const char *string)
959 {
960 int
961 longest,
962 offset;
963
964 register char
965 **p;
966
967 offset=(-1);
968 longest=0;
969 for (p=list; *p; p++)
970 if (strEQcase(string,*p) > longest)
971 {
972 offset=p-list;
973 longest=strEQcase(string,*p);
974 }
975 return(offset);
976 }
977
978 /*
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
980 % %
981 % %
982 % %
983 % M a g i c k E r r o r H a n d l e r %
984 % %
985 % %
986 % %
987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
988 %
989 % Method MagickErrorHandler replaces GraphicsMagick's fatal error handler. This
990 % stores the message in a Perl variable,and longjmp's to return the error to
991 % Perl. If the error_flag variable is set, it also calls the Perl warn
992 % routine. Note that this doesn't exit but returns control to Perl; the
993 % Graphics::Magick handle may be left in a bad state.
994 %
995 % The format of the MagickErrorHandler routine is:
996 %
997 % MagickErrorHandler(const ExceptionType severity,const char *reason,
998 % const char *qualifier)
999 %
1000 % A description of each parameter follows:
1001 %
1002 % o severity: The severity of the exception.
1003 %
1004 % o reason: The reason of the exception.
1005 %
1006 % o description: The exception description.
1007 %
1008 %
1009 */
MagickErrorHandler(const ExceptionType severity,const char * reason,const char * description)1010 static void MagickErrorHandler(const ExceptionType severity,const char *reason,
1011 const char *description)
1012 {
1013 char
1014 text[MaxTextExtent];
1015
1016 dTHX; /* perl context */
1017 dMY_CXT;
1018 errno=0;
1019 FormatString(text,"Exception %d: %.1024s%s%.1024s%s%s%.64s%s",severity,
1020 (reason ? GetLocaleExceptionMessage(severity,reason) : "ERROR"),
1021 description ? " (" : "",
1022 description ? GetLocaleExceptionMessage(severity,description) : "",
1023 description ? ")" : "",errno ? " [" : "",errno ? strerror(errno) : "",
1024 errno? "]" : "");
1025 if ((MY_CXT.error_list == NULL) || (MY_CXT.error_jump == NULL))
1026 {
1027 /*
1028 Set up error buffer.
1029 */
1030 warn("%s",text);
1031 if (MY_CXT.error_jump == NULL)
1032 exit((int) severity % 100);
1033 }
1034 if (MY_CXT.error_list)
1035 {
1036 if (SvCUR(MY_CXT.error_list))
1037 sv_catpv(MY_CXT.error_list,"\n");
1038 sv_catpv(MY_CXT.error_list,text);
1039 }
1040 longjmp(*MY_CXT.error_jump,(int) severity);
1041 }
1042
1043 /*
1044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1045 % %
1046 % %
1047 % %
1048 % M a g i c k W a r n i n g H a n d l e r %
1049 % %
1050 % %
1051 % %
1052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1053 %
1054 % Method MagickWarningHandler replaces the GraphicsMagick warning handler. This
1055 % stores the (possibly multiple) reasons in a Perl variable for later
1056 % returning.
1057 %
1058 % The format of the MagickWarningHandler routine is:
1059 %
1060 % MagickWarningHandler(const ExceptionType severity,const char *reason,
1061 % const char *description)
1062 %
1063 % A description of each parameter follows:
1064 %
1065 % o severity: Specifies the numeric severity category.
1066 %
1067 % o reason: The reason of the exception.
1068 %
1069 % o description: Specifies any description to the reason.
1070 %
1071 %
1072 */
1073
MagickWarningHandler(const ExceptionType severity,const char * reason,const char * description)1074 static void MagickWarningHandler(const ExceptionType severity,
1075 const char *reason,const char *description)
1076 {
1077 char
1078 text[MaxTextExtent];
1079
1080 dTHX; /* perl context */
1081 dMY_CXT;
1082 errno=0;
1083 if (!reason)
1084 return;
1085 FormatString(text,"Exception %d: %.1024s%s%.1024s%s%s%.64s%s",severity,
1086 (reason ? GetLocaleExceptionMessage(severity,reason) : "WARNING"),
1087 description ? " (" : "",
1088 description ? GetLocaleExceptionMessage(severity,description) : "",
1089 description ? ")" : "",errno ? " [" : "",errno ? strerror(errno) : "",
1090 errno? "]" : "");
1091 if (MY_CXT.error_list == NULL)
1092 {
1093 /*
1094 Set up reason buffer.
1095 */
1096 warn("%s",text);
1097 if (MY_CXT.error_list == NULL)
1098 return;
1099 }
1100 if (SvCUR(MY_CXT.error_list))
1101 sv_catpv(MY_CXT.error_list,"\n"); /* add \n separator between reasons */
1102 sv_catpv(MY_CXT.error_list,text);
1103 }
1104
1105 /*
1106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1107 % %
1108 % %
1109 % %
1110 % S e t A t t r i b u t e %
1111 % %
1112 % %
1113 % %
1114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1115 %
1116 % Method SetAttribute sets the attribute to the value in sval. This can
1117 % change either or both of image or info.
1118 %
1119 % The format of the SetAttribute routine is:
1120 %
1121 % SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1122 % SV *sval)
1123 %
1124 % A description of each parameter follows:
1125 %
1126 % o status: Method SetAttribute returns the index of string in the list
1127 % otherwise -1.
1128 %
1129 % o list: a list of strings.
1130 %
1131 % o string: a character string.
1132 %
1133 %
1134 */
SetAttribute(pTHX_ struct PackageInfo * info,Image * image,char * attribute,SV * sval)1135 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1136 char *attribute,SV *sval)
1137 {
1138 DoublePixelPacket
1139 pixel;
1140
1141 ExceptionInfo
1142 exception;
1143
1144 int
1145 sp;
1146
1147 long
1148 x,
1149 y;
1150
1151 PixelPacket
1152 *color,
1153 target_color;
1154
1155 GetExceptionInfo(&exception);
1156 switch (*attribute)
1157 {
1158 case 'A':
1159 case 'a':
1160 {
1161 if (LocaleCompare(attribute,"adjoin") == 0)
1162 {
1163 sp=SvPOK(sval) ? LookupStr(BooleanTypes,SvPV(sval,na)) : SvIV(sval);
1164 if (sp < 0)
1165 {
1166 MagickError(OptionError,UnrecognizedType,SvPV(sval,na));
1167 return;
1168 }
1169 if (info)
1170 info->image_info->adjoin=sp != 0;
1171 return;
1172 }
1173 if (LocaleCompare(attribute,"antialias") == 0)
1174 {
1175 sp=SvPOK(sval) ? LookupStr(BooleanTypes,SvPV(sval,na)) : SvIV(sval);
1176 if (sp < 0)
1177 {
1178 MagickError(OptionError,UnrecognizedType,SvPV(sval,na));
1179 return;
1180 }
1181 if (info)
1182 {
1183 info->image_info->antialias=sp != 0;
1184 info->draw_info->text_antialias=sp != 0;
1185 }
1186 return;
1187 }
1188 if (LocaleCompare(attribute,"authenticate") == 0)
1189 {
1190 if (info)
1191 (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1192 return;
1193 }
1194 MagickError(OptionError,UnrecognizedAttribute,attribute);
1195 break;
1196 }
1197 case 'B':
1198 case 'b':
1199 {
1200 if (LocaleCompare(attribute,"background") == 0)
1201 {
1202 (void) QueryColorDatabase(SvPV(sval,na),&target_color,
1203 image ? &image->exception : &exception);
1204 if (info)
1205 info->image_info->background_color=target_color;
1206 for ( ; image; image=image->next)
1207 image->background_color=target_color;
1208 return;
1209 }
1210 if (LocaleCompare(attribute,"blue-primary") == 0)
1211 {
1212 for ( ; image; image=image->next)
1213 (void) sscanf(SvPV(sval,na),"%lf%*[,/]%lf",
1214 &image->chromaticity.blue_primary.x,
1215 &image->chromaticity.blue_primary.y);
1216 return;
1217 }
1218 if (LocaleCompare(attribute,"bordercolor") == 0)
1219 {
1220 (void) QueryColorDatabase(SvPV(sval,na),&target_color,
1221 image ? &image->exception : &exception);
1222 if (info)
1223 {
1224 info->image_info->border_color=target_color;
1225 info->draw_info->border_color=target_color;
1226 }
1227 for ( ; image; image=image->next)
1228 image->border_color=target_color;
1229 return;
1230 }
1231 MagickError(OptionError,UnrecognizedAttribute,attribute);
1232 break;
1233 }
1234 case 'C':
1235 case 'c':
1236 {
1237 if (LocaleCompare(attribute,"cache-threshold") == 0)
1238 {
1239 SetMagickResourceLimit(MemoryResource,SvIV(sval));
1240 SetMagickResourceLimit(MapResource,2*SvIV(sval));
1241 return;
1242 }
1243 if (LocaleCompare(attribute,"clip-mask") == 0)
1244 {
1245 Image
1246 *clip_mask;
1247
1248 clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL);
1249 for ( ; image; image=image->next)
1250 SetImageClipMask(image,clip_mask);
1251 return;
1252 }
1253 if (LocaleNCompare(attribute,"colormap",8) == 0)
1254 {
1255 for ( ; image; image=image->next)
1256 {
1257 int
1258 i;
1259
1260 if (image->storage_class == DirectClass)
1261 continue;
1262 i=0;
1263 (void) sscanf(attribute,"%*[^[][%d",&i);
1264 if (i > (long) image->colors)
1265 i%=image->colors;
1266 if (strchr(SvPV(sval,na),',') == 0)
1267 QueryColorDatabase(SvPV(sval,na),image->colormap+i,
1268 image ? &image->exception : &exception);
1269 else
1270 {
1271 color=image->colormap+i;
1272 pixel.red=color->red;
1273 pixel.green=color->green;
1274 pixel.blue=color->blue;
1275 (void) sscanf(SvPV(sval,na),"%lf%*[,/]%lf%*[,/]%lf",&pixel.red,
1276 &pixel.green,&pixel.blue);
1277 color->red=(Quantum) ((pixel.red < 0) ? 0 :
1278 (pixel.red > MaxRGB) ? MaxRGB : pixel.red+0.5);
1279 color->green=(Quantum) ((pixel.green < 0) ? 0 :
1280 (pixel.green > MaxRGB) ? MaxRGB : pixel.green+0.5);
1281 color->blue=(Quantum) ((pixel.blue < 0) ? 0 :
1282 (pixel.blue > MaxRGB) ? MaxRGB : pixel.blue+0.5);
1283 }
1284 }
1285 return;
1286 }
1287 if (LocaleCompare(attribute,"colorspace") == 0)
1288 {
1289 sp=SvPOK(sval) ? LookupStr(ColorspaceTypes,SvPV(sval,na)) :
1290 SvIV(sval);
1291 if (sp < 0)
1292 {
1293 MagickError(OptionError,UnrecognizedColorspace,SvPV(sval,na));
1294 return;
1295 }
1296 if (info)
1297 info->image_info->colorspace=(ColorspaceType) sp;
1298 for ( ; image; image=image->next)
1299 TransformColorspace(image,(ColorspaceType) sp);
1300 return;
1301 }
1302 if (LocaleCompare(attribute,"compression") == 0)
1303 {
1304 sp=SvPOK(sval) ? LookupStr(CompressionTypes,SvPV(sval,na)) :
1305 SvIV(sval);
1306 if (sp < 0)
1307 {
1308 MagickError(OptionError,UnrecognizedImageCompression,
1309 SvPV(sval,na));
1310 return;
1311 }
1312 if (info)
1313 info->image_info->compression=(CompressionType) sp;
1314 for ( ; image; image=image->next)
1315 image->compression=(CompressionType) sp;
1316 return;
1317 }
1318 MagickError(OptionError,UnrecognizedAttribute,attribute);
1319 break;
1320 }
1321 case 'D':
1322 case 'd':
1323 {
1324 if (LocaleCompare(attribute,"debug") == 0)
1325 {
1326 SetLogEventMask(SvPV(sval,na));
1327 return;
1328 }
1329 if (LocaleCompare(attribute,"delay") == 0)
1330 {
1331 for ( ; image; image=image->next)
1332 image->delay=SvIV(sval);
1333 return;
1334 }
1335 if (LocaleCompare(attribute,"disk-limit") == 0)
1336 {
1337 SetMagickResourceLimit(DiskResource,SvIV(sval));
1338 return;
1339 }
1340 if (LocaleCompare(attribute,"density") == 0)
1341 {
1342 if (!IsGeometry(SvPV(sval,na)))
1343 {
1344 MagickError(OptionError,MissingGeometry,SvPV(sval,na));
1345 return;
1346 }
1347 if (info)
1348 {
1349 (void) CloneString(&info->image_info->density,SvPV(sval,na));
1350 (void) CloneString(&info->draw_info->density,SvPV(sval,na));
1351 }
1352 for ( ; image; image=image->next)
1353 {
1354 int
1355 count;
1356
1357 count=sscanf(info->image_info->density,"%lfx%lf",
1358 &image->x_resolution,&image->y_resolution);
1359 if (count != 2)
1360 image->y_resolution=image->x_resolution;
1361 }
1362 return;
1363 }
1364 if (LocaleCompare(attribute,"depth") == 0)
1365 {
1366 if (info)
1367 info->image_info->depth=SvIV(sval);
1368 for ( ; image; image=image->next)
1369 SetImageDepth(image,SvIV(sval));
1370 return;
1371 }
1372 if (LocaleCompare(attribute,"dispose") == 0)
1373 {
1374 sp=SvPOK(sval) ? LookupStr(DisposeTypes,SvPV(sval,na)) : SvIV(sval);
1375 if (sp < 0)
1376 sp=SvIV(sval);
1377 if (sp < 0)
1378 {
1379 MagickError(OptionError,UnrecognizedDisposeMethod,
1380 SvPV(sval,na));
1381 return;
1382 }
1383 for ( ; image; image=image->next)
1384 image->dispose=(DisposeType) sp;
1385 return;
1386 }
1387 if (LocaleCompare(attribute,"dither") == 0)
1388 {
1389 if (info)
1390 {
1391 sp=SvPOK(sval) ? LookupStr(BooleanTypes,SvPV(sval,na)) :
1392 SvIV(sval);
1393 if (sp < 0)
1394 {
1395 MagickError(OptionError,UnrecognizedType,SvPV(sval,na));
1396 return;
1397 }
1398 info->image_info->dither=sp != 0;
1399 }
1400 return;
1401 }
1402 if (LocaleCompare(attribute,"display") == 0)
1403 {
1404 display:
1405 if (info)
1406 {
1407 (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1408 (void) CloneString(&info->draw_info->server_name,SvPV(sval,na));
1409 }
1410 return;
1411 }
1412 MagickError(OptionError,UnrecognizedAttribute,attribute);
1413 break;
1414 }
1415 case 'E':
1416 case 'e':
1417 {
1418 if (LocaleCompare(attribute,"endian") == 0)
1419 {
1420 sp=SvPOK(sval) ? LookupStr(EndianTypes,SvPV(sval,na)) : SvIV(sval);
1421 if (sp < 0)
1422 {
1423 MagickError(OptionError,UnrecognizedEndianType,SvPV(sval,na));
1424 return;
1425 }
1426 if (info)
1427 info->image_info->endian=(EndianType) sp;
1428 for ( ; image; image=image->next)
1429 image->endian=(EndianType) sp;
1430 return;
1431 }
1432 MagickError(OptionError,UnrecognizedAttribute,attribute);
1433 break;
1434 }
1435 case 'F':
1436 case 'f':
1437 {
1438 if (LocaleCompare(attribute,"filename") == 0)
1439 {
1440 if (info)
1441 (void) strncpy(info->image_info->filename,SvPV(sval,na),
1442 MaxTextExtent-1);
1443 for ( ; image; image=image->next)
1444 (void) strncpy(image->filename,SvPV(sval,na),MaxTextExtent-1);
1445 return;
1446 }
1447 if (LocaleCompare(attribute,"file") == 0)
1448 {
1449 if (info)
1450 info->image_info->file=PerlIO_findFILE(IoIFP(sv_2io(sval)));
1451 return;
1452 }
1453 if (LocaleCompare(attribute,"fill") == 0)
1454 {
1455 if (info)
1456 {
1457 (void) QueryColorDatabase(SvPV(sval,na),&info->draw_info->fill,
1458 image ? &image->exception : &exception);
1459 (void) QueryColorDatabase(SvPV(sval,na),&info->image_info->pen,
1460 image ? &image->exception : &exception);
1461 }
1462 return;
1463 }
1464 if (LocaleCompare(attribute,"font") == 0)
1465 {
1466 if (info)
1467 {
1468 (void) CloneString(&info->image_info->font,SvPV(sval,na));
1469 (void) CloneString(&info->draw_info->font,SvPV(sval,na));
1470 }
1471 return;
1472 }
1473 if (LocaleCompare(attribute,"fuzz") == 0)
1474 {
1475 if (info)
1476 info->image_info->fuzz=SvNV(sval);
1477 for ( ; image; image=image->next)
1478 image->fuzz=SvNV(sval);
1479 return;
1480 }
1481 MagickError(OptionError,UnrecognizedAttribute,attribute);
1482 break;
1483 }
1484 case 'G':
1485 case 'g':
1486 {
1487 if (LocaleCompare(attribute,"gamma") == 0)
1488 {
1489 for ( ; image; image=image->next)
1490 image->gamma=SvNV(sval);
1491 return;
1492 }
1493 if (LocaleCompare(attribute,"gravity") == 0)
1494 {
1495 sp=SvPOK(sval) ? LookupStr(GravityTypes,SvPV(sval,na)) :
1496 SvIV(sval);
1497 if (sp < 0)
1498 {
1499 MagickError(OptionError,UnrecognizedGravityType,SvPV(sval,na));
1500 return;
1501 }
1502 for ( ; image; image=image->next)
1503 image->gravity=(GravityType) sp;
1504 return;
1505 }
1506 if (LocaleCompare(attribute,"green-primary") == 0)
1507 {
1508 for ( ; image; image=image->next)
1509 (void) sscanf(SvPV(sval,na),"%lf%*[,/]%lf",
1510 &image->chromaticity.green_primary.x,
1511 &image->chromaticity.green_primary.y);
1512 return;
1513 }
1514 MagickError(OptionError,UnrecognizedAttribute,attribute);
1515 break;
1516 }
1517 case 'I':
1518 case 'i':
1519 {
1520 if (LocaleNCompare(attribute,"index",5) == 0)
1521 {
1522 long
1523 index;
1524
1525 IndexPacket
1526 *indexes;
1527
1528 register PixelPacket
1529 *p;
1530
1531 for ( ; image; image=image->next)
1532 {
1533 if (image->storage_class != PseudoClass)
1534 continue;
1535 x=0;
1536 y=0;
1537 (void) sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1538 p=GetImagePixels(image,(long) (x % image->columns),
1539 (long) (y % image->rows),1,1);
1540 if (p == (PixelPacket *) NULL)
1541 break;
1542 indexes=AccessMutableIndexes(image);
1543 (void) sscanf(SvPV(sval,na),"%ld",&index);
1544 if ((index >= 0) && (index < (long) image->colors))
1545 *indexes=(IndexPacket) index;
1546 (void) SyncImagePixels(image);
1547 }
1548 return;
1549 }
1550 if (LocaleCompare(attribute,"iterations") == 0)
1551 {
1552 iterations:
1553 for ( ; image; image=image->next)
1554 image->iterations=SvIV(sval);
1555 return;
1556 }
1557 if (LocaleCompare(attribute,"interlace") == 0)
1558 {
1559 sp=SvPOK(sval) ? LookupStr(InterlaceTypes,SvPV(sval,na)) : SvIV(sval);
1560 if (sp < 0)
1561 {
1562 MagickError(OptionError,UnrecognizedInterlaceType,
1563 SvPV(sval,na));
1564 return;
1565 }
1566 if (info)
1567 info->image_info->interlace=(InterlaceType) sp;
1568 for ( ; image; image=image->next)
1569 image->interlace=(InterlaceType) sp;
1570 return;
1571 }
1572 MagickError(OptionError,UnrecognizedAttribute,attribute);
1573 break;
1574 }
1575 case 'L':
1576 case 'l':
1577 {
1578 if (LocaleCompare(attribute,"loop") == 0)
1579 goto iterations;
1580 MagickError(OptionError,UnrecognizedAttribute,attribute);
1581 break;
1582 }
1583 case 'M':
1584 case 'm':
1585 {
1586 if (LocaleCompare(attribute,"magick") == 0)
1587 {
1588 if (info)
1589 {
1590 ExceptionInfo
1591 exception;
1592
1593 GetExceptionInfo(&exception);
1594 FormatString(info->image_info->filename,"%.1024s:",SvPV(sval,na));
1595 SetImageInfo(info->image_info,SETMAGICK_WRITE,&exception);
1596 if (*info->image_info->magick == '\0')
1597 MagickError(OptionError,UnrecognizedImageFormat,
1598 info->image_info->filename);
1599 else
1600 for ( ; image; image=image->next)
1601 (void) strncpy(image->magick,info->image_info->magick,
1602 MaxTextExtent-1);
1603 DestroyExceptionInfo(&exception);
1604 }
1605 return;
1606 }
1607 if (LocaleCompare(attribute,"map-limit") == 0)
1608 {
1609 SetMagickResourceLimit(MapResource,SvIV(sval));
1610 return;
1611 }
1612 if (LocaleCompare(attribute,"mattecolor") == 0)
1613 {
1614 (void) QueryColorDatabase(SvPV(sval,na),&target_color,
1615 image ? &image->exception : &exception);
1616 if (info)
1617 info->image_info->matte_color=target_color;
1618 for ( ; image; image=image->next)
1619 image->matte_color=target_color;
1620 return;
1621 }
1622 if (LocaleCompare(attribute,"matte") == 0)
1623 {
1624 sp=SvPOK(sval) ? LookupStr(BooleanTypes,SvPV(sval,na)) : SvIV(sval);
1625 if (sp < 0)
1626 {
1627 MagickError(OptionError,UnrecognizedType,SvPV(sval,na));
1628 return;
1629 }
1630 for ( ; image; image=image->next)
1631 image->matte=sp != 0;
1632 return;
1633 }
1634 if (LocaleCompare(attribute,"memory-limit") == 0)
1635 {
1636 SetMagickResourceLimit(MemoryResource,SvIV(sval));
1637 return;
1638 }
1639 if (LocaleCompare(attribute,"monochrome") == 0)
1640 {
1641 sp=SvPOK(sval) ? LookupStr(BooleanTypes,SvPV(sval,na)) : SvIV(sval);
1642 if (sp < 0)
1643 {
1644 MagickError(OptionError,UnrecognizedType,SvPV(sval,na));
1645 return;
1646 }
1647 if (info)
1648 info->image_info->monochrome=sp != 0;
1649 return;
1650 }
1651 MagickError(OptionError,UnrecognizedAttribute,attribute);
1652 break;
1653 }
1654 case 'P':
1655 case 'p':
1656 {
1657 if (LocaleCompare(attribute,"page") == 0)
1658 {
1659 char
1660 *geometry;
1661
1662 geometry=GetPageGeometry(SvPV(sval,na));
1663 if (info)
1664 (void) CloneString(&info->image_info->page,geometry);
1665 for ( ; image; image=image->next)
1666 (void) GetImageGeometry(image,geometry,False,&image->page);
1667 MagickFreeMemory(geometry);
1668 return;
1669 }
1670 if (LocaleCompare(attribute,"pen") == 0)
1671 {
1672 if (info)
1673 (void) QueryColorDatabase(SvPV(sval,na),&info->draw_info->fill,
1674 image ? &image->exception : &exception);
1675 return;
1676 }
1677 if (LocaleNCompare(attribute,"pixel",5) == 0)
1678 {
1679 register PixelPacket
1680 *p;
1681
1682 for ( ; image; image=image->next)
1683 {
1684 x=0;
1685 y=0;
1686 (void) sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1687 p=GetImagePixels(image,(long) (x % image->columns),
1688 (long) (y % image->rows),1,1);
1689 if (p == (PixelPacket *) NULL)
1690 break;
1691 image->storage_class=DirectClass;
1692 if (strchr(SvPV(sval,na),',') == 0)
1693 QueryColorDatabase(SvPV(sval,na),p,
1694 image ? &image->exception : &exception);
1695 else
1696 {
1697 pixel.red=p->red;
1698 pixel.green=p->green;
1699 pixel.blue=p->blue;
1700 pixel.opacity=p->opacity;
1701 (void) sscanf(SvPV(sval,na),"%lf%*[,/]%lf%*[,/]%lf%*[,/]%lf",
1702 &pixel.red,&pixel.green,&pixel.blue,&pixel.opacity);
1703 p->red=(Quantum) ((pixel.red < 0) ? 0 :
1704 (pixel.red > MaxRGB) ? MaxRGB : pixel.red+0.5);
1705 p->green=(Quantum) ((pixel.green < 0) ? 0 :
1706 (pixel.green > MaxRGB) ? MaxRGB : pixel.green+0.5);
1707 p->blue=(Quantum) ((pixel.blue < 0) ? 0 :
1708 (pixel.blue > MaxRGB) ? MaxRGB : pixel.blue+0.5);
1709 p->opacity=(Quantum) ((pixel.opacity < 0) ? 0 :
1710 (pixel.opacity > MaxRGB) ? MaxRGB : pixel.opacity+0.5);
1711 }
1712 (void) SyncImagePixels(image);
1713 }
1714 return;
1715 }
1716 if (LocaleCompare(attribute,"pointsize") == 0)
1717 {
1718 if (info)
1719 {
1720 (void) sscanf(SvPV(sval,na),"%lf",&info->image_info->pointsize);
1721 (void) sscanf(SvPV(sval,na),"%lf",&info->draw_info->pointsize);
1722 }
1723 return;
1724 }
1725 if (LocaleCompare(attribute,"preview") == 0)
1726 {
1727 sp=SvPOK(sval) ? LookupStr(PreviewTypes,SvPV(sval,na)) : SvIV(sval);
1728 if (sp < 0)
1729 {
1730 MagickError(OptionError,UnrecognizedType,SvPV(sval,na));
1731 return;
1732 }
1733 if (info)
1734 info->image_info->preview_type=(PreviewType) sp;
1735 return;
1736 }
1737 MagickError(OptionError,UnrecognizedAttribute,attribute);
1738 break;
1739 }
1740 case 'Q':
1741 case 'q':
1742 {
1743 if (LocaleCompare(attribute,"quality") == 0)
1744 {
1745 if (info)
1746 info->image_info->quality=SvIV(sval);
1747 return;
1748 }
1749 MagickError(OptionError,UnrecognizedAttribute,attribute);
1750 break;
1751 }
1752 case 'R':
1753 case 'r':
1754 {
1755 if (LocaleCompare(attribute,"red-primary") == 0)
1756 {
1757 for ( ; image; image=image->next)
1758 (void) sscanf(SvPV(sval,na),"%lf%*[,/]%lf",
1759 &image->chromaticity.red_primary.x,
1760 &image->chromaticity.red_primary.y);
1761 return;
1762 }
1763 if (LocaleCompare(attribute,"render") == 0)
1764 {
1765 sp=SvPOK(sval) ? LookupStr(IntentTypes,SvPV(sval,na)) : SvIV(sval);
1766 if (sp < 0)
1767 {
1768 MagickError(OptionError,UnrecognizedIntentType,SvPV(sval,na));
1769 return;
1770 }
1771 for ( ; image; image=image->next)
1772 image->rendering_intent=(RenderingIntent) sp;
1773 return;
1774 }
1775 MagickError(OptionError,UnrecognizedAttribute,attribute);
1776 break;
1777 }
1778 case 'S':
1779 case 's':
1780 {
1781 if (LocaleCompare(attribute,"sampling-factor") == 0)
1782 {
1783 if (!IsGeometry(SvPV(sval,na)))
1784 {
1785 MagickError(OptionError,MissingGeometry,SvPV(sval,na));
1786 return;
1787 }
1788 if (info)
1789 (void) CloneString(&info->image_info->sampling_factor,
1790 SvPV(sval,na));
1791 return;
1792 }
1793 if (LocaleCompare(attribute,"scene") == 0)
1794 {
1795 for ( ; image; image=image->next)
1796 image->scene=SvIV(sval);
1797 return;
1798 }
1799 if (LocaleCompare(attribute,"subimage") == 0)
1800 {
1801 if (info)
1802 info->image_info->subimage=SvIV(sval);
1803 return;
1804 }
1805 if (LocaleCompare(attribute,"subrange") == 0)
1806 {
1807 if (info)
1808 info->image_info->subrange=SvIV(sval);
1809 return;
1810 }
1811 if (LocaleCompare(attribute,"server") == 0)
1812 goto display;
1813 if (LocaleCompare(attribute,"size") == 0)
1814 {
1815 if (info)
1816 {
1817 if (!IsGeometry(SvPV(sval,na)))
1818 {
1819 MagickError(OptionError,MissingGeometry,SvPV(sval,na));
1820 return;
1821 }
1822 (void) CloneString(&info->image_info->size,SvPV(sval,na));
1823 }
1824 return;
1825 }
1826 if (LocaleCompare(attribute,"stroke") == 0)
1827 {
1828 if (info)
1829 (void) QueryColorDatabase(SvPV(sval,na),&info->draw_info->stroke,
1830 image ? &image->exception : &exception);
1831 return;
1832 }
1833 MagickError(OptionError,UnrecognizedAttribute,attribute);
1834 break;
1835 }
1836 case 'T':
1837 case 't':
1838 {
1839 if (LocaleCompare(attribute,"tile") == 0)
1840 {
1841 if (info)
1842 (void) CloneString(&info->image_info->tile,SvPV(sval,na));
1843 return;
1844 }
1845 if (LocaleCompare(attribute,"texture") == 0)
1846 {
1847 if (info)
1848 (void) CloneString(&info->image_info->texture,SvPV(sval,na));
1849 return;
1850 }
1851 if (LocaleCompare(attribute,"type") == 0)
1852 {
1853 sp=SvPOK(sval) ? LookupStr(ImageTypes,SvPV(sval,na)) : SvIV(sval);
1854 if (sp < 0)
1855 {
1856 MagickError(OptionError,UnrecognizedType,SvPV(sval,na));
1857 return;
1858 }
1859 if (info)
1860 info->image_info->type=(ImageType) sp;
1861 for ( ; image; image=image->next)
1862 SetImageType(image,(ImageType) sp);
1863 return;
1864 }
1865 MagickError(OptionError,UnrecognizedAttribute,attribute);
1866 break;
1867 }
1868 case 'U':
1869 case 'u':
1870 {
1871 if (LocaleCompare(attribute,"units") == 0)
1872 {
1873 sp=SvPOK(sval) ? LookupStr(ResolutionTypes,SvPV(sval,na)) :
1874 SvIV(sval);
1875 if (sp < 0)
1876 {
1877 MagickError(OptionError,MissingType,SvPV(sval,na));
1878 return;
1879 }
1880 if (info)
1881 info->image_info->units=(ResolutionType) sp;
1882 for ( ; image; image=image->next)
1883 image->units=(ResolutionType) sp;
1884 return;
1885 }
1886 MagickError(OptionError,UnrecognizedAttribute,attribute);
1887 break;
1888 }
1889 case 'V':
1890 case 'v':
1891 {
1892 if (LocaleCompare(attribute,"verbose") == 0)
1893 {
1894 sp=SvPOK(sval) ? LookupStr(BooleanTypes,SvPV(sval,na)) : SvIV(sval);
1895 if (sp < 0)
1896 {
1897 MagickError(OptionError,UnrecognizedType,SvPV(sval,na));
1898 return;
1899 }
1900 if (info)
1901 info->image_info->verbose=sp != 0;
1902 return;
1903 }
1904 if (LocaleCompare(attribute,"view") == 0)
1905 {
1906 if (info)
1907 (void) CloneString(&info->image_info->view,SvPV(sval,na));
1908 return;
1909 }
1910 if (LocaleCompare(attribute,"virtual-pixel") == 0)
1911 {
1912 sp=SvPOK(sval) ? LookupStr(VirtualPixelMethods,SvPV(sval,na)) :
1913 SvIV(sval);
1914 if (sp < 0)
1915 {
1916 MagickError(OptionError,UnrecognizedVirtualPixelMethod,
1917 SvPV(sval,na));
1918 return;
1919 }
1920 for ( ; image; image=image->next)
1921 SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
1922 return;
1923 }
1924 MagickError(OptionError,UnrecognizedAttribute,attribute);
1925 break;
1926 }
1927 case 'W':
1928 case 'w':
1929 {
1930 if (LocaleCompare(attribute,"white-point") == 0)
1931 {
1932 for ( ; image; image=image->next)
1933 (void) sscanf(SvPV(sval,na),"%lf%*[,/]%lf",
1934 &image->chromaticity.white_point.x,
1935 &image->chromaticity.white_point.y);
1936 return;
1937 }
1938 MagickError(OptionError,UnrecognizedAttribute,attribute);
1939 break;
1940 }
1941 default:
1942 {
1943 MagickError(OptionError,UnrecognizedAttribute,attribute);
1944 break;
1945 }
1946 }
1947 DestroyExceptionInfo(&exception);
1948 if (image == (Image *) NULL)
1949 MagickError(OptionError,UnrecognizedAttribute,attribute);
1950 for ( ; image; image=image->next)
1951 (void) SetImageAttribute(image,attribute,SvPV(sval,na));
1952 }
1953
1954 /*
1955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1956 % %
1957 % %
1958 % %
1959 % S e t u p L i s t %
1960 % %
1961 % %
1962 % %
1963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1964 %
1965 % Method SetupList returns the list of all the images linked by their
1966 % image->next and image->previous link lists for use with GraphicsMagick. If
1967 % info is non-NULL, an info structure is returned in *info. If
1968 % reference_vector is non-NULL,an array of SV* are returned in
1969 % *reference_vector. Reference_vector is used when the images are going to be
1970 % replaced with new Image*'s.
1971 %
1972 % The format of the SetupList routine is:
1973 %
1974 % Image *SetupList(SV *reference,struct PackageInfo **info,
1975 % SV ***reference_vector)
1976 %
1977 % A description of each parameter follows:
1978 %
1979 % o status: Method SetupList returns the index of string in the list
1980 % otherwise -1.
1981 %
1982 % o list: a list of strings.
1983 %
1984 % o string: a character string.
1985 %
1986 %
1987 */
SetupList(pTHX_ SV * reference,struct PackageInfo ** info,SV *** reference_vector)1988 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
1989 SV ***reference_vector)
1990 {
1991 Image
1992 *image;
1993
1994 int
1995 current,
1996 last;
1997
1998 if (reference_vector)
1999 *reference_vector=NULL;
2000 if (info)
2001 *info=NULL;
2002 current=0;
2003 last=0;
2004 image=GetList(aTHX_ reference,reference_vector,¤t,&last);
2005 if (info && (SvTYPE(reference) == SVt_PVAV))
2006 *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL);
2007 return(image);
2008 }
2009
2010 /*
2011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2012 % %
2013 % %
2014 % %
2015 % s t r E Q c a s e %
2016 % %
2017 % %
2018 % %
2019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2020 %
2021 % Method strEQcase compares two strings and returns 0 if they are the
2022 % same or if the second string runs out first. The comparison is case
2023 % insensitive.
2024 %
2025 % The format of the strEQcase routine is:
2026 %
2027 % int strEQcase(const char *p,const char *q)
2028 %
2029 % A description of each parameter follows:
2030 %
2031 % o status: Method strEQcase returns zero if strings p and q are the
2032 % same or if the second string runs out first.
2033 %
2034 % o p: a character string.
2035 %
2036 % o q: a character string.
2037 %
2038 %
2039 */
strEQcase(const char * p,const char * q)2040 static int strEQcase(const char *p,const char *q)
2041 {
2042 char
2043 c;
2044
2045 register int
2046 i;
2047
2048 for (i=0 ; (c=(*q)) != 0; i++)
2049 {
2050 if ((isUPPER(c) ? toLOWER(c) : c) != (isUPPER(*p) ? toLOWER(*p) : *p))
2051 return(0);
2052 p++;
2053 q++;
2054 }
2055 return(i);
2056 }
2057
2058 /*
2059 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2060 % %
2061 % %
2062 % %
2063 % G r a p h i c s : : M a g i c k %
2064 % %
2065 % %
2066 % %
2067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2068 %
2069 %
2070 */
2071 MODULE = Graphics::Magick PACKAGE = Graphics::Magick
2072
2073 PROTOTYPES: ENABLE
2074
2075 BOOT:
2076 InitializeMagick(PackageName);
2077 SetWarningHandler(MagickWarningHandler);
2078 SetErrorHandler(MagickErrorHandler);
2079 { MY_CXT_INIT; }
2080
2081 double
constant(name,argument)2082 constant(name,argument)
2083 char *name
2084 int argument
2085
2086 #
2087 ###############################################################################
2088 # #
2089 # #
2090 # #
2091 # A n i m a t e #
2092 # #
2093 # #
2094 # #
2095 ###############################################################################
2096 #
2097 #
2098 void
2099 Animate(ref,...)
2100 Graphics::Magick ref=NO_INIT
2101 ALIAS:
2102 AnimateImage = 1
2103 animate = 2
2104 animateimage = 3
2105 PPCODE:
2106 {
2107 jmp_buf
2108 error_jmp;
2109
2110 Image
2111 *image;
2112
2113 register int
2114 i;
2115
2116 struct PackageInfo
2117 *info,
2118 *package_info;
2119
2120 SV
2121 *reference;
2122
2123 volatile int
2124 status;
2125
2126 dMY_CXT;
2127 MY_CXT.error_list=newSVpv("",0);
2128 package_info=(struct PackageInfo *) NULL;
2129 status=0;
2130 if (!sv_isobject(ST(0)))
2131 {
2132 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
2133 goto MethodException;
2134 }
2135 reference=SvRV(ST(0));
2136 MY_CXT.error_jump=(&error_jmp);
2137 status=setjmp(error_jmp);
2138 if (status)
2139 goto MethodException;
2140 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
2141 if (!image)
2142 {
2143 MagickError(OptionError,NoImagesDefined,NULL);
2144 goto MethodException;
2145 }
2146 package_info=ClonePackageInfo(info);
2147 if (items == 2)
2148 SetAttribute(aTHX_ package_info,NULL,"server",ST(1));
2149 else
2150 if (items > 2)
2151 for (i=2; i < items; i+=2)
2152 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i));
2153 AnimateImages(package_info->image_info,image);
2154 (void) CatchImageException(image);
2155
2156 MethodException:
2157 if (package_info)
2158 DestroyPackageInfo(package_info);
2159 sv_setiv(MY_CXT.error_list,(IV)
2160 (status ? status : SvCUR(MY_CXT.error_list) != 0));
2161 SvPOK_on(MY_CXT.error_list);
2162 ST(0)=sv_2mortal(MY_CXT.error_list);
2163 MY_CXT.error_list=NULL;
2164 MY_CXT.error_jump=NULL;
2165 XSRETURN(1);
2166 }
2167
2168 #
2169 ###############################################################################
2170 # #
2171 # #
2172 # #
2173 # A p p e n d #
2174 # #
2175 # #
2176 # #
2177 ###############################################################################
2178 #
2179 #
2180 void
Append(ref,...)2181 Append(ref,...)
2182 Graphics::Magick ref=NO_INIT
2183 ALIAS:
2184 AppendImage = 1
2185 append = 2
2186 appendimage = 3
2187 PPCODE:
2188 {
2189 AV
2190 *av;
2191
2192 char
2193 *attribute;
2194
2195 ExceptionInfo
2196 exception;
2197
2198 HV
2199 *hv;
2200
2201 jmp_buf
2202 error_jmp;
2203
2204 Image
2205 *image;
2206
2207 int
2208 stack;
2209
2210 register int
2211 i;
2212
2213 struct PackageInfo
2214 *info;
2215
2216 SV
2217 *av_reference,
2218 *reference,
2219 *rv,
2220 *sv;
2221
2222 volatile int
2223 status;
2224
2225 dMY_CXT;
2226 MY_CXT.error_list=newSVpv("",0);
2227 attribute=NULL;
2228 av=NULL;
2229 status=0;
2230 if (!sv_isobject(ST(0)))
2231 {
2232 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
2233 goto MethodException;
2234 }
2235 reference=SvRV(ST(0));
2236 hv=SvSTASH(reference);
2237 av=newAV();
2238 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2239 SvREFCNT_dec(av);
2240 MY_CXT.error_jump=(&error_jmp);
2241 status=setjmp(error_jmp);
2242 if (status)
2243 goto MethodException;
2244 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
2245 if (!image)
2246 {
2247 MagickError(OptionError,NoImagesDefined,NULL);
2248 goto MethodException;
2249 }
2250 info=GetPackageInfo(aTHX_ (void *) av,info);
2251 /*
2252 Get options.
2253 */
2254 stack=True;
2255 for (i=2; i < items; i+=2)
2256 {
2257 attribute=(char *) SvPV(ST(i-1),na);
2258 switch (*attribute)
2259 {
2260 case 'S':
2261 case 's':
2262 {
2263 if (LocaleCompare(attribute,"stack") == 0)
2264 {
2265 stack=LookupStr(BooleanTypes,SvPV(ST(i),na));
2266 if (stack < 0)
2267 {
2268 MagickError(OptionError,UnrecognizedType,SvPV(ST(i),na));
2269 return;
2270 }
2271 break;
2272 }
2273 MagickError(OptionError,UnrecognizedAttribute,attribute);
2274 break;
2275 }
2276 default:
2277 {
2278 MagickError(OptionError,UnrecognizedAttribute,attribute);
2279 break;
2280 }
2281 }
2282 }
2283 GetExceptionInfo(&exception);
2284 image=AppendImages(image,stack,&exception);
2285 if (exception.severity != UndefinedException)
2286 CatchException(&exception);
2287 DestroyExceptionInfo(&exception);
2288 for ( ; image; image=image->next)
2289 {
2290 sv=newSViv((IV) (magick_uintptr_t)image);
2291 rv=newRV(sv);
2292 av_push(av,sv_bless(rv,hv));
2293 SvREFCNT_dec(sv);
2294 }
2295 ST(0)=av_reference;
2296 MY_CXT.error_jump=NULL;
2297 SvREFCNT_dec(MY_CXT.error_list); /* can't return warning messages */
2298 MY_CXT.error_list=NULL;
2299 XSRETURN(1);
2300
2301 MethodException:
2302 MY_CXT.error_jump=NULL;
2303 sv_setiv(MY_CXT.error_list,(IV) (status ? status : SvCUR(MY_CXT.error_list) != 0));
2304 SvPOK_on(MY_CXT.error_list);
2305 ST(0)=sv_2mortal(MY_CXT.error_list);
2306 MY_CXT.error_list=NULL;
2307 MY_CXT.error_jump=NULL;
2308 XSRETURN(1);
2309 }
2310
2311 #
2312 ###############################################################################
2313 # #
2314 # #
2315 # #
2316 # A v e r a g e #
2317 # #
2318 # #
2319 # #
2320 ###############################################################################
2321 #
2322 #
2323 void
Average(ref)2324 Average(ref)
2325 Graphics::Magick ref=NO_INIT
2326 ALIAS:
2327 AverageImage = 1
2328 average = 2
2329 averageimage = 3
2330 PPCODE:
2331 {
2332 AV
2333 *av;
2334
2335 char
2336 *p;
2337
2338 ExceptionInfo
2339 exception;
2340
2341 HV
2342 *hv;
2343
2344 jmp_buf
2345 error_jmp;
2346
2347 Image
2348 *image;
2349
2350 struct PackageInfo
2351 *info;
2352
2353 SV
2354 *reference,
2355 *rv,
2356 *sv;
2357
2358 volatile int
2359 status;
2360
2361 dMY_CXT;
2362 MY_CXT.error_list=newSVpv("",0);
2363 status=0;
2364 if (!sv_isobject(ST(0)))
2365 {
2366 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
2367 goto MethodException;
2368 }
2369 reference=SvRV(ST(0));
2370 hv=SvSTASH(reference);
2371 MY_CXT.error_jump=(&error_jmp);
2372 status=setjmp(error_jmp);
2373 if (status)
2374 goto MethodException;
2375 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
2376 if (!image)
2377 {
2378 MagickError(OptionError,NoImagesDefined,NULL);
2379 goto MethodException;
2380 }
2381 GetExceptionInfo(&exception);
2382 image=AverageImages(image,&exception);
2383 if (exception.severity != UndefinedException)
2384 CatchException(&exception);
2385 DestroyExceptionInfo(&exception);
2386 /*
2387 Create blessed Perl array for the returned image.
2388 */
2389 av=newAV();
2390 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2391 SvREFCNT_dec(av);
2392 sv=newSViv((IV) (magick_uintptr_t)image);
2393 rv=newRV(sv);
2394 av_push(av,sv_bless(rv,hv));
2395 SvREFCNT_dec(sv);
2396 info=GetPackageInfo(aTHX_ (void *) av,info);
2397 FormatString(info->image_info->filename,"average-%.*s",MaxTextExtent-9,
2398 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2399 (void) strncpy(image->filename,info->image_info->filename,MaxTextExtent-1);
2400 SetImageInfo(info->image_info,SETMAGICK_WRITE,&image->exception);
2401 SvREFCNT_dec(MY_CXT.error_list);
2402 MY_CXT.error_jump=NULL;
2403 XSRETURN(1);
2404
2405 MethodException:
2406 sv_setiv(MY_CXT.error_list,(IV) (status ? status : SvCUR(MY_CXT.error_list) != 0));
2407 SvPOK_on(MY_CXT.error_list); /* return messages in string context */
2408 ST(0)=sv_2mortal(MY_CXT.error_list);
2409 MY_CXT.error_list=NULL;
2410 MY_CXT.error_jump=NULL;
2411 XSRETURN(1);
2412 }
2413
2414 #
2415 ###############################################################################
2416 # #
2417 # #
2418 # #
2419 # B l o b T o I m a g e #
2420 # #
2421 # #
2422 # #
2423 ###############################################################################
2424 #
2425 #
2426 void
BlobToImage(ref,...)2427 BlobToImage(ref,...)
2428 Graphics::Magick ref=NO_INIT
2429 ALIAS:
2430 BlobToImage = 1
2431 blobtoimage = 2
2432 blobto = 3
2433 PPCODE:
2434 {
2435 AV
2436 *av;
2437
2438 char
2439 **keep,
2440 **list;
2441
2442 ExceptionInfo
2443 exception;
2444
2445 HV
2446 *hv;
2447
2448 Image
2449 *image;
2450
2451 int
2452 ac,
2453 n;
2454
2455 jmp_buf
2456 error_jmp;
2457
2458 register char
2459 **p;
2460
2461 register int
2462 i;
2463
2464 struct PackageInfo
2465 *info;
2466
2467 STRLEN
2468 *length;
2469
2470 SV
2471 *reference,
2472 *rv,
2473 *sv;
2474
2475 volatile int
2476 number_images;
2477
2478 dMY_CXT;
2479 MY_CXT.error_list=newSVpv("",0);
2480 number_images=0;
2481 ac=(items < 2) ? 1 : items-1;
2482 list=MagickAllocateMemory(char **,(ac+1)*sizeof(*list));
2483 length=MagickAllocateMemory(STRLEN *,(ac+1)*sizeof(length));
2484 if (!sv_isobject(ST(0)))
2485 {
2486 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
2487 goto ReturnIt;
2488 }
2489 reference=SvRV(ST(0));
2490 hv=SvSTASH(reference);
2491 if (SvTYPE(reference) != SVt_PVAV)
2492 {
2493 MagickError(OptionError,ReferenceIsNotMyType,NULL);
2494 goto ReturnIt;
2495 }
2496 av=(AV *) reference;
2497 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL);
2498 n=1;
2499 if (items <= 1)
2500 {
2501 MagickError(OptionError,NoBlobDefined,NULL);
2502 goto ReturnIt;
2503 }
2504 for (n=0, i=0; i < ac; i++)
2505 {
2506 list[n]=(char *) (SvPV(ST(i+1),length[n]));
2507 if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2508 {
2509 list[n]=(char *) (SvPV(ST(i+2),length[n]));
2510 continue;
2511 }
2512 n++;
2513 }
2514 list[n]=(char *) NULL;
2515 keep=list;
2516 MY_CXT.error_jump=(&error_jmp);
2517 if (setjmp(error_jmp))
2518 goto ReturnIt;
2519 GetExceptionInfo(&exception);
2520 for (i=number_images=0; i < n; i++)
2521 {
2522 image=BlobToImage(info->image_info,list[i],length[i],&exception);
2523 if (exception.severity != UndefinedException)
2524 CatchException(&exception);
2525 for ( ; image; image=image->next)
2526 {
2527 sv=newSViv((IV) (magick_uintptr_t)image);
2528 rv=newRV(sv);
2529 av_push(av,sv_bless(rv,hv));
2530 SvREFCNT_dec(sv);
2531 number_images++;
2532 }
2533 }
2534 DestroyExceptionInfo(&exception);
2535 /*
2536 Free resources.
2537 */
2538 for (i=0; i < n; i++)
2539 if (list[i])
2540 for (p=keep; list[i] != *p++; )
2541 if (*p == NULL)
2542 {
2543 MagickFreeMemory(list[i]);
2544 break;
2545 }
2546
2547 ReturnIt:
2548 MagickFreeMemory(list);
2549 MagickFreeMemory(length);
2550 sv_setiv(MY_CXT.error_list,(IV) number_images);
2551 SvPOK_on(MY_CXT.error_list);
2552 ST(0)=sv_2mortal(MY_CXT.error_list);
2553 MY_CXT.error_list=NULL;
2554 MY_CXT.error_jump=NULL;
2555 XSRETURN(1);
2556 }
2557
2558 #
2559 ###############################################################################
2560 # #
2561 # #
2562 # #
2563 # C o a l e s c e #
2564 # #
2565 # #
2566 # #
2567 ###############################################################################
2568 #
2569 #
2570 void
Coalesce(ref)2571 Coalesce(ref)
2572 Graphics::Magick ref=NO_INIT
2573 ALIAS:
2574 CoalesceImage = 1
2575 coalesce = 2
2576 coalesceimage = 3
2577 PPCODE:
2578 {
2579 AV
2580 *av;
2581
2582 ExceptionInfo
2583 exception;
2584
2585 HV
2586 *hv;
2587
2588 jmp_buf
2589 error_jmp;
2590
2591 Image
2592 *image;
2593
2594 struct PackageInfo
2595 *info;
2596
2597 SV
2598 *av_reference,
2599 *reference,
2600 *rv,
2601 *sv;
2602
2603 volatile int
2604 status;
2605
2606 dMY_CXT;
2607 MY_CXT.error_list=newSVpv("",0);
2608 status=0;
2609 if (!sv_isobject(ST(0)))
2610 {
2611 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
2612 goto MethodException;
2613 }
2614 reference=SvRV(ST(0));
2615 hv=SvSTASH(reference);
2616 av=newAV();
2617 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2618 SvREFCNT_dec(av);
2619 MY_CXT.error_jump=(&error_jmp);
2620 status=setjmp(error_jmp);
2621 if (status)
2622 goto MethodException;
2623 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
2624 if (!image)
2625 {
2626 MagickError(OptionError,NoImagesDefined,NULL);
2627 goto MethodException;
2628 }
2629 GetExceptionInfo(&exception);
2630 image=CoalesceImages(image,&exception);
2631 if (exception.severity != UndefinedException)
2632 CatchException(&exception);
2633 DestroyExceptionInfo(&exception);
2634 for ( ; image; image=image->next)
2635 {
2636 sv=newSViv((IV) (magick_uintptr_t)image);
2637 rv=newRV(sv);
2638 av_push(av,sv_bless(rv,hv));
2639 SvREFCNT_dec(sv);
2640 }
2641 ST(0)=av_reference;
2642 MY_CXT.error_jump=NULL;
2643 SvREFCNT_dec(MY_CXT.error_list);
2644 MY_CXT.error_list=NULL;
2645 XSRETURN(1);
2646
2647 MethodException:
2648 sv_setiv(MY_CXT.error_list,(IV) (status ? status : SvCUR(MY_CXT.error_list) != 0));
2649 SvPOK_on(MY_CXT.error_list);
2650 ST(0)=sv_2mortal(MY_CXT.error_list);
2651 MY_CXT.error_list=NULL;
2652 MY_CXT.error_jump=NULL;
2653 XSRETURN(1);
2654 }
2655
2656 #
2657 ###############################################################################
2658 # #
2659 # #
2660 # #
2661 # C o p y #
2662 # #
2663 # #
2664 # #
2665 ###############################################################################
2666 #
2667 #
2668 void
Copy(ref)2669 Copy(ref)
2670 Graphics::Magick ref=NO_INIT
2671 ALIAS:
2672 CopyImage = 1
2673 copy = 2
2674 copyimage = 3
2675 CloneImage = 4
2676 clone = 5
2677 cloneimage = 6
2678 Clone = 7
2679 PPCODE:
2680 {
2681 AV
2682 *av;
2683
2684 ExceptionInfo
2685 exception;
2686
2687 HV
2688 *hv;
2689
2690 Image
2691 *clone,
2692 *image;
2693
2694 jmp_buf
2695 error_jmp;
2696
2697 struct PackageInfo
2698 *info;
2699
2700 SV
2701 *reference,
2702 *rv,
2703 *sv;
2704
2705 volatile int
2706 status;
2707
2708 dMY_CXT;
2709 MY_CXT.error_list=newSVpv("",0);
2710 status=0;
2711 if (!sv_isobject(ST(0)))
2712 {
2713 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
2714 goto MethodException;
2715 }
2716 reference=SvRV(ST(0));
2717 hv=SvSTASH(reference);
2718 MY_CXT.error_jump=(&error_jmp);
2719 status=setjmp(error_jmp);
2720 if (status)
2721 goto MethodException;
2722 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
2723 if (image == (Image *) NULL)
2724 {
2725 MagickError(OptionError,NoImagesDefined,NULL);
2726 goto MethodException;
2727 }
2728 /*
2729 Create blessed Perl array for the returned image.
2730 */
2731 av=newAV();
2732 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2733 SvREFCNT_dec(av);
2734 GetExceptionInfo(&exception);
2735 for ( ; image; image=image->next)
2736 {
2737 clone=CloneImage(image,0,0,True,&exception);
2738 if (exception.severity != UndefinedException)
2739 CatchException(&exception);
2740 sv=newSViv((IV) (magick_uintptr_t)clone);
2741 rv=newRV(sv);
2742 av_push(av,sv_bless(rv,hv));
2743 SvREFCNT_dec(sv);
2744 }
2745 DestroyExceptionInfo(&exception);
2746 info=GetPackageInfo(aTHX_ (void *) av,info);
2747 SvREFCNT_dec(MY_CXT.error_list);
2748 MY_CXT.error_jump=NULL;
2749 XSRETURN(1);
2750
2751 MethodException:
2752 sv_setiv(MY_CXT.error_list,(IV) (status ? status : SvCUR(MY_CXT.error_list) != 0));
2753 SvPOK_on(MY_CXT.error_list);
2754 ST(0)=sv_2mortal(MY_CXT.error_list);
2755 MY_CXT.error_list=NULL;
2756 MY_CXT.error_jump=NULL;
2757 XSRETURN(1);
2758 }
2759
2760 #
2761 ###############################################################################
2762 # #
2763 # #
2764 # #
2765 # D e s t r o y #
2766 # #
2767 # #
2768 # #
2769 ###############################################################################
2770 #
2771 #
2772 void
DESTROY(ref)2773 DESTROY(ref)
2774 Graphics::Magick ref=NO_INIT
2775 PPCODE:
2776 {
2777 SV
2778 *reference;
2779
2780 if (!sv_isobject(ST(0)))
2781 croak("ReferenceIsNotMyType");
2782 reference=SvRV(ST(0));
2783 switch (SvTYPE(reference))
2784 {
2785 case SVt_PVAV:
2786 {
2787 char
2788 message[MaxTextExtent];
2789
2790 struct PackageInfo
2791 *info;
2792
2793 SV
2794 *sv;
2795
2796 /*
2797 Array (AV *) reference
2798 */
2799 FormatString(message,"%s::Ref%lx_%s",PackageName,(long) reference,
2800 XS_VERSION);
2801 sv=perl_get_sv(message,FALSE);
2802 if (sv)
2803 {
2804 if ((SvREFCNT(sv) == 1) && SvIOK(sv) &&
2805 (info=(struct PackageInfo *) (magick_uintptr_t)SvIV(sv)))
2806 {
2807 DestroyPackageInfo(info);
2808 sv_setiv(sv,0);
2809 }
2810 }
2811 break;
2812 }
2813 case SVt_PVMG:
2814 {
2815 Image
2816 *image;
2817
2818 /*
2819 Blessed scalar = (Image *) SvIV(reference)
2820 */
2821 image=(Image *) (magick_uintptr_t)SvIV(reference);
2822 if (image)
2823 {
2824 if (image->previous && image->previous->next == image)
2825 image->previous->next=0;
2826 if (image->next && image->next->previous == image)
2827 image->next->previous=0;
2828 DestroyImage(image);
2829 sv_setiv(reference,0);
2830 }
2831 break;
2832 }
2833 default:
2834 break;
2835 }
2836 }
2837
2838 #
2839 ###############################################################################
2840 # #
2841 # #
2842 # #
2843 # D i s p l a y #
2844 # #
2845 # #
2846 # #
2847 ###############################################################################
2848 #
2849 #
2850 void
Display(ref,...)2851 Display(ref,...)
2852 Graphics::Magick ref=NO_INIT
2853 ALIAS:
2854 DisplayImage = 1
2855 display = 2
2856 displayimage = 3
2857 PPCODE:
2858 {
2859 jmp_buf
2860 error_jmp;
2861
2862 Image
2863 *image;
2864
2865 register int
2866 i;
2867
2868 struct PackageInfo
2869 *info,
2870 *package_info;
2871
2872 SV
2873 *reference;
2874
2875 volatile int
2876 status;
2877
2878 dMY_CXT;
2879 MY_CXT.error_list=newSVpv("",0);
2880 status=0;
2881 package_info=(struct PackageInfo *) NULL;
2882 if (!sv_isobject(ST(0)))
2883 {
2884 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
2885 goto MethodException;
2886 }
2887 reference=SvRV(ST(0));
2888 MY_CXT.error_jump=(&error_jmp);
2889 status=setjmp(error_jmp);
2890 if (status)
2891 goto MethodException;
2892 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
2893 if (image == (Image *) NULL)
2894 {
2895 MagickError(OptionError,NoImagesDefined,NULL);
2896 goto MethodException;
2897 }
2898 package_info=ClonePackageInfo(info);
2899 if (items == 2)
2900 SetAttribute(aTHX_ package_info,NULL,"server",ST(1));
2901 else
2902 if (items > 2)
2903 for (i=2; i < items; i+=2)
2904 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i));
2905 DisplayImages(package_info->image_info,image);
2906 (void) CatchImageException(image);
2907
2908 MethodException:
2909 if (package_info)
2910 DestroyPackageInfo(package_info);
2911 sv_setiv(MY_CXT.error_list,(IV) status);
2912 SvPOK_on(MY_CXT.error_list);
2913 ST(0)=sv_2mortal(MY_CXT.error_list);
2914 MY_CXT.error_list=NULL;
2915 MY_CXT.error_jump=NULL;
2916 XSRETURN(1);
2917 }
2918
2919 #
2920 ###############################################################################
2921 # #
2922 # #
2923 # #
2924 # F l a t t e n #
2925 # #
2926 # #
2927 # #
2928 ###############################################################################
2929 #
2930 #
2931 void
Flatten(ref)2932 Flatten(ref)
2933 Graphics::Magick ref=NO_INIT
2934 ALIAS:
2935 FlattenImage = 1
2936 flatten = 2
2937 flattenimage = 3
2938 PPCODE:
2939 {
2940 AV
2941 *av;
2942
2943 char
2944 *p;
2945
2946 ExceptionInfo
2947 exception;
2948
2949 HV
2950 *hv;
2951
2952 jmp_buf
2953 error_jmp;
2954
2955 Image
2956 *image;
2957
2958 struct PackageInfo
2959 *info;
2960
2961 SV
2962 *reference,
2963 *rv,
2964 *sv;
2965
2966 volatile int
2967 status;
2968
2969 dMY_CXT;
2970 MY_CXT.error_list=newSVpv("",0);
2971 status=0;
2972 if (!sv_isobject(ST(0)))
2973 {
2974 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
2975 goto MethodException;
2976 }
2977 reference=SvRV(ST(0));
2978 hv=SvSTASH(reference);
2979 MY_CXT.error_jump=(&error_jmp);
2980 status=setjmp(error_jmp);
2981 if (status)
2982 goto MethodException;
2983 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
2984 if (!image)
2985 {
2986 MagickError(OptionError,NoImagesDefined,NULL);
2987 goto MethodException;
2988 }
2989 GetExceptionInfo(&exception);
2990 image=FlattenImages(image,&exception);
2991 if (exception.severity != UndefinedException)
2992 CatchException(&exception);
2993 DestroyExceptionInfo(&exception);
2994 /*
2995 Create blessed Perl array for the returned image.
2996 */
2997 av=newAV();
2998 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2999 SvREFCNT_dec(av);
3000 sv=newSViv((IV) (magick_uintptr_t)image);
3001 rv=newRV(sv);
3002 av_push(av,sv_bless(rv,hv));
3003 SvREFCNT_dec(sv);
3004 info=GetPackageInfo(aTHX_ (void *) av,info);
3005 FormatString(info->image_info->filename,"average-%.*s",MaxTextExtent-9,
3006 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3007 (void) strncpy(image->filename,info->image_info->filename,MaxTextExtent-1);
3008 SetImageInfo(info->image_info,SETMAGICK_WRITE,&image->exception);
3009 SvREFCNT_dec(MY_CXT.error_list);
3010 MY_CXT.error_jump=NULL;
3011 XSRETURN(1);
3012
3013 MethodException:
3014 sv_setiv(MY_CXT.error_list,(IV) (status ? status : SvCUR(MY_CXT.error_list) != 0));
3015 SvPOK_on(MY_CXT.error_list); /* return messages in string context */
3016 ST(0)=sv_2mortal(MY_CXT.error_list);
3017 MY_CXT.error_list=NULL;
3018 MY_CXT.error_jump=NULL;
3019 XSRETURN(1);
3020 }
3021
3022 #
3023 ###############################################################################
3024 # #
3025 # #
3026 # #
3027 # G e t #
3028 # #
3029 # #
3030 # #
3031 ###############################################################################
3032 #
3033 #
3034 void
Get(ref,...)3035 Get(ref,...)
3036 Graphics::Magick ref=NO_INIT
3037 ALIAS:
3038 GetAttributes = 1
3039 GetAttribute = 2
3040 get = 3
3041 getattributes = 4
3042 getattribute = 5
3043 PPCODE:
3044 {
3045 char
3046 *attribute,
3047 color[MaxTextExtent];
3048
3049 const ImageAttribute
3050 *image_attribute;
3051
3052 Image
3053 *image;
3054
3055 const unsigned char *
3056 profile_info;
3057
3058 size_t
3059 profile_length;
3060
3061 int
3062 j;
3063
3064 register int
3065 i;
3066
3067 struct PackageInfo
3068 *info;
3069
3070 SV
3071 *reference,
3072 *s;
3073
3074 if (!sv_isobject(ST(0)))
3075 {
3076 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
3077 XSRETURN_EMPTY;
3078 }
3079 reference=SvRV(ST(0));
3080 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
3081 if (!image && !info)
3082 {
3083 MagickError(OptionError,ReferenceIsNotMyType,NULL);
3084 XSRETURN_EMPTY;
3085 }
3086 EXTEND(sp,items);
3087 for (i=1; i < items; i++)
3088 {
3089 attribute=(char *) SvPV(ST(i),na);
3090 s=NULL;
3091 switch (*attribute)
3092 {
3093 case 'A':
3094 case 'a':
3095 {
3096 if (LocaleCompare(attribute,"adjoin") == 0)
3097 {
3098 if (info)
3099 s=newSViv((long) info->image_info->adjoin);
3100 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3101 continue;
3102 }
3103 if (LocaleCompare(attribute,"antialias") == 0)
3104 {
3105 if (info)
3106 s=newSViv((long) info->image_info->antialias);
3107 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3108 continue;
3109 }
3110 if (LocaleCompare(attribute,"authenticate") == 0)
3111 {
3112 if (info)
3113 s=newSVpv(info->image_info->authenticate,0);
3114 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3115 continue;
3116 }
3117 MagickError(OptionError,UnrecognizedAttribute,attribute);
3118 break;
3119 }
3120 case 'B':
3121 case 'b':
3122 {
3123 if (LocaleCompare(attribute,"background") == 0)
3124 {
3125 if (!image)
3126 break;
3127 FormatString(color,"%u,%u,%u,%u",image->background_color.red,
3128 image->background_color.green,image->background_color.blue,
3129 image->background_color.opacity);
3130 s=newSVpv(color,0);
3131 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3132 continue;
3133 }
3134 if (LocaleCompare(attribute,"base-columns") == 0)
3135 {
3136 if (image)
3137 s=newSViv((long) image->magick_columns);
3138 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3139 continue;
3140 }
3141 if (LocaleCompare(attribute,"base-filename") == 0)
3142 {
3143 if (image)
3144 s=newSVpv(image->magick_filename,0);
3145 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3146 continue;
3147 }
3148 if (LocaleCompare(attribute,"base-height") == 0)
3149 {
3150 if (image)
3151 s=newSViv((long) image->magick_rows);
3152 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3153 continue;
3154 }
3155 if (LocaleCompare(attribute,"base-rows") == 0)
3156 {
3157 if (image)
3158 s=newSViv((long) image->magick_rows);
3159 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3160 continue;
3161 }
3162 if (LocaleCompare(attribute,"base-width") == 0)
3163 {
3164 if (image)
3165 s=newSViv((long) image->magick_columns);
3166 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3167 continue;
3168 }
3169 if (LocaleCompare(attribute,"blue-primary") == 0)
3170 {
3171 if (!image)
3172 break;
3173 FormatString(color,"%g,%g",image->chromaticity.blue_primary.x,
3174 image->chromaticity.blue_primary.y);
3175 s=newSVpv(color,0);
3176 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3177 continue;
3178 }
3179 if (LocaleCompare(attribute,"bordercolor") == 0)
3180 {
3181 if (!image)
3182 break;
3183 FormatString(color,"%u,%u,%u,%u",image->border_color.red,
3184 image->border_color.green,image->border_color.blue,
3185 image->border_color.opacity);
3186 s=newSVpv(color,0);
3187 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3188 continue;
3189 }
3190 MagickError(OptionError,UnrecognizedAttribute,attribute);
3191 break;
3192 }
3193 case 'C':
3194 case 'c':
3195 {
3196 if (LocaleCompare(attribute,"class") == 0)
3197 {
3198 if (!image)
3199 break;
3200 #if defined(__cplusplus) || defined(c_plusplus)
3201 j=image->c_class;
3202 #else
3203 j=image->storage_class;
3204 #endif
3205 s=newSViv(j);
3206 if ((j >= 0) && (j < (long) NumberOf(ClassTypes)-1))
3207 {
3208 (void) sv_setpv(s,ClassTypes[j]);
3209 SvIOK_on(s);
3210 }
3211 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3212 continue;
3213 }
3214 if (LocaleCompare(attribute,"clip-mask") == 0)
3215 {
3216 if (image)
3217 {
3218 SV
3219 *sv;
3220
3221 if (GetImageClipMask(image,&image->exception) == (Image *) NULL)
3222 ClipImage(image);
3223 sv=newSViv((IV) (magick_uintptr_t)GetImageClipMask(image,&image->exception));
3224 s=sv_bless(newRV(sv),SvSTASH(reference));
3225 }
3226 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3227 continue;
3228 }
3229 if (LocaleCompare(attribute,"compression") == 0)
3230 {
3231 j=info ? info->image_info->compression : image->compression;
3232 if (info)
3233 if (info->image_info->compression == UndefinedCompression)
3234 j=image->compression;
3235 s=newSViv(j);
3236 if ((j >= 0) && (j < (long) NumberOf(CompressionTypes)-1))
3237 {
3238 (void) sv_setpv(s,CompressionTypes[j]);
3239 SvIOK_on(s);
3240 }
3241 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3242 continue;
3243 }
3244 if (LocaleCompare(attribute,"colorspace") == 0)
3245 {
3246 j=image ? image->colorspace : RGBColorspace;
3247 s=newSViv(j);
3248 if ((j >= 0) && (j < (long) NumberOf(ColorspaceTypes)-1))
3249 {
3250 (void) sv_setpv(s,ColorspaceTypes[j]);
3251 SvIOK_on(s);
3252 }
3253 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3254 continue;
3255 }
3256 if (LocaleCompare(attribute,"colors") == 0)
3257 {
3258 if (image)
3259 s=newSViv((long) GetNumberColors(image,(FILE *) NULL,
3260 &image->exception));
3261 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3262 continue;
3263 }
3264 if (LocaleNCompare(attribute,"colormap",8) == 0)
3265 {
3266 if (!image || !image->colormap)
3267 break;
3268 j=0;
3269 (void) sscanf(attribute,"%*[^[][%d",&j);
3270 if (j > (long) image->colors)
3271 j%=image->colors;
3272 FormatString(color,"%u,%u,%u,%u",image->colormap[j].red,
3273 image->colormap[j].green,image->colormap[j].blue,
3274 image->colormap[j].opacity);
3275 s=newSVpv(color,0);
3276 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3277 continue;
3278 }
3279 if (LocaleCompare(attribute,"columns") == 0)
3280 {
3281 if (image)
3282 s=newSViv((long) image->columns);
3283 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3284 continue;
3285 }
3286 if (LocaleCompare(attribute,"comment") == 0)
3287 {
3288 const ImageAttribute
3289 *attribute;
3290
3291 attribute=GetImageAttribute(image,"comment");
3292 if (attribute != (ImageAttribute *) NULL)
3293 s=newSVpv(attribute->value,0);
3294 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3295 continue;
3296 }
3297 MagickError(OptionError,UnrecognizedAttribute,attribute);
3298 break;
3299 }
3300 case 'D':
3301 case 'd':
3302 {
3303 if (LocaleCompare(attribute,"density") == 0)
3304 {
3305 char
3306 geometry[MaxTextExtent];
3307
3308 if (!image)
3309 break;
3310 FormatString(geometry,"%gx%g",image->x_resolution,
3311 image->y_resolution);
3312 s=newSVpv(geometry,0);
3313 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3314 continue;
3315 }
3316 if (LocaleCompare(attribute,"dispose") == 0)
3317 {
3318 if (!image)
3319 break;
3320
3321 j=image->dispose;
3322 s=newSViv(j);
3323 if ((j >= 0) && (j < (long) NumberOf(DisposeTypes)-1))
3324 {
3325 (void) sv_setpv(s,DisposeTypes[j]);
3326 SvIOK_on(s);
3327 }
3328 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3329 continue;
3330 }
3331 if (LocaleCompare(attribute,"delay") == 0)
3332 {
3333 if (image)
3334 s=newSViv((long) image->delay);
3335 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3336 continue;
3337 }
3338 if (LocaleCompare(attribute,"depth") == 0)
3339 {
3340 if (info)
3341 s=newSViv((long) info->image_info->depth);
3342 if (image)
3343 s=newSViv((long) GetImageDepth(image,&image->exception));
3344 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3345 continue;
3346 }
3347 if (LocaleCompare(attribute,"dither") == 0)
3348 {
3349 if (info)
3350 s=newSViv((long) info->image_info->dither);
3351 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3352 continue;
3353 }
3354 if (LocaleCompare(attribute,"display") == 0) /* same as server */
3355 {
3356 if (info && info->image_info->server_name)
3357 s=newSVpv(info->image_info->server_name,0);
3358 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3359 continue;
3360 }
3361 if (LocaleCompare(attribute,"directory") == 0)
3362 {
3363 if (image && image->directory)
3364 s=newSVpv(image->directory,0);
3365 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3366 continue;
3367 }
3368 MagickError(OptionError,UnrecognizedAttribute,attribute);
3369 break;
3370 }
3371 case 'E':
3372 case 'e':
3373 {
3374 if (LocaleCompare(attribute,"endian") == 0)
3375 {
3376 j=info ? info->image_info->endian : image->endian;
3377 s=newSViv(j);
3378 if ((j >= 0) && (j < (long) NumberOf(EndianTypes)-1))
3379 {
3380 (void) sv_setpv(s,EndianTypes[j]);
3381 SvIOK_on(s);
3382 }
3383 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3384 continue;
3385 }
3386 if (LocaleCompare(attribute,"error") == 0)
3387 {
3388 if (image)
3389 s=newSVnv(image->error.mean_error_per_pixel);
3390 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3391 continue;
3392 }
3393 MagickError(OptionError,UnrecognizedAttribute,attribute);
3394 break;
3395 }
3396 case 'F':
3397 case 'f':
3398 {
3399 if (LocaleCompare(attribute,"filesize") == 0)
3400 {
3401 if (image)
3402 s=newSViv((long) GetBlobSize(image));
3403 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3404 continue;
3405 }
3406 if (LocaleCompare(attribute,"filename") == 0)
3407 {
3408 if (image)
3409 s=newSVpv(image->filename,0);
3410 else
3411 if (info && info->image_info->filename[0])
3412 s=newSVpv(info->image_info->filename,0);
3413 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3414 continue;
3415 }
3416 if (LocaleCompare(attribute,"filter") == 0)
3417 {
3418 j=image->filter;
3419 s=newSViv(j);
3420 if ((j >= 0) && (j < (long) NumberOf(FilterTypess)-1))
3421 {
3422 (void) sv_setpv(s,FilterTypess[j]);
3423 SvIOK_on(s);
3424 }
3425 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3426 continue;
3427 }
3428 if (LocaleCompare(attribute,"font") == 0)
3429 {
3430 if (info && info->image_info->font)
3431 s=newSVpv(info->image_info->font,0);
3432 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3433 continue;
3434 }
3435 if (LocaleCompare(attribute,"format") == 0)
3436 {
3437 ExceptionInfo
3438 exception;
3439
3440 const MagickInfo
3441 *magick_info;
3442
3443 magick_info=(const MagickInfo *) NULL;
3444 if (info && (*info->image_info->magick != '\0'))
3445 {
3446 GetExceptionInfo(&exception);
3447 magick_info=
3448 GetMagickInfo(info->image_info->magick,&exception);
3449 DestroyExceptionInfo(&exception);
3450 }
3451 else
3452 if (image)
3453 magick_info=GetMagickInfo(image->magick,&image->exception);
3454 if ((magick_info != (const MagickInfo *) NULL) &&
3455 (*magick_info->description != '\0'))
3456 s=newSVpv((char *) magick_info->description,0);
3457 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3458 continue;
3459 }
3460 if (LocaleCompare(attribute,"fuzz") == 0)
3461 {
3462 if (info)
3463 s=newSVnv(info->image_info->fuzz);
3464 else
3465 if (image)
3466 s=newSVnv(image->fuzz);
3467 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3468 continue;
3469 }
3470 MagickError(OptionError,UnrecognizedAttribute,attribute);
3471 break;
3472 }
3473 case 'G':
3474 case 'g':
3475 {
3476 if (LocaleCompare(attribute,"gamma") == 0)
3477 {
3478 if (image)
3479 s=newSVnv(image->gamma);
3480 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3481 continue;
3482 }
3483 if (LocaleCompare(attribute,"geometry") == 0)
3484 {
3485 if (image && image->geometry)
3486 s=newSVpv(image->geometry,0);
3487 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3488 continue;
3489 }
3490 if (LocaleCompare(attribute,"gravity") == 0)
3491 {
3492 j=image->gravity;
3493 s=newSViv(j);
3494 if ((j >= 0) && (j < (long) NumberOf(GravityTypes)-1))
3495 {
3496 (void) sv_setpv(s,GravityTypes[j]);
3497 SvIOK_on(s);
3498 }
3499 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3500 continue;
3501 }
3502 if (LocaleCompare(attribute,"green-primary") == 0)
3503 {
3504 if (!image)
3505 break;
3506 FormatString(color,"%g,%g",image->chromaticity.green_primary.x,
3507 image->chromaticity.green_primary.y);
3508 s=newSVpv(color,0);
3509 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3510 continue;
3511 }
3512 MagickError(OptionError,UnrecognizedAttribute,attribute);
3513 break;
3514 }
3515 case 'H':
3516 case 'h':
3517 {
3518 if (LocaleCompare(attribute,"height") == 0)
3519 {
3520 if (image)
3521 s=newSViv((long) image->rows);
3522 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3523 continue;
3524 }
3525 MagickError(OptionError,UnrecognizedAttribute,attribute);
3526 break;
3527 }
3528 case 'I':
3529 case 'i':
3530 {
3531 if (LocaleCompare(attribute,"icm") == 0)
3532 {
3533 if (image)
3534 {
3535 profile_info=GetImageProfile(image,"ICM",&profile_length);
3536 s=newSVpv((const char *) profile_info,profile_length);
3537 }
3538 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3539 continue;
3540 }
3541 if (LocaleCompare(attribute,"id") == 0)
3542 {
3543 if (image)
3544 s=newSViv(SetMagickRegistry(ImageRegistryType,image,0,
3545 &image->exception));
3546 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3547 continue;
3548 }
3549 if (LocaleNCompare(attribute,"index",5) == 0)
3550 {
3551 char
3552 name[MaxTextExtent];
3553
3554 const IndexPacket
3555 *indexes;
3556
3557 long
3558 x,
3559 y;
3560
3561 if (!image)
3562 break;
3563 if (image->storage_class != PseudoClass)
3564 break;
3565 x=0;
3566 y=0;
3567 (void) sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
3568 (void) AcquireImagePixels(image,(long) (x % image->columns),
3569 (long) (y % image->rows),1,1,&image->exception);
3570 indexes=AccessImmutableIndexes(image);
3571 FormatString(name,"%u",*indexes);
3572 s=newSVpv(name,0);
3573 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3574 continue;
3575 }
3576 if (LocaleCompare(attribute,"iptc") == 0)
3577 {
3578 if (image)
3579 {
3580 profile_info=GetImageProfile(image,"IPTC",&profile_length);
3581 s=newSVpv((const char *) profile_info,profile_length);
3582 }
3583 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3584 continue;
3585 }
3586 if (LocaleCompare(attribute,"iterations") == 0) /* same as loop */
3587 {
3588 if (image)
3589 s=newSViv((long) image->iterations);
3590 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3591 continue;
3592 }
3593 if (LocaleCompare(attribute,"interlace") == 0)
3594 {
3595 j=info ? info->image_info->interlace : image->interlace;
3596 s=newSViv(j);
3597 if ((j >= 0) && (j < (long) NumberOf(InterlaceTypes)-1))
3598 {
3599 (void) sv_setpv(s,InterlaceTypes[j]);
3600 SvIOK_on(s);
3601 }
3602 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3603 continue;
3604 }
3605 MagickError(OptionError,UnrecognizedAttribute,attribute);
3606 break;
3607 }
3608 case 'L':
3609 case 'l':
3610 {
3611 if (LocaleCompare(attribute,"label") == 0)
3612 {
3613 const ImageAttribute
3614 *attribute;
3615
3616 if (!image)
3617 break;
3618 attribute=GetImageAttribute(image,"label");
3619 if (attribute != (ImageAttribute *) NULL)
3620 s=newSVpv(attribute->value,0);
3621 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3622 continue;
3623 }
3624 if (LocaleCompare(attribute,"loop") == 0) /* same as iterations */
3625 {
3626 if (image)
3627 s=newSViv((long) image->iterations);
3628 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3629 continue;
3630 }
3631 MagickError(OptionError,UnrecognizedAttribute,attribute);
3632 break;
3633 }
3634 case 'M':
3635 case 'm':
3636 {
3637 if (LocaleCompare(attribute,"magick") == 0)
3638 {
3639 if (info && *info->image_info->magick)
3640 s=newSVpv(info->image_info->magick,0);
3641 else
3642 if (image)
3643 s=newSVpv(image->magick,0);
3644 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3645 continue;
3646 }
3647 if (LocaleCompare(attribute,"maximum-error") == 0)
3648 {
3649 if (image)
3650 s=newSVnv(image->error.normalized_maximum_error);
3651 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3652 continue;
3653 }
3654 if (LocaleCompare(attribute,"mean-error") == 0)
3655 {
3656 if (image)
3657 s=newSVnv(image->error.normalized_mean_error);
3658 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3659 continue;
3660 }
3661 if (LocaleCompare(attribute,"monochrome") == 0)
3662 {
3663 if (!image)
3664 continue;
3665 j=info ? info->image_info->monochrome :
3666 IsMonochromeImage(image,&image->exception);
3667 s=newSViv(j);
3668 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3669 continue;
3670 }
3671 if (LocaleCompare(attribute,"mattecolor") == 0)
3672 {
3673 if (!image)
3674 break;
3675 FormatString(color,"%u,%u,%u,%u",image->matte_color.red,
3676 image->matte_color.green,image->matte_color.blue,
3677 image->matte_color.opacity);
3678 s=newSVpv(color,0);
3679 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3680 continue;
3681 }
3682 if (LocaleCompare(attribute,"matte") == 0)
3683 {
3684 if (image)
3685 s=newSViv((long) image->matte);
3686 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3687 continue;
3688 }
3689 if (LocaleCompare(attribute,"montage") == 0)
3690 {
3691 if (image && image->montage)
3692 s=newSVpv(image->montage,0);
3693 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3694 continue;
3695 }
3696 MagickError(OptionError,UnrecognizedAttribute,attribute);
3697 break;
3698 }
3699 case 'P':
3700 case 'p':
3701 {
3702 if (LocaleCompare(attribute,"page") == 0)
3703 {
3704 if (info && info->image_info->page)
3705 s=newSVpv(info->image_info->page,0);
3706 else
3707 if (image)
3708 {
3709 char
3710 geometry[MaxTextExtent];
3711
3712 FormatString(geometry,"%lux%lu%+ld%+ld",image->page.width,
3713 image->page.height,image->page.x,image->page.y);
3714 s=newSVpv(geometry,0);
3715 }
3716 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3717 continue;
3718 }
3719 if (LocaleNCompare(attribute,"pixel",5) == 0)
3720 {
3721 char
3722 name[MaxTextExtent];
3723
3724 long
3725 x,
3726 y;
3727
3728 PixelPacket
3729 pixel;
3730
3731 if (!image)
3732 break;
3733 x=0;
3734 y=0;
3735 (void) sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
3736 (void) AcquireOnePixelByReference(image,&pixel,(long) (x % image->columns),
3737 (long) (y % image->rows),&image->exception);
3738 FormatString(name,"%u,%u,%u,%u",pixel.red,pixel.green,pixel.blue,
3739 pixel.opacity);
3740 s=newSVpv(name,0);
3741 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3742 continue;
3743 }
3744 if (LocaleCompare(attribute,"pointsize") == 0)
3745 {
3746 if (info)
3747 s=newSViv((long) info->image_info->pointsize);
3748 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3749 continue;
3750 }
3751 if (LocaleCompare(attribute,"preview") == 0)
3752 {
3753 s=newSViv(info->image_info->preview_type);
3754 if ((info->image_info->preview_type != UndefinedPreview) &&
3755 (info->image_info->preview_type < (long) NumberOf(PreviewTypes)-1))
3756 {
3757 (void) sv_setpv(s,
3758 PreviewTypes[info->image_info->preview_type]);
3759 SvIOK_on(s);
3760 }
3761 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3762 continue;
3763 }
3764 MagickError(OptionError,UnrecognizedAttribute,attribute);
3765 break;
3766 }
3767 case 'Q':
3768 case 'q':
3769 {
3770 if (LocaleCompare(attribute,"quality") == 0)
3771 {
3772 if (info)
3773 s=newSViv((long) info->image_info->quality);
3774 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3775 continue;
3776 }
3777 MagickError(OptionError,UnrecognizedAttribute,attribute);
3778 break;
3779 }
3780 case 'R':
3781 case 'r':
3782 {
3783 if (LocaleCompare(attribute,"rendering-intent") == 0)
3784 {
3785 j=image->rendering_intent;
3786 s=newSViv(j);
3787 if ((j >= 0) && (j < (long) NumberOf(IntentTypes)-1))
3788 {
3789 (void) sv_setpv(s,IntentTypes[j]);
3790 SvIOK_on(s);
3791 }
3792 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3793 continue;
3794 }
3795 if (LocaleCompare(attribute,"red-primary") == 0)
3796 {
3797 if (!image)
3798 break;
3799 FormatString(color,"%g,%g",image->chromaticity.red_primary.x,
3800 image->chromaticity.red_primary.y);
3801 s=newSVpv(color,0);
3802 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3803 continue;
3804 }
3805 if (LocaleCompare(attribute,"rows") == 0)
3806 {
3807 if (image)
3808 s=newSViv((long) image->rows);
3809 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3810 continue;
3811 }
3812 MagickError(OptionError,UnrecognizedAttribute,attribute);
3813 break;
3814 }
3815 case 'S':
3816 case 's':
3817 {
3818 if (LocaleCompare(attribute,"sampling-factor") == 0)
3819 {
3820 if (info && info->image_info->sampling_factor)
3821 s=newSVpv(info->image_info->sampling_factor,0);
3822 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3823 continue;
3824 }
3825 if (LocaleCompare(attribute,"subimage") == 0)
3826 {
3827 if (info)
3828 s=newSViv((long) info->image_info->subimage);
3829 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3830 continue;
3831 }
3832 if (LocaleCompare(attribute,"subrange") == 0)
3833 {
3834 if (info)
3835 s=newSViv((long) info->image_info->subrange);
3836 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3837 continue;
3838 }
3839 if (LocaleCompare(attribute,"server") == 0) /* same as display */
3840 {
3841 if (info && info->image_info->server_name)
3842 s=newSVpv(info->image_info->server_name,0);
3843 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3844 continue;
3845 }
3846 if (LocaleCompare(attribute,"size") == 0)
3847 {
3848 if (info && info->image_info->size)
3849 s=newSVpv(info->image_info->size,0);
3850 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3851 continue;
3852 }
3853 if (LocaleCompare(attribute,"scene") == 0)
3854 {
3855 if (image)
3856 s=newSViv((long) image->scene);
3857 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3858 continue;
3859 }
3860 if (LocaleCompare(attribute,"signature") == 0)
3861 {
3862 const ImageAttribute
3863 *attribute;
3864
3865 if (!image)
3866 break;
3867 (void) SignatureImage(image);
3868 attribute=GetImageAttribute(image,"signature");
3869 if (attribute != (ImageAttribute *) NULL)
3870 s=newSVpv(attribute->value,0);
3871 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3872 continue;
3873 }
3874 MagickError(OptionError,UnrecognizedAttribute,attribute);
3875 break;
3876 }
3877 case 'T':
3878 case 't':
3879 {
3880 if (LocaleCompare(attribute,"taint") == 0)
3881 {
3882 if (image)
3883 s=newSViv((long) IsTaintImage(image));
3884 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3885 continue;
3886 }
3887 if (LocaleCompare(attribute,"tile") == 0)
3888 {
3889 if (info && info->image_info->tile)
3890 s=newSVpv(info->image_info->tile,0);
3891 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3892 continue;
3893 }
3894 if (LocaleCompare(attribute,"texture") == 0)
3895 {
3896 if (info && info->image_info->texture)
3897 s=newSVpv(info->image_info->texture,0);
3898 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3899 continue;
3900 }
3901 if (LocaleCompare(attribute,"type") == 0)
3902 {
3903 if (!image)
3904 break;
3905 j=(long) GetImageType(image,&image->exception);
3906 s=newSViv(j);
3907 if ((j >= 0) && (j < (long) NumberOf(ImageTypes)-1))
3908 {
3909 (void) sv_setpv(s,ImageTypes[j]);
3910 SvIOK_on(s);
3911 }
3912 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3913 continue;
3914 }
3915 MagickError(OptionError,UnrecognizedAttribute,attribute);
3916 break;
3917 }
3918 case 'U':
3919 case 'u':
3920 {
3921 if (LocaleCompare(attribute,"units") == 0)
3922 {
3923 j=info ? info->image_info->units : image->units;
3924 if (info)
3925 if (info->image_info->units == UndefinedResolution)
3926 j=image->units;
3927 if (j == UndefinedResolution)
3928 s=newSVpv("undefined units",0);
3929 else
3930 if (j == PixelsPerInchResolution)
3931 s=newSVpv("pixels / inch",0);
3932 else
3933 s=newSVpv("pixels / centimeter",0);
3934 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3935 continue;
3936 }
3937 MagickError(OptionError,UnrecognizedAttribute,attribute);
3938 break;
3939 }
3940 case 'V':
3941 case 'v':
3942 {
3943 if (LocaleCompare(attribute,"verbose") == 0)
3944 {
3945 if (info)
3946 s=newSViv((long) info->image_info->verbose);
3947 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3948 continue;
3949 }
3950 if (LocaleCompare(attribute,"view") == 0)
3951 {
3952 if (info && info->image_info->view)
3953 s=newSVpv(info->image_info->view,0);
3954 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3955 continue;
3956 }
3957 if (LocaleCompare(attribute,"virtual-pixel") == 0)
3958 {
3959 if (!image)
3960 break;
3961 j=(long) GetImageVirtualPixelMethod(image);
3962 s=newSViv(j);
3963 if ((j >= 0) && (j < (long) NumberOf(VirtualPixelMethods)-1))
3964 {
3965 (void) sv_setpv(s,VirtualPixelMethods[j]);
3966 SvIOK_on(s);
3967 }
3968 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3969 continue;
3970 }
3971 MagickError(OptionError,UnrecognizedAttribute,attribute);
3972 break;
3973 }
3974 case 'W':
3975 case 'w':
3976 {
3977 if (LocaleCompare(attribute,"white-point") == 0)
3978 {
3979 if (!image)
3980 break;
3981 FormatString(color,"%g,%g",image->chromaticity.white_point.x,
3982 image->chromaticity.white_point.y);
3983 s=newSVpv(color,0);
3984 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3985 continue;
3986 }
3987 if (LocaleCompare(attribute,"width") == 0)
3988 {
3989 if (image)
3990 s=newSViv((long) image->columns);
3991 PUSHs(s ? sv_2mortal(s) : &sv_undef);
3992 continue;
3993 }
3994 MagickError(OptionError,UnrecognizedAttribute,attribute);
3995 break;
3996 }
3997 case 'X':
3998 case 'x':
3999 {
4000 if (LocaleCompare(attribute,"x-resolution") == 0)
4001 {
4002 if (image)
4003 s=newSVnv(image->x_resolution);
4004 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4005 continue;
4006 }
4007 MagickError(OptionError,UnrecognizedAttribute,attribute);
4008 break;
4009 }
4010 case 'Y':
4011 case 'y':
4012 {
4013 if (LocaleCompare(attribute,"y-resolution") == 0)
4014 {
4015 if (image)
4016 s=newSVnv(image->y_resolution);
4017 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4018 continue;
4019 }
4020 MagickError(OptionError,UnrecognizedAttribute,attribute);
4021 break;
4022 }
4023 default:
4024 {
4025 MagickError(OptionError,UnrecognizedAttribute,attribute);
4026 break;
4027 }
4028 }
4029 if (image == (Image *) NULL)
4030 MagickError(OptionError,UnrecognizedAttribute,attribute);
4031 else
4032 {
4033 image_attribute=GetImageAttribute(image,attribute);
4034 if (image_attribute == (ImageAttribute *) NULL)
4035 MagickError(OptionError,UnrecognizedAttribute,attribute);
4036 else
4037 {
4038 s=newSVpv(image_attribute->value,0);
4039 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4040 }
4041 }
4042 }
4043 }
4044
4045 #
4046 ###############################################################################
4047 # #
4048 # #
4049 # #
4050 # I m a g e T o B l o b #
4051 # #
4052 # #
4053 # #
4054 ###############################################################################
4055 #
4056 #
4057 void
ImageToBlob(ref,...)4058 ImageToBlob(ref,...)
4059 Graphics::Magick ref=NO_INIT
4060 ALIAS:
4061 ImageToBlob = 1
4062 imagetoblob = 2
4063 toblob = 3
4064 blob = 4
4065 PPCODE:
4066 {
4067 char
4068 filename[MaxTextExtent];
4069
4070 ExceptionInfo
4071 exception;
4072
4073 Image
4074 *image,
4075 *next;
4076
4077 int
4078 scene;
4079
4080 register int
4081 i;
4082
4083 jmp_buf
4084 error_jmp;
4085
4086 struct PackageInfo
4087 *info,
4088 *package_info;
4089
4090 size_t
4091 length;
4092
4093 SV
4094 *reference;
4095
4096 void
4097 *blob;
4098
4099 dMY_CXT;
4100 MY_CXT.error_list=newSVpv("",0);
4101 package_info=(struct PackageInfo *) NULL;
4102 if (!sv_isobject(ST(0)))
4103 {
4104 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
4105 goto MethodException;
4106 }
4107 reference=SvRV(ST(0));
4108 MY_CXT.error_jump=(&error_jmp);
4109 if (setjmp(error_jmp))
4110 goto MethodException;
4111 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
4112 if (!image)
4113 {
4114 MagickError(OptionError,NoImagesDefined,NULL);
4115 goto MethodException;
4116 }
4117 package_info=ClonePackageInfo(info);
4118 for (i=2; i < items; i+=2)
4119 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i));
4120 (void) strncpy(filename,package_info->image_info->filename,MaxTextExtent-1);
4121 scene=0;
4122 for (next=image; next; next=next->next)
4123 {
4124 (void) strncpy(next->filename,filename,MaxTextExtent-1);
4125 next->scene=scene++;
4126 }
4127 SetImageInfo(package_info->image_info,SETMAGICK_WRITE,&image->exception);
4128 EXTEND(sp,(long) GetImageListLength(image));
4129 GetExceptionInfo(&exception);
4130 for ( ; image; image=image->next)
4131 {
4132 length=0;
4133 blob=ImageToBlob(package_info->image_info,image,&length,&exception);
4134 if (exception.severity != UndefinedException)
4135 CatchException(&exception);
4136 if (blob != (char *) NULL)
4137 {
4138 PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
4139 MagickFreeMemory(blob);
4140 }
4141 if (package_info->image_info->adjoin)
4142 break;
4143 }
4144 DestroyExceptionInfo(&exception);
4145
4146 MethodException:
4147 if (package_info)
4148 DestroyPackageInfo(package_info);
4149 SvREFCNT_dec(MY_CXT.error_list); /* throw away all errors */
4150 MY_CXT.error_list=NULL;
4151 }
4152
4153 #
4154 ###############################################################################
4155 # #
4156 # #
4157 # #
4158 # M o g r i f y #
4159 # #
4160 # #
4161 # #
4162 ###############################################################################
4163 #
4164 #
4165 void
Mogrify(ref,...)4166 Mogrify(ref,...)
4167 Graphics::Magick ref=NO_INIT
4168 ALIAS:
4169 Comment = 1
4170 CommentImage = 2
4171 Label = 3
4172 LabelImage = 4
4173 AddNoise = 5
4174 AddNoiseImage = 6
4175 Colorize = 7
4176 ColorizeImage = 8
4177 Border = 9
4178 BorderImage = 10
4179 Blur = 11
4180 BlurImage = 12
4181 Chop = 13
4182 ChopImage = 14
4183 Crop = 15
4184 CropImage = 16
4185 Despeckle = 17
4186 DespeckleImage = 18
4187 Edge = 19
4188 EdgeImage = 20
4189 Emboss = 21
4190 EmbossImage = 22
4191 Enhance = 23
4192 EnhanceImage = 24
4193 Flip = 25
4194 FlipImage = 26
4195 Flop = 27
4196 FlopImage = 28
4197 Frame = 29
4198 FrameImage = 30
4199 Implode = 31
4200 ImplodeImage = 32
4201 Magnify = 33
4202 MagnifyImage = 34
4203 MedianFilter = 35
4204 MedianFilterImage = 36
4205 Minify = 37
4206 MinifyImage = 38
4207 OilPaint = 39
4208 OilPaintImage = 40
4209 ReduceNoise = 41
4210 ReduceNoiseImage = 42
4211 Roll = 43
4212 RollImage = 44
4213 Rotate = 45
4214 RotateImage = 46
4215 Sample = 47
4216 SampleImage = 48
4217 Scale = 49
4218 ScaleImage = 50
4219 Shade = 51
4220 ShadeImage = 52
4221 Sharpen = 53
4222 SharpenImage = 54
4223 Shear = 55
4224 ShearImage = 56
4225 Spread = 57
4226 SpreadImage = 58
4227 Swirl = 59
4228 SwirlImage = 60
4229 Resize = 61
4230 ResizeImage = 62
4231 Zoom = 63
4232 ZoomImage = 64
4233 Annotate = 65
4234 AnnotateImage = 66
4235 ColorFloodfill = 67
4236 ColorFloodfillImage= 68
4237 Composite = 69
4238 CompositeImage = 70
4239 Contrast = 71
4240 ContrastImage = 72
4241 CycleColormap = 73
4242 CycleColormapImage = 74
4243 Draw = 75
4244 DrawImage = 76
4245 Equalize = 77
4246 EqualizeImage = 78
4247 Gamma = 79
4248 GammaImage = 80
4249 Map = 81
4250 MapImage = 82
4251 MatteFloodfill = 83
4252 MatteFloodfillImage= 84
4253 Modulate = 85
4254 ModulateImage = 86
4255 Negate = 87
4256 NegateImage = 88
4257 Normalize = 89
4258 NormalizeImage = 90
4259 NumberColors = 91
4260 NumberColorsImage = 92
4261 Opaque = 93
4262 OpaqueImage = 94
4263 Quantize = 95
4264 QuantizeImage = 96
4265 Raise = 97
4266 RaiseImage = 98
4267 Segment = 99
4268 SegmentImage = 100
4269 Signature = 101
4270 SignatureImage = 102
4271 Solarize = 103
4272 SolarizeImage = 104
4273 Sync = 105
4274 SyncImage = 106
4275 Texture = 107
4276 TextureImage = 108
4277 Sans = 109
4278 SansImage = 110
4279 Transparent = 111
4280 TransparentImage = 112
4281 Threshold = 113
4282 ThresholdImage = 114
4283 Charcoal = 115
4284 CharcoalImage = 116
4285 Trim = 117
4286 TrimImage = 118
4287 Wave = 119
4288 WaveImage = 120
4289 Channel = 121
4290 ChannelImage = 122
4291 Stereo = 125
4292 StereoImage = 126
4293 Stegano = 127
4294 SteganoImage = 128
4295 Deconstruct = 129
4296 DeconstructImage = 130
4297 GaussianBlur = 131
4298 GaussianBlurImage = 132
4299 Convolve = 133
4300 ConvolveImage = 134
4301 Profile = 135
4302 ProfileImage = 136
4303 UnsharpMask = 137
4304 UnsharpMaskImage = 138
4305 MotionBlur = 139
4306 MotionBlurImage = 140
4307 OrderedDither = 141
4308 OrderedDitherImage = 142
4309 Shave = 143
4310 ShaveImage = 144
4311 Level = 145
4312 LevelImage = 146
4313 Clip = 147
4314 ClipImage = 148
4315 AffineTransform = 149
4316 AffineTransformImage = 150
4317 Compare = 151
4318 CompareImage = 152
4319 AdaptiveThreshold = 153
4320 AdaptiveThresholdImage = 154
4321 MogrifyRegion = 666
4322 PPCODE:
4323 {
4324 AffineMatrix
4325 affine,
4326 current;
4327
4328 char
4329 *attribute,
4330 /* absolute_geometry[MaxTextExtent], */
4331 attribute_flag[MaxArguments],
4332 message[MaxTextExtent],
4333 *value;
4334
4335 double
4336 angle;
4337
4338 ExceptionInfo
4339 exception;
4340
4341 FrameInfo
4342 frame_info;
4343
4344 jmp_buf
4345 error_jmp;
4346
4347 Image
4348 *image,
4349 *next,
4350 *region_image;
4351
4352 int
4353 base,
4354 flags,
4355 j,
4356 k,
4357 y;
4358
4359 PixelPacket
4360 fill_color;
4361
4362 RectangleInfo
4363 geometry,
4364 region_info;
4365
4366 register int
4367 i,
4368 x;
4369
4370 struct PackageInfo
4371 *info;
4372
4373 struct Methods
4374 *rp;
4375
4376 SV
4377 **pv,
4378 *reference,
4379 **reference_vector;
4380
4381 struct ArgumentList
4382 argument_list[MaxArguments];
4383
4384 volatile int
4385 number_images;
4386
4387 dMY_CXT;
4388 MY_CXT.error_list=newSVpv("",0);
4389 reference_vector=NULL;
4390 region_image=NULL;
4391 number_images=0;
4392 base=2;
4393 if (!sv_isobject(ST(0)))
4394 {
4395 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
4396 goto ReturnIt;
4397 }
4398 reference=SvRV(ST(0));
4399 region_info.width=0;
4400 region_info.height=0;
4401 region_info.x=0;
4402 region_info.y=0;
4403 region_image=(Image *) NULL;
4404 image=SetupList(aTHX_ reference,&info,&reference_vector);
4405 if (ix && (ix != 666))
4406 {
4407 /*
4408 Called as Method(...)
4409 */
4410 ix=(ix+1)/2;
4411 rp=(&Methods[ix-1]);
4412 attribute=rp->name;
4413 }
4414 else
4415 {
4416 /*
4417 Called as Mogrify("Method",...)
4418 */
4419 attribute=(char *) SvPV(ST(1),na);
4420 if (ix)
4421 {
4422 /*flags=*/GetImageGeometry(image,attribute,False,®ion_info);
4423 attribute=(char *) SvPV(ST(2),na);
4424 base++;
4425 }
4426 for (rp=Methods; ; rp++)
4427 {
4428 if (rp >= EndOf(Methods))
4429 {
4430 MagickError(OptionError,UnrecognizedPerlMagickMethod,attribute);
4431 goto ReturnIt;
4432 }
4433 if (strEQcase(attribute,rp->name))
4434 break;
4435 }
4436 ix=rp-Methods+1;
4437 base++;
4438 }
4439 if (!image)
4440 {
4441 MagickError(OptionError,NoImagesDefined,attribute);
4442 goto ReturnIt;
4443 }
4444 Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
4445 Zero(&attribute_flag,NumberOf(attribute_flag),char);
4446 for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
4447 {
4448 int
4449 longest;
4450
4451 Arguments
4452 *pp,
4453 *qq;
4454
4455 struct ArgumentList
4456 *al;
4457
4458 SV
4459 *sv;
4460
4461 longest=0;
4462 pp=(Arguments *) NULL;
4463 qq=rp->arguments;
4464 if (i == items)
4465 {
4466 pp=rp->arguments,
4467 sv=ST(i-1);
4468 }
4469 else
4470 for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
4471 {
4472 if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
4473 break;
4474 if (strEQcase(attribute,qq->method) > longest)
4475 {
4476 pp=qq;
4477 longest=strEQcase(attribute,qq->method);
4478 }
4479 }
4480 if (pp == (Arguments *) NULL)
4481 {
4482 MagickError(OptionError,UnrecognizedOption,attribute);
4483 goto continue_outer_loop;
4484 }
4485 al=(&argument_list[pp-rp->arguments]);
4486 if (pp->type == IntegerReference)
4487 al->int_reference=SvIV(sv);
4488 else
4489 if (pp->type == StringReference)
4490 al->string_reference=(char *) SvPV(sv,al->length);
4491 else
4492 if (pp->type == DoubleReference)
4493 al->double_reference=SvNV(sv);
4494 else
4495 if (pp->type == ImageReference)
4496 {
4497 if (!sv_isobject(sv) ||
4498 !(al->image_reference=SetupList(aTHX_ SvRV(sv),
4499 (struct PackageInfo **) NULL,(SV ***) NULL)))
4500 {
4501 MagickError(OptionError,ReferenceIsNotMyType,
4502 PackageName);
4503 goto ReturnIt;
4504 }
4505 }
4506 else
4507 if (pp->type == ArrayReference)
4508 al->array_reference=SvRV(sv);
4509 else
4510 if (!SvPOK(sv)) /* not a string; just get number */
4511 al->int_reference=SvIV(sv);
4512 else
4513 {
4514 /*
4515 Is a string; look up name.
4516 */
4517 al->int_reference=LookupStr(pp->type,SvPV(sv,na));
4518 if ((al->int_reference < 0) &&
4519 ((al->int_reference=SvIV(sv)) <= 0))
4520 {
4521 FormatString(message,"invalid %.60s value",pp->method);
4522 MagickError(OptionError,message,attribute);
4523 goto continue_outer_loop;
4524 }
4525 }
4526 attribute_flag[pp-rp->arguments]++;
4527 continue_outer_loop: ;
4528 }
4529 MY_CXT.error_jump=(&error_jmp);
4530 if (setjmp(error_jmp))
4531 goto ReturnIt;
4532 (void) memset((char *) &fill_color,0,sizeof(PixelPacket));
4533 pv=reference_vector;
4534 GetExceptionInfo(&exception);
4535 for (next=image; next; next=next->next)
4536 {
4537 image=next;
4538 SetGeometry(image,&geometry);
4539 if ((region_info.width*region_info.height) != 0)
4540 {
4541 region_image=image;
4542 image=CropImage(image,®ion_info,&exception);
4543 if (exception.severity != UndefinedException)
4544 CatchException(&exception);
4545 }
4546 switch (ix)
4547 {
4548 default:
4549 {
4550 FormatString(message,"%ld",(long) ix);
4551 MagickError(OptionError,UnrecognizedPerlMagickMethod,message);
4552 goto ReturnIt;
4553 }
4554 case 1: /* Comment */
4555 {
4556 if (!attribute_flag[0])
4557 argument_list[0].string_reference=(char *) NULL;
4558 (void) SetImageAttribute(image,"comment",(char *) NULL);
4559 (void) SetImageAttribute(image,"comment",
4560 argument_list[0].string_reference);
4561 break;
4562 }
4563 case 2: /* Label */
4564 {
4565 if (!attribute_flag[0])
4566 argument_list[0].string_reference=(char *) NULL;
4567 (void) SetImageAttribute(image,"label",(char *) NULL);
4568 (void) SetImageAttribute(image,"label",
4569 argument_list[0].string_reference);
4570 break;
4571 }
4572 case 3: /* AddNoise */
4573 {
4574 if (!attribute_flag[0])
4575 argument_list[0].int_reference=UniformNoise;
4576 image=AddNoiseImage(image,(NoiseType) argument_list[0].int_reference,
4577 &exception);
4578 break;
4579 }
4580 case 4: /* Colorize */
4581 {
4582 PixelPacket
4583 target;
4584
4585 (void) AcquireOnePixelByReference(image,&target,0,0,&exception);
4586 if (attribute_flag[0])
4587 (void) QueryColorDatabase(argument_list[0].string_reference,&target,
4588 &exception);
4589 if (!attribute_flag[1])
4590 argument_list[1].string_reference="100";
4591 image=ColorizeImage(image,argument_list[1].string_reference,target,
4592 &exception);
4593 break;
4594 }
4595 case 5: /* Border */
4596 {
4597 if (attribute_flag[0])
4598 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
4599 False,&geometry);
4600 if (attribute_flag[1])
4601 geometry.width=argument_list[1].int_reference;
4602 if (attribute_flag[2])
4603 geometry.height=argument_list[2].int_reference;
4604 if (attribute_flag[3])
4605 QueryColorDatabase(argument_list[3].string_reference,&fill_color,
4606 &exception);
4607 if (attribute_flag[4])
4608 QueryColorDatabase(argument_list[4].string_reference,&fill_color,
4609 &exception);
4610 if (attribute_flag[3] || attribute_flag[4])
4611 image->border_color=fill_color;
4612 image=BorderImage(image,&geometry,&exception);
4613 break;
4614 }
4615 case 6: /* Blur */
4616 {
4617 double
4618 radius,
4619 sigma;
4620
4621 radius=0.0;
4622 sigma=1.0;
4623 if (attribute_flag[1])
4624 radius=argument_list[1].double_reference;
4625 if (attribute_flag[2])
4626 sigma=argument_list[2].double_reference;
4627 if (attribute_flag[0])
4628 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",
4629 &radius,&sigma);
4630 image=BlurImage(image,radius,sigma,&exception);
4631 break;
4632 }
4633 case 7: /* Chop */
4634 {
4635 if (attribute_flag[0])
4636 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
4637 False,&geometry);
4638 if (attribute_flag[1])
4639 geometry.width=argument_list[1].int_reference;
4640 if (attribute_flag[2])
4641 geometry.height=argument_list[2].int_reference;
4642 if (attribute_flag[3])
4643 geometry.x=argument_list[3].int_reference;
4644 if (attribute_flag[4])
4645 geometry.y=argument_list[4].int_reference;
4646 image=ChopImage(image,&geometry,&exception);
4647 break;
4648 }
4649 case 8: /* Crop */
4650 {
4651 if (attribute_flag[0])
4652 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
4653 False,&geometry);
4654 if (attribute_flag[1])
4655 geometry.width=argument_list[1].int_reference;
4656 if (attribute_flag[2])
4657 geometry.height=argument_list[2].int_reference;
4658 if (attribute_flag[3])
4659 geometry.x=argument_list[3].int_reference;
4660 if (attribute_flag[4])
4661 geometry.y=argument_list[4].int_reference;
4662 image=CropImage(image,&geometry,&exception);
4663 break;
4664 }
4665 case 9: /* Despeckle */
4666 {
4667 image=DespeckleImage(image,&exception);
4668 break;
4669 }
4670 case 10: /* Edge */
4671 {
4672 double
4673 radius;
4674
4675 radius=0.0;
4676 if (attribute_flag[0])
4677 radius=argument_list[0].double_reference;
4678 image=EdgeImage(image,radius,&exception);
4679 break;
4680 }
4681 case 11: /* Emboss */
4682 {
4683 double
4684 radius,
4685 sigma;
4686
4687 radius=0.0;
4688 sigma=1.0;
4689 if (attribute_flag[1])
4690 radius=argument_list[1].double_reference;
4691 if (attribute_flag[2])
4692 sigma=argument_list[2].double_reference;
4693 if (attribute_flag[0])
4694 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",
4695 &radius,&sigma);
4696 image=EmbossImage(image,radius,sigma,&exception);
4697 break;
4698 }
4699 case 12: /* Enhance */
4700 {
4701 image=EnhanceImage(image,&exception);
4702 break;
4703 }
4704 case 13: /* Flip */
4705 {
4706 image=FlipImage(image,&exception);
4707 break;
4708 }
4709 case 14: /* Flop */
4710 {
4711 image=FlopImage(image,&exception);
4712 break;
4713 }
4714 case 15: /* Frame */
4715 {
4716 if (attribute_flag[0])
4717 {
4718 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
4719 False,&geometry);
4720 frame_info.width=geometry.width;
4721 frame_info.height=geometry.height;
4722 frame_info.outer_bevel=geometry.x;
4723 frame_info.inner_bevel=geometry.y;
4724 }
4725 if (attribute_flag[1])
4726 frame_info.width=argument_list[1].int_reference;
4727 if (attribute_flag[2])
4728 frame_info.height=argument_list[2].int_reference;
4729 if (attribute_flag[3])
4730 frame_info.inner_bevel=argument_list[3].int_reference;
4731 if (attribute_flag[4])
4732 frame_info.outer_bevel=argument_list[4].int_reference;
4733 if (attribute_flag[5])
4734 QueryColorDatabase(argument_list[5].string_reference,&fill_color,
4735 &exception);
4736 if (attribute_flag[6])
4737 QueryColorDatabase(argument_list[6].string_reference,&fill_color,
4738 &exception);
4739 frame_info.x=(long) frame_info.width;
4740 frame_info.y=(long) frame_info.height;
4741 frame_info.width=image->columns+2*frame_info.x;
4742 frame_info.height=image->rows+2*frame_info.y;
4743 if (attribute_flag[5] || attribute_flag[6])
4744 image->matte_color=fill_color;
4745 image=FrameImage(image,&frame_info,&exception);
4746 break;
4747 }
4748 case 16: /* Implode */
4749 {
4750 if (!attribute_flag[0])
4751 argument_list[0].double_reference=0.5;
4752 image=ImplodeImage(image,argument_list[0].double_reference,
4753 &exception);
4754 break;
4755 }
4756 case 17: /* Magnify */
4757 {
4758 image=MagnifyImage(image,&exception);
4759 break;
4760 }
4761 case 18: /* MedianFilter */
4762 {
4763 if (!attribute_flag[0])
4764 argument_list[0].double_reference=0.0;
4765 image=MedianFilterImage(image,argument_list[0].double_reference,
4766 &exception);
4767 break;
4768 }
4769 case 19: /* Minify */
4770 {
4771 image=MinifyImage(image,&exception);
4772 break;
4773 }
4774 case 20: /* OilPaint */
4775 {
4776 if (!attribute_flag[0])
4777 argument_list[0].double_reference=0.0;
4778 image=OilPaintImage(image,argument_list[0].double_reference,
4779 &exception);
4780 break;
4781 }
4782 case 21: /* ReduceNoise */
4783 {
4784 if (!attribute_flag[0])
4785 argument_list[0].double_reference=0.0;
4786 image=ReduceNoiseImage(image,argument_list[0].double_reference,
4787 &exception);
4788 break;
4789 }
4790 case 22: /* Roll */
4791 {
4792 if (attribute_flag[0])
4793 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
4794 False,&geometry);
4795 if (attribute_flag[1])
4796 geometry.x=argument_list[1].int_reference;
4797 if (attribute_flag[2])
4798 geometry.y=argument_list[2].int_reference;
4799 image=RollImage(image,geometry.x,geometry.y,&exception);
4800 break;
4801 }
4802 case 23: /* Rotate */
4803 {
4804 if (!attribute_flag[0])
4805 argument_list[0].double_reference=90.0;
4806 if (attribute_flag[1])
4807 QueryColorDatabase(argument_list[1].string_reference,
4808 &image->background_color,&exception);
4809 image=RotateImage(image,argument_list[0].double_reference,&exception);
4810 break;
4811 }
4812 case 24: /* Sample */
4813 {
4814 if (attribute_flag[0])
4815 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
4816 True,&geometry);
4817 if (attribute_flag[1])
4818 geometry.width=argument_list[1].int_reference;
4819 if (attribute_flag[2])
4820 geometry.height=argument_list[2].int_reference;
4821 image=SampleImage(image,geometry.width,geometry.height,&exception);
4822 break;
4823 }
4824 case 25: /* Scale */
4825 {
4826 if (attribute_flag[0])
4827 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
4828 True,&geometry);
4829 if (attribute_flag[1])
4830 geometry.width=argument_list[1].int_reference;
4831 if (attribute_flag[2])
4832 geometry.height=argument_list[2].int_reference;
4833 image=ScaleImage(image,geometry.width,geometry.height,&exception);
4834 break;
4835 }
4836 case 26: /* Shade */
4837 {
4838 double
4839 azimuth,
4840 elevation;
4841
4842 azimuth=30.0;
4843 if (attribute_flag[1])
4844 azimuth=argument_list[1].double_reference;
4845 elevation=30.0;
4846 if (attribute_flag[2])
4847 elevation=argument_list[2].double_reference;
4848 if (attribute_flag[0])
4849 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",&azimuth,
4850 &elevation);
4851 image=ShadeImage(image,argument_list[3].int_reference,azimuth,
4852 elevation,&exception);
4853 break;
4854 }
4855 case 27: /* Sharpen */
4856 {
4857 double
4858 radius,
4859 sigma;
4860
4861 radius=0.0;
4862 sigma=1.0;
4863 if (attribute_flag[1])
4864 radius=argument_list[1].double_reference;
4865 if (attribute_flag[2])
4866 sigma=argument_list[2].double_reference;
4867 if (attribute_flag[0])
4868 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",
4869 &radius,&sigma);
4870 image=SharpenImage(image,radius,sigma,&exception);
4871 break;
4872 }
4873 case 28: /* Shear */
4874 {
4875 double
4876 x_shear,
4877 y_shear;
4878
4879 x_shear=45.0;
4880 y_shear=45.0;
4881 if (attribute_flag[1])
4882 x_shear=argument_list[1].double_reference;
4883 if (attribute_flag[2])
4884 y_shear=argument_list[2].double_reference;
4885 if (attribute_flag[0])
4886 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",&x_shear,
4887 &y_shear);
4888 if (attribute_flag[3])
4889 QueryColorDatabase(argument_list[3].string_reference,
4890 &image->background_color,&exception);
4891 image=ShearImage(image,x_shear,y_shear,&exception);
4892 break;
4893 }
4894 case 29: /* Spread */
4895 {
4896 if (!attribute_flag[0])
4897 argument_list[0].int_reference=1;
4898 image=SpreadImage(image,argument_list[0].int_reference,&exception);
4899 break;
4900 }
4901 case 30: /* Swirl */
4902 {
4903 if (!attribute_flag[0])
4904 argument_list[0].double_reference=50.0;
4905 image=SwirlImage(image,argument_list[0].double_reference,&exception);
4906 break;
4907 }
4908 case 31: /* Resize */
4909 case 32: /* Zoom */
4910 {
4911 if (attribute_flag[0])
4912 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
4913 True,&geometry);
4914 if (attribute_flag[1])
4915 geometry.width=argument_list[1].int_reference;
4916 if (attribute_flag[2])
4917 geometry.height=argument_list[2].int_reference;
4918 if (!attribute_flag[3])
4919 argument_list[3].int_reference=(long) LanczosFilter;
4920 if (!attribute_flag[4])
4921 argument_list[4].double_reference=1.0;
4922 image=ResizeImage(image,geometry.width,geometry.height,
4923 (FilterTypes) argument_list[3].int_reference,
4924 argument_list[4].double_reference,&exception);
4925 break;
4926 }
4927 case 33: /* Annotate */
4928 {
4929 DrawInfo
4930 *draw_info;
4931
4932 draw_info=CloneDrawInfo(info ? info->image_info :
4933 (ImageInfo *) NULL,info ? info->draw_info : (DrawInfo *) NULL);
4934 if (attribute_flag[1])
4935 (void) CloneString(&draw_info->font,
4936 argument_list[1].string_reference);
4937 if (attribute_flag[2])
4938 draw_info->pointsize=argument_list[2].double_reference;
4939 if (attribute_flag[3])
4940 (void) CloneString(&draw_info->density,
4941 argument_list[3].string_reference);
4942 if (attribute_flag[0])
4943 (void) CloneString(&draw_info->text,
4944 argument_list[0].string_reference);
4945 if (attribute_flag[4])
4946 (void) QueryColorDatabase(argument_list[4].string_reference,
4947 &draw_info->undercolor,&exception);
4948 if (attribute_flag[5])
4949 (void) QueryColorDatabase(argument_list[5].string_reference,
4950 &draw_info->stroke,&exception);
4951 if (attribute_flag[6])
4952 (void) QueryColorDatabase(argument_list[6].string_reference,
4953 &draw_info->fill,&exception);
4954 if (attribute_flag[7])
4955 (void) CloneString(&draw_info->geometry,
4956 argument_list[7].string_reference);
4957 if (attribute_flag[9] || attribute_flag[10])
4958 {
4959 if (!attribute_flag[9])
4960 argument_list[9].int_reference=0;
4961 if (!attribute_flag[10])
4962 argument_list[10].int_reference=0;
4963 FormatString(message,"%+ld%+ld",argument_list[9].int_reference,
4964 argument_list[10].int_reference);
4965 (void) CloneString(&draw_info->geometry,message);
4966 }
4967 if (attribute_flag[11])
4968 draw_info->gravity=(GravityType) argument_list[11].int_reference;
4969 if (attribute_flag[25])
4970 {
4971 AV
4972 *av;
4973
4974 av=(AV *) argument_list[25].array_reference;
4975 if (av_len(av) >= 1)
4976 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
4977 if (av_len(av) >= 2)
4978 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
4979 if (av_len(av) >= 3)
4980 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
4981 if (av_len(av) >= 4)
4982 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
4983 if (av_len(av) >= 5)
4984 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
4985 if (av_len(av) >= 6)
4986 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
4987 }
4988 for (j=12; j < 17; j++)
4989 {
4990 if (!attribute_flag[j])
4991 continue;
4992 value=argument_list[j].string_reference;
4993 angle=argument_list[j].double_reference;
4994 current=draw_info->affine;
4995 IdentityAffine(&affine);
4996 switch (j)
4997 {
4998 case 12:
4999 {
5000 /*
5001 Translate.
5002 */
5003 k=sscanf(value,"%lf%*[,/]%lf",&affine.tx,&affine.ty);
5004 if (k == 1)
5005 affine.ty=affine.tx;
5006 break;
5007 }
5008 case 13:
5009 {
5010 /*
5011 Scale.
5012 */
5013 k=sscanf(value,"%lf%*[,/]%lf",&affine.sx,&affine.sy);
5014 if (k == 1)
5015 affine.sy=affine.sx;
5016 break;
5017 }
5018 case 14:
5019 {
5020 /*
5021 Rotate.
5022 */
5023 if (angle == 0.0)
5024 break;
5025 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
5026 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
5027 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
5028 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
5029 break;
5030 }
5031 case 15:
5032 {
5033 /*
5034 SkewX.
5035 */
5036 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
5037 break;
5038 }
5039 case 16:
5040 {
5041 /*
5042 SkewY.
5043 */
5044 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
5045 break;
5046 }
5047 }
5048 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
5049 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
5050 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
5051 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
5052 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
5053 current.tx;
5054 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
5055 current.ty;
5056 }
5057 if (attribute_flag[17])
5058 draw_info->stroke_width=argument_list[17].int_reference;
5059 if (attribute_flag[18])
5060 draw_info->text_antialias=argument_list[18].int_reference != 0;
5061 if (attribute_flag[19])
5062 (void) CloneString(&draw_info->family,
5063 argument_list[19].string_reference);
5064 if (attribute_flag[20])
5065 draw_info->style=(StyleType) argument_list[20].int_reference;
5066 if (attribute_flag[21])
5067 draw_info->stretch=(StretchType) argument_list[21].int_reference;
5068 if (attribute_flag[22])
5069 draw_info->weight=argument_list[22].int_reference;
5070 if (attribute_flag[23])
5071 draw_info->align=(AlignType) argument_list[23].int_reference;
5072 if (attribute_flag[24])
5073 (void) CloneString(&draw_info->encoding,
5074 argument_list[24].string_reference);
5075 if (attribute_flag[26])
5076 draw_info->decorate=(DecorationType) argument_list[26].int_reference;
5077 AnnotateImage(image,draw_info);
5078 DestroyDrawInfo(draw_info);
5079 break;
5080 }
5081 case 34: /* ColorFloodfill */
5082 {
5083 DrawInfo
5084 *draw_info;
5085
5086 PixelPacket
5087 target;
5088
5089 draw_info=CloneDrawInfo(info ? info->image_info :
5090 (ImageInfo *) NULL,info ? info->draw_info : (DrawInfo *) NULL);
5091 if (attribute_flag[0])
5092 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
5093 False,&geometry);
5094 if (attribute_flag[1])
5095 geometry.x=argument_list[1].int_reference;
5096 if (attribute_flag[2])
5097 geometry.y=argument_list[2].int_reference;
5098 if (attribute_flag[3])
5099 (void) QueryColorDatabase(argument_list[3].string_reference,
5100 &draw_info->fill,&exception);
5101 if (attribute_flag[4])
5102 QueryColorDatabase(argument_list[4].string_reference,&fill_color,
5103 &exception);
5104 (void) AcquireOnePixelByReference(image,&target,(long) (geometry.x % image->columns),
5105 (long) (geometry.y % image->rows),&exception);
5106 if (attribute_flag[4])
5107 target=fill_color;
5108 if (attribute_flag[5])
5109 image->fuzz=argument_list[5].double_reference;
5110 ColorFloodfillImage(image,draw_info,target,geometry.x,geometry.y,
5111 attribute_flag[4] ? FillToBorderMethod : FloodfillMethod);
5112 DestroyDrawInfo(draw_info);
5113 break;
5114 }
5115 case 35: /* Composite */
5116 {
5117 char
5118 composite_geometry[MaxTextExtent];
5119
5120 CompositeOperator
5121 compose;
5122
5123 double
5124 opacity;
5125
5126 Image
5127 *composite_image,
5128 *mask_image,
5129 *rotate_image;
5130
5131 compose=OverCompositeOp;
5132 if (attribute_flag[0])
5133 composite_image=argument_list[0].image_reference;
5134 else
5135 {
5136 MagickError(OptionError,CompositeImageRequired,NULL);
5137 goto ReturnIt;
5138 }
5139 if (attribute_flag[1])
5140 compose=(CompositeOperator) argument_list[1].int_reference;
5141 opacity=OpaqueOpacity;
5142 if (attribute_flag[6])
5143 {
5144 opacity=argument_list[6].double_reference;
5145 if (compose == DissolveCompositeOp)
5146 {
5147 register PixelPacket
5148 *q;
5149
5150 if (!composite_image->matte)
5151 SetImageOpacity(composite_image,OpaqueOpacity);
5152 for (y=0; y < (long) composite_image->rows; y++)
5153 {
5154 q=GetImagePixels(composite_image,0,y,
5155 composite_image->columns,1);
5156 if (q == (PixelPacket *) NULL)
5157 break;
5158 for (x=(long) composite_image->columns; x > 0; x--)
5159 {
5160 q->opacity=(Quantum) ((opacity*(MaxRGB-q->opacity))/100.0);
5161 q++;
5162 }
5163 if (!SyncImagePixels(composite_image))
5164 break;
5165 }
5166 }
5167 else
5168 {
5169 if (opacity != OpaqueOpacity)
5170 SetImageOpacity(composite_image,(unsigned int) opacity);
5171 }
5172 }
5173 if (attribute_flag[9])
5174 QueryColorDatabase(argument_list[9].string_reference,
5175 &composite_image->background_color,&exception);
5176 rotate_image=(Image *) NULL;
5177 if (attribute_flag[8])
5178 {
5179 /*
5180 Rotate image.
5181 */
5182 rotate_image=RotateImage(composite_image,
5183 argument_list[8].double_reference,&exception);
5184 if (rotate_image == (Image *) NULL)
5185 break;
5186 }
5187 if (attribute_flag[7] && argument_list[7].int_reference)
5188 {
5189 /*
5190 Tile image on background.
5191 */
5192 for (y=0; y < (long) image->rows; y+=composite_image->rows)
5193 for (x=0; x < (long) image->columns; x+=composite_image->columns)
5194 {
5195 if (attribute_flag[8])
5196 (void) CompositeImage(image,compose,rotate_image,x,y);
5197 else
5198 (void) CompositeImage(image,compose,composite_image,x,y);
5199 (void) CatchImageException(image);
5200 }
5201 if (attribute_flag[8])
5202 DestroyImage(rotate_image);
5203 break;
5204 }
5205 if (attribute_flag[2])
5206 /*flags=*/GetGeometry(argument_list[2].string_reference,&geometry.x,
5207 &geometry.y,&geometry.width,&geometry.height);
5208 if (attribute_flag[3])
5209 geometry.x=argument_list[3].int_reference;
5210 if (attribute_flag[4])
5211 geometry.y=argument_list[4].int_reference;
5212 if (attribute_flag[5])
5213 image->gravity=(GravityType) argument_list[5].int_reference;
5214 if (attribute_flag[10])
5215 {
5216 mask_image=argument_list[10].image_reference;
5217 SetImageType(composite_image,TrueColorMatteType);
5218 if (!composite_image->matte)
5219 SetImageOpacity(composite_image,OpaqueOpacity);
5220 (void) CompositeImage(composite_image,CopyOpacityCompositeOp,
5221 mask_image,0,0);
5222 }
5223 /*
5224 Composite image.
5225 */
5226 FormatString(composite_geometry,"%lux%lu%+ld%+ld",
5227 composite_image->columns,composite_image->rows,geometry.x,
5228 geometry.y);
5229 /*flags=*/GetImageGeometry(image,composite_geometry,False,&geometry);
5230 if (!attribute_flag[8])
5231 CompositeImage(image,compose,composite_image,geometry.x,geometry.y);
5232 else
5233 {
5234 /*
5235 Rotate image.
5236 */
5237 geometry.x-=(long)
5238 (rotate_image->columns-composite_image->columns)/2;
5239 geometry.y-=(long) (rotate_image->rows-composite_image->rows)/2;
5240 CompositeImage(image,compose,rotate_image,geometry.x,geometry.y);
5241 DestroyImage(rotate_image);
5242 }
5243 break;
5244 }
5245 case 36: /* Contrast */
5246 {
5247 if (!attribute_flag[0])
5248 argument_list[0].int_reference=0;
5249 ContrastImage(image,argument_list[0].int_reference);
5250 break;
5251 }
5252 case 37: /* CycleColormap */
5253 {
5254 if (!attribute_flag[0])
5255 argument_list[0].int_reference=6;
5256 CycleColormapImage(image,argument_list[0].int_reference);
5257 break;
5258 }
5259 case 38: /* Draw */
5260 {
5261 DrawInfo
5262 *draw_info;
5263
5264 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
5265 info ? info->draw_info : (DrawInfo *) NULL);
5266 draw_info->fill.opacity=TransparentOpacity;
5267 draw_info->stroke.opacity=OpaqueOpacity;
5268 (void) CloneString(&draw_info->primitive,"Point");
5269 if (attribute_flag[0] && (argument_list[0].int_reference > 0))
5270 (void) CloneString(&draw_info->primitive,
5271 PrimitiveTypes[argument_list[0].int_reference]);
5272 if (attribute_flag[1])
5273 {
5274 if (LocaleCompare(draw_info->primitive,"path") == 0)
5275 {
5276 (void) ConcatenateString(&draw_info->primitive," '");
5277 ConcatenateString(&draw_info->primitive,
5278 argument_list[1].string_reference);
5279 (void) ConcatenateString(&draw_info->primitive,"'");
5280 }
5281 else
5282 {
5283 (void) ConcatenateString(&draw_info->primitive," ");
5284 ConcatenateString(&draw_info->primitive,
5285 argument_list[1].string_reference);
5286 }
5287 }
5288 if (attribute_flag[2])
5289 {
5290 (void) ConcatenateString(&draw_info->primitive," ");
5291 (void) ConcatenateString(&draw_info->primitive,
5292 MethodTypes[argument_list[2].int_reference]);
5293 }
5294 if (attribute_flag[3])
5295 (void) QueryColorDatabase(argument_list[3].string_reference,
5296 &draw_info->stroke,&exception);
5297 if (attribute_flag[4])
5298 (void) QueryColorDatabase(argument_list[4].string_reference,
5299 &draw_info->fill,&exception);
5300 if (attribute_flag[5])
5301 draw_info->stroke_width=argument_list[5].double_reference;
5302 if (attribute_flag[6])
5303 (void) CloneString(&draw_info->font,
5304 argument_list[6].string_reference);
5305 if (attribute_flag[7])
5306 (void) QueryColorDatabase(argument_list[7].string_reference,
5307 &draw_info->border_color,&exception);
5308 if (attribute_flag[8])
5309 draw_info->affine.tx=argument_list[8].double_reference;
5310 if (attribute_flag[9])
5311 draw_info->affine.ty=argument_list[9].double_reference;
5312 if (attribute_flag[20])
5313 {
5314 AV
5315 *av;
5316
5317 av=(AV *) argument_list[20].array_reference;
5318 if (av_len(av) >= 1)
5319 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
5320 if (av_len(av) >= 2)
5321 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
5322 if (av_len(av) >= 3)
5323 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
5324 if (av_len(av) >= 4)
5325 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
5326 if (av_len(av) >= 5)
5327 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
5328 if (av_len(av) >= 6)
5329 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
5330 }
5331 for (j=10; j < 15; j++)
5332 {
5333 if (!attribute_flag[j])
5334 continue;
5335 value=argument_list[j].string_reference;
5336 angle=argument_list[j].double_reference;
5337 current=draw_info->affine;
5338 IdentityAffine(&affine);
5339 switch (j)
5340 {
5341 case 10:
5342 {
5343 /*
5344 Translate.
5345 */
5346 k=sscanf(value,"%lf%*[,/]%lf",&affine.tx,&affine.ty);
5347 if (k == 1)
5348 affine.ty=affine.tx;
5349 break;
5350 }
5351 case 11:
5352 {
5353 /*
5354 Scale.
5355 */
5356 k=sscanf(value,"%lf%*[,/]%lf",&affine.sx,&affine.sy);
5357 if (k == 1)
5358 affine.sy=affine.sx;
5359 break;
5360 }
5361 case 12:
5362 {
5363 /*
5364 Rotate.
5365 */
5366 if (angle == 0.0)
5367 break;
5368 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
5369 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
5370 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
5371 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
5372 break;
5373 }
5374 case 13:
5375 {
5376 /*
5377 SkewX.
5378 */
5379 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
5380 break;
5381 }
5382 case 14:
5383 {
5384 /*
5385 SkewY.
5386 */
5387 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
5388 break;
5389 }
5390 }
5391 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
5392 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
5393 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
5394 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
5395 draw_info->affine.tx=
5396 current.sx*affine.tx+current.ry*affine.ty+current.tx;
5397 draw_info->affine.ty=
5398 current.rx*affine.tx+current.sy*affine.ty+current.ty;
5399 }
5400 if (attribute_flag[15])
5401 draw_info->fill_pattern=
5402 CloneImage(argument_list[15].image_reference,0,0,True,&exception);
5403 if (attribute_flag[16])
5404 draw_info->pointsize=argument_list[16].double_reference;
5405 if (attribute_flag[17])
5406 {
5407 draw_info->stroke_antialias=argument_list[17].int_reference != 0;
5408 draw_info->text_antialias=argument_list[17].int_reference != 0;
5409 }
5410 if (attribute_flag[18])
5411 (void) CloneString(&draw_info->density,
5412 argument_list[18].string_reference);
5413 if (attribute_flag[19])
5414 draw_info->stroke_width=argument_list[19].double_reference;
5415 DrawImage(image,draw_info);
5416 DestroyDrawInfo(draw_info);
5417 break;
5418 }
5419 case 39: /* Equalize */
5420 {
5421 EqualizeImage(image);
5422 break;
5423 }
5424 case 40: /* Gamma */
5425 {
5426 if (!attribute_flag[1])
5427 argument_list[1].double_reference=1.0;
5428 if (!attribute_flag[2])
5429 argument_list[2].double_reference=1.0;
5430 if (!attribute_flag[3])
5431 argument_list[3].double_reference=1.0;
5432 if (!attribute_flag[0])
5433 {
5434 FormatString(message,"%g,%g,%g",
5435 argument_list[1].double_reference,
5436 argument_list[2].double_reference,
5437 argument_list[3].double_reference);
5438 argument_list[0].string_reference=message;
5439 }
5440 GammaImage(image,argument_list[0].string_reference);
5441 break;
5442 }
5443 case 41: /* Map */
5444 {
5445 if (!attribute_flag[1])
5446 argument_list[1].int_reference=1;
5447 if (!attribute_flag[0])
5448 {
5449 MagickError(OptionError,MapImageRequired,NULL);
5450 goto ReturnIt;
5451 }
5452 (void) MapImages(image,argument_list[0].image_reference,
5453 argument_list[1].int_reference);
5454 break;
5455 }
5456 case 42: /* MatteFloodfill */
5457 {
5458 PixelPacket
5459 target;
5460
5461 unsigned int
5462 opacity;
5463
5464 if (attribute_flag[0])
5465 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
5466 False,&geometry);
5467 if (attribute_flag[1])
5468 geometry.x=argument_list[1].int_reference;
5469 if (attribute_flag[2])
5470 geometry.y=argument_list[2].int_reference;
5471 if (attribute_flag[4])
5472 QueryColorDatabase(argument_list[4].string_reference,&fill_color,
5473 &exception);
5474 opacity=TransparentOpacity;
5475 if (attribute_flag[3])
5476 opacity=argument_list[3].int_reference;
5477 if (!image->matte)
5478 SetImageOpacity(image,OpaqueOpacity);
5479 (void) AcquireOnePixelByReference(image,&target,(long) (geometry.x % image->columns),
5480 (long) (geometry.y % image->rows),&exception);
5481 if (attribute_flag[4])
5482 target=fill_color;
5483 if (attribute_flag[5])
5484 image->fuzz=argument_list[5].double_reference;
5485 MatteFloodfillImage(image,target,opacity,geometry.x,geometry.y,
5486 attribute_flag[4] ? FillToBorderMethod : FloodfillMethod);
5487 break;
5488 }
5489 case 43: /* Modulate */
5490 {
5491 if (!attribute_flag[1])
5492 argument_list[1].double_reference=100.0;
5493 if (!attribute_flag[2])
5494 argument_list[2].double_reference=100.0;
5495 if (!attribute_flag[3])
5496 argument_list[3].double_reference=100.0;
5497 FormatString(message,"%g,%g,%g",
5498 argument_list[1].double_reference,
5499 argument_list[2].double_reference,
5500 argument_list[3].double_reference);
5501 if (!attribute_flag[0])
5502 argument_list[0].string_reference=message;
5503 ModulateImage(image,argument_list[0].string_reference);
5504 break;
5505 }
5506 case 44: /* Negate */
5507 {
5508 if (!attribute_flag[0])
5509 argument_list[0].int_reference=0;
5510 NegateImage(image,argument_list[0].int_reference);
5511 break;
5512 }
5513 case 45: /* Normalize */
5514 {
5515 NormalizeImage(image);
5516 break;
5517 }
5518 case 46: /* NumberColors */
5519 break;
5520 case 47: /* Opaque */
5521 {
5522 PixelPacket
5523 fill_color,
5524 target;
5525
5526 (void) AcquireOnePixelByReference(image,&target,0,0,&exception);
5527 if (attribute_flag[0])
5528 (void) QueryColorDatabase(argument_list[0].string_reference,
5529 &target,&exception);
5530 (void) AcquireOnePixelByReference(image,&fill_color,0,0,&exception);
5531 if (attribute_flag[1])
5532 (void) QueryColorDatabase(argument_list[1].string_reference,
5533 &fill_color,&exception);
5534 if (attribute_flag[2])
5535 image->fuzz=argument_list[2].double_reference;
5536 OpaqueImage(image,target,fill_color);
5537 break;
5538 }
5539 case 48: /* Quantize */
5540 {
5541 QuantizeInfo
5542 quantize_info;
5543
5544 GetQuantizeInfo(&quantize_info);
5545 quantize_info.number_colors=
5546 attribute_flag[0] ? (unsigned long) argument_list[0].int_reference :
5547 (info ? info->quantize_info->number_colors :
5548 MaxRGB + 1U);
5549 quantize_info.tree_depth=attribute_flag[1] ?
5550 (unsigned int) argument_list[1].int_reference :
5551 (info ? info->quantize_info->tree_depth : 8U);
5552 quantize_info.colorspace=(ColorspaceType)
5553 (attribute_flag[2] ? (ColorspaceType) argument_list[2].int_reference :
5554 (info? info->quantize_info->colorspace : RGBColorspace));
5555 quantize_info.dither=attribute_flag[3] ?
5556 (unsigned int) argument_list[3].int_reference :
5557 (info ? info->quantize_info->dither : False);
5558 quantize_info.measure_error=attribute_flag[4] ?
5559 (unsigned int) argument_list[4].int_reference :
5560 (info ? info->quantize_info->measure_error : False);
5561 if (attribute_flag[5] && argument_list[5].int_reference)
5562 {
5563 (void) QuantizeImages(&quantize_info,image);
5564 goto ReturnIt;
5565 }
5566 if ((image->storage_class == DirectClass) ||
5567 (image->colors > quantize_info.number_colors) ||
5568 (quantize_info.colorspace == GRAYColorspace))
5569 (void) QuantizeImage(&quantize_info,image);
5570 else
5571 CompressImageColormap(image);
5572 break;
5573 }
5574 case 49: /* Raise */
5575 {
5576 if (attribute_flag[0])
5577 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
5578 False,&geometry);
5579 if (attribute_flag[1])
5580 geometry.width=argument_list[1].int_reference;
5581 if (attribute_flag[2])
5582 geometry.height=argument_list[2].int_reference;
5583 if (!attribute_flag[3])
5584 argument_list[3].int_reference=1;
5585 RaiseImage(image,&geometry,argument_list[3].int_reference);
5586 break;
5587 }
5588 case 50: /* Segment */
5589 {
5590 ColorspaceType
5591 colorspace;
5592
5593 double
5594 cluster_threshold,
5595 smoothing_threshold;
5596
5597 unsigned int
5598 verbose;
5599
5600 cluster_threshold=1.0;
5601 smoothing_threshold=1.5;
5602 colorspace=RGBColorspace;
5603 verbose=False;
5604 if (attribute_flag[1])
5605 cluster_threshold=argument_list[1].double_reference;
5606 if (attribute_flag[2])
5607 smoothing_threshold=argument_list[2].double_reference;
5608 if (attribute_flag[0])
5609 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",
5610 &cluster_threshold,&smoothing_threshold);
5611 if (attribute_flag[3])
5612 colorspace=(ColorspaceType) argument_list[3].int_reference;
5613 if (attribute_flag[4])
5614 verbose=argument_list[4].int_reference != 0;
5615 (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
5616 smoothing_threshold);
5617 break;
5618 }
5619 case 51: /* Signature */
5620 {
5621 (void) SignatureImage(image);
5622 break;
5623 }
5624 case 52: /* Solarize */
5625 {
5626 if (!attribute_flag[0])
5627 argument_list[0].double_reference=50.0;
5628 SolarizeImage(image,argument_list[0].double_reference);
5629 break;
5630 }
5631 case 53: /* Sync */
5632 {
5633 (void) SyncImage(image);
5634 break;
5635 }
5636 case 54: /* Texture */
5637 {
5638 if (!attribute_flag[0])
5639 break;
5640 TextureImage(image,argument_list[0].image_reference);
5641 break;
5642 }
5643 case 55: /* Sans */
5644 break;
5645 case 56: /* Transparent */
5646 {
5647 PixelPacket
5648 target;
5649
5650 unsigned int
5651 opacity;
5652
5653 (void) AcquireOnePixelByReference(image,&target,0,0,&exception);
5654 if (attribute_flag[0])
5655 (void) QueryColorDatabase(argument_list[0].string_reference,
5656 &target,&exception);
5657 opacity=TransparentOpacity;
5658 if (attribute_flag[1])
5659 opacity=argument_list[1].int_reference;
5660 if (attribute_flag[2])
5661 image->fuzz=argument_list[2].double_reference;
5662 TransparentImage(image,target,opacity);
5663 break;
5664 }
5665 case 57: /* Threshold */
5666 {
5667 double
5668 threshold;
5669
5670 int
5671 count;
5672
5673 if (!attribute_flag[0])
5674 argument_list[0].string_reference="50%";
5675 count=sscanf(argument_list[0].string_reference,"%lf",&threshold);
5676 if (count > 0)
5677 {
5678 if (strchr(argument_list[0].string_reference,'%') != (char *) NULL)
5679 threshold *= MaxRGB/100.0;
5680 (void) ThresholdImage(image,threshold);
5681 }
5682 break;
5683 }
5684 case 58: /* Charcoal */
5685 {
5686 double
5687 radius,
5688 sigma;
5689
5690 radius=0.0;
5691 sigma=1.0;
5692 if (attribute_flag[1])
5693 radius=argument_list[1].double_reference;
5694 if (attribute_flag[2])
5695 sigma=argument_list[2].double_reference;
5696 if (attribute_flag[0])
5697 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",
5698 &radius,&sigma);
5699 image=CharcoalImage(image,radius,sigma,&exception);
5700 break;
5701 }
5702 case 59: /* Trim */
5703 {
5704 if (attribute_flag[0])
5705 image->fuzz=argument_list[0].double_reference;
5706 /*flags=*/GetGeometry("0x0",&geometry.x,&geometry.y,
5707 &geometry.width,&geometry.height);
5708 image=CropImage(image,&geometry,&exception);
5709 break;
5710 }
5711 case 60: /* Wave */
5712 {
5713 double
5714 amplitude,
5715 wavelength;
5716
5717 amplitude=25.0;
5718 wavelength=150.0;
5719 if (attribute_flag[1])
5720 amplitude=argument_list[1].double_reference;
5721 if (attribute_flag[2])
5722 wavelength=argument_list[2].double_reference;
5723 if (attribute_flag[0])
5724 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",
5725 &litude,&wavelength);
5726 image=WaveImage(image,amplitude,wavelength,&exception);
5727 break;
5728 }
5729 case 61: /* Channel */
5730 {
5731 if (!attribute_flag[0])
5732 argument_list[0].int_reference=1;
5733 ChannelImage(image,(ChannelType) argument_list[0].int_reference);
5734 break;
5735 }
5736 case 63: /* Stereo */
5737 {
5738 if (!attribute_flag[0])
5739 {
5740 MagickError(OptionError,StereoImageRequired,NULL);
5741 goto ReturnIt;
5742 }
5743 image=StereoImage(image,argument_list[0].image_reference,&exception);
5744 break;
5745 }
5746 case 64: /* Stegano */
5747 {
5748 if (!attribute_flag[1])
5749 argument_list[1].int_reference=0;
5750 if (!attribute_flag[0])
5751 {
5752 MagickError(OptionError,SteganoImageRequired,NULL);
5753 goto ReturnIt;
5754 }
5755 image->offset=argument_list[1].int_reference;
5756 image=SteganoImage(image,argument_list[0].image_reference,&exception);
5757 break;
5758 }
5759 case 65: /* Deconstruct */
5760 {
5761 image=DeconstructImages(image,&exception);
5762 break;
5763 }
5764 case 66: /* GaussianBlur */
5765 {
5766 double
5767 radius,
5768 sigma;
5769
5770 radius=0.0;
5771 sigma=1.0;
5772 if (attribute_flag[1])
5773 radius=argument_list[1].double_reference;
5774 if (attribute_flag[2])
5775 sigma=argument_list[2].double_reference;
5776 if (attribute_flag[0])
5777 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",
5778 &radius,&sigma);
5779 image=GaussianBlurImage(image,radius,sigma,&exception);
5780 break;
5781 }
5782 case 67: /* Convolve */
5783 {
5784 AV
5785 *av;
5786
5787 double
5788 *kernel;
5789
5790 unsigned int
5791 radius;
5792
5793 if (!attribute_flag[0])
5794 break;
5795 av=(AV *) argument_list[0].array_reference;
5796 radius=(unsigned int) sqrt(av_len(av)+1);
5797 kernel=MagickAllocateMemory(double *,radius*radius*sizeof(double));
5798 for (j=0; j < (av_len(av)+1); j++)
5799 kernel[j]=(double) SvNV(*(av_fetch(av,j,0)));
5800 for ( ; j < (long) (radius*radius); j++)
5801 kernel[j]=0.0;
5802 image=ConvolveImage(image,radius,kernel,&exception);
5803 MagickFreeMemory(kernel);
5804 break;
5805 }
5806 case 68: /* Profile */
5807 {
5808 if (!attribute_flag[0])
5809 argument_list[0].string_reference="*";
5810 if (!attribute_flag[1])
5811 argument_list[1].string_reference=(char *) NULL;
5812 (void) ProfileImage(image,argument_list[0].string_reference,
5813 (unsigned char *) argument_list[1].string_reference,
5814 argument_list[1].length,True);
5815 break;
5816 }
5817 case 69: /* UnsharpMask */
5818 {
5819 double
5820 amount,
5821 radius,
5822 sigma,
5823 threshold;
5824
5825 radius=0.0;
5826 sigma=1.0;
5827 amount=1.0;
5828 threshold=0.05;
5829 if (attribute_flag[1])
5830 radius=argument_list[1].double_reference;
5831 if (attribute_flag[2])
5832 sigma=argument_list[2].double_reference;
5833 if (attribute_flag[3])
5834 amount=argument_list[3].double_reference;
5835 if (attribute_flag[4])
5836 threshold=argument_list[4].double_reference;
5837 if (attribute_flag[0])
5838 (void) sscanf(argument_list[0].string_reference,"%lfx%lf%lf%lf",
5839 &radius,&sigma,&amount,&threshold);
5840 image=UnsharpMaskImage(image,radius,sigma,amount,threshold,
5841 &exception);
5842 break;
5843 }
5844 case 70: /* MotionBlur */
5845 {
5846 double
5847 angle,
5848 radius,
5849 sigma;
5850
5851 radius=0.0;
5852 sigma=1.0;
5853 angle=1.0;
5854 if (attribute_flag[1])
5855 radius=argument_list[1].double_reference;
5856 if (attribute_flag[2])
5857 sigma=argument_list[2].double_reference;
5858 if (attribute_flag[3])
5859 angle=argument_list[3].double_reference;
5860 if (attribute_flag[0])
5861 (void) sscanf(argument_list[0].string_reference,"%lfx%lf",
5862 &radius,&sigma);
5863 image=MotionBlurImage(image,radius,sigma,angle,&exception);
5864 break;
5865 }
5866 case 71: /* OrderedDither */
5867 {
5868 (void) OrderedDitherImage(image);
5869 break;
5870 }
5871 case 72: /* Shave */
5872 {
5873 if (attribute_flag[0])
5874 /*flags=*/GetImageGeometry(image,argument_list[0].string_reference,
5875 False,&geometry);
5876 if (attribute_flag[1])
5877 geometry.width=argument_list[1].int_reference;
5878 if (attribute_flag[2])
5879 geometry.height=argument_list[2].int_reference;
5880 image=ShaveImage(image,&geometry,&exception);
5881 break;
5882 }
5883 case 73: /* Level */
5884 {
5885 if (!attribute_flag[1])
5886 argument_list[1].double_reference=0.0;
5887 if (!attribute_flag[2])
5888 argument_list[2].double_reference=1.0;
5889 if (!attribute_flag[3])
5890 argument_list[3].double_reference=MaxRGB;
5891 if (!attribute_flag[0])
5892 {
5893 FormatString(message,"%g,%g,%g",
5894 argument_list[1].double_reference,
5895 argument_list[2].double_reference,
5896 argument_list[3].double_reference);
5897 argument_list[0].string_reference=message;
5898 }
5899 LevelImage(image,argument_list[0].string_reference);
5900 break;
5901 }
5902 case 74: /* Clip */
5903 {
5904 (void) ClipImage(image);
5905 break;
5906 }
5907 case 75: /* AffineTransform */
5908 {
5909 DrawInfo
5910 *draw_info;
5911
5912 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
5913 info ? info->draw_info : (DrawInfo *) NULL);
5914 if (attribute_flag[0])
5915 {
5916 AV
5917 *av;
5918
5919 av=(AV *) argument_list[0].array_reference;
5920 if (av_len(av) >= 1)
5921 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
5922 if (av_len(av) >= 2)
5923 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
5924 if (av_len(av) >= 3)
5925 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
5926 if (av_len(av) >= 4)
5927 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
5928 if (av_len(av) >= 5)
5929 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
5930 if (av_len(av) >= 6)
5931 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
5932 }
5933 for (j=1; j < 6; j++)
5934 {
5935 if (!attribute_flag[j])
5936 continue;
5937 value=argument_list[j].string_reference;
5938 angle=argument_list[j].double_reference;
5939 current=draw_info->affine;
5940 IdentityAffine(&affine);
5941 switch (j)
5942 {
5943 case 1:
5944 {
5945 /*
5946 Translate.
5947 */
5948 k=sscanf(value,"%lf%*[,/]%lf",&affine.tx,&affine.ty);
5949 if (k == 1)
5950 affine.ty=affine.tx;
5951 break;
5952 }
5953 case 2:
5954 {
5955 /*
5956 Scale.
5957 */
5958 k=sscanf(value,"%lf%*[,/]%lf",&affine.sx,&affine.sy);
5959 if (k == 1)
5960 affine.sy=affine.sx;
5961 break;
5962 }
5963 case 3:
5964 {
5965 /*
5966 Rotate.
5967 */
5968 if (angle == 0.0)
5969 break;
5970 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
5971 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
5972 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
5973 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
5974 break;
5975 }
5976 case 4:
5977 {
5978 /*
5979 SkewX.
5980 */
5981 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
5982 break;
5983 }
5984 case 5:
5985 {
5986 /*
5987 SkewY.
5988 */
5989 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
5990 break;
5991 }
5992 }
5993 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
5994 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
5995 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
5996 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
5997 draw_info->affine.tx=
5998 current.sx*affine.tx+current.ry*affine.ty+current.tx;
5999 draw_info->affine.ty=
6000 current.rx*affine.tx+current.sy*affine.ty+current.ty;
6001 }
6002 image=AffineTransformImage(image,&draw_info->affine,&exception);
6003 DestroyDrawInfo(draw_info);
6004 break;
6005 }
6006 case 76: /* Compare */
6007 {
6008 if (!attribute_flag[0])
6009 {
6010 MagickError(OptionError,ReferenceImageRequired,NULL);
6011 goto ReturnIt;
6012 }
6013 (void) IsImagesEqual(image,argument_list[0].image_reference);
6014 break;
6015 }
6016 case 77: /* AdaptiveThreshold */
6017 {
6018 double
6019 offset;
6020
6021 unsigned long
6022 height,
6023 width;
6024
6025 height=3;
6026 width=3;
6027 offset=0.0;
6028 if (attribute_flag[1])
6029 width=argument_list[1].int_reference;
6030 if (attribute_flag[2])
6031 height=argument_list[2].int_reference;
6032 if (attribute_flag[3])
6033 offset=argument_list[3].int_reference;;
6034 if (attribute_flag[0])
6035 {
6036 (void) sscanf(argument_list[0].string_reference,"%lux%lu%lf",
6037 &width,&height,&offset);
6038 if (strchr(argument_list[0].string_reference,'%') != (char *) NULL)
6039 offset*=(double) MaxRGB/100.0;
6040 }
6041 image=AdaptiveThresholdImage(image,width,height,offset,&exception);
6042 break;
6043 }
6044 }
6045 if (exception.severity != UndefinedException)
6046 CatchException(&exception);
6047 if (next != (Image *) NULL)
6048 (void) CatchImageException(next);
6049 if (region_image != (Image *) NULL)
6050 {
6051 /*unsigned int
6052 status;*/
6053
6054 /*
6055 Composite region.
6056 */
6057 /*status=*/CompositeImage(region_image,CopyCompositeOp,image,
6058 region_info.x,region_info.y);
6059 (void) CatchImageException(region_image);
6060 DestroyImage(image);
6061 image=region_image;
6062 }
6063 if (image)
6064 {
6065 number_images++;
6066 if (next && (next != image))
6067 {
6068 image->next=next->next;
6069 next->previous=0;
6070 DestroyImage(next);
6071 }
6072 sv_setiv(*pv,(IV) (magick_uintptr_t)image);
6073 next=image;
6074 }
6075 if (*pv)
6076 pv++;
6077 }
6078 DestroyExceptionInfo(&exception);
6079
6080 ReturnIt:
6081 MagickFreeMemory(reference_vector);
6082 sv_setiv(MY_CXT.error_list,(IV) number_images);
6083 SvPOK_on(MY_CXT.error_list);
6084 ST(0)=sv_2mortal(MY_CXT.error_list);
6085 MY_CXT.error_list=NULL;
6086 MY_CXT.error_jump=NULL;
6087 XSRETURN(1);
6088 }
6089
6090 #
6091 ###############################################################################
6092 # #
6093 # #
6094 # #
6095 # M o n t a g e #
6096 # #
6097 # #
6098 # #
6099 ###############################################################################
6100 #
6101 #
6102 void
Montage(ref,...)6103 Montage(ref,...)
6104 Graphics::Magick ref=NO_INIT
6105 ALIAS:
6106 MontageImage = 1
6107 montage = 2
6108 montageimage = 3
6109 PPCODE:
6110 {
6111 AV
6112 *av;
6113
6114 char
6115 *attribute;
6116
6117 ExceptionInfo
6118 exception;
6119
6120 HV
6121 *hv;
6122
6123 Image
6124 *image,
6125 *next;
6126
6127 int
6128 sp;
6129
6130 jmp_buf
6131 error_jmp;
6132
6133 MontageInfo
6134 *montage_info;
6135
6136 PixelPacket
6137 transparent_color;
6138
6139 register int
6140 i;
6141
6142 struct PackageInfo
6143 *info;
6144
6145 SV
6146 *av_reference,
6147 *reference,
6148 *rv,
6149 *sv;
6150
6151 volatile int
6152 status;
6153
6154 dMY_CXT;
6155 MY_CXT.error_list=newSVpv("",0);
6156 status=0;
6157 attribute=NULL;
6158 if (!sv_isobject(ST(0)))
6159 {
6160 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
6161 goto MethodException;
6162 }
6163 reference=SvRV(ST(0));
6164 hv=SvSTASH(reference);
6165 av=newAV();
6166 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6167 SvREFCNT_dec(av);
6168 MY_CXT.error_jump=(&error_jmp);
6169 status=setjmp(error_jmp);
6170 if (status)
6171 goto MethodException;
6172 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
6173 if (!image)
6174 {
6175 MagickError(OptionError,NoImagesDefined,NULL);
6176 goto MethodException;
6177 }
6178 /*
6179 Get options.
6180 */
6181 info=GetPackageInfo(aTHX_ (void *) av,info);
6182 montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
6183 GetExceptionInfo(&exception);
6184 (void) QueryColorDatabase("none",&transparent_color,&exception);
6185 for (i=2; i < items; i+=2)
6186 {
6187 attribute=(char *) SvPV(ST(i-1),na);
6188 switch (*attribute)
6189 {
6190 case 'B':
6191 case 'b':
6192 {
6193 if (LocaleCompare(attribute,"background") == 0)
6194 {
6195 (void) QueryColorDatabase(SvPV(ST(i),na),
6196 &montage_info->background_color,&exception);
6197 break;
6198 }
6199 if (LocaleCompare(attribute,"bordercolor") == 0)
6200 {
6201 (void) QueryColorDatabase(SvPV(ST(i),na),
6202 &montage_info->border_color,&exception);
6203 break;
6204 }
6205 if (LocaleCompare(attribute,"borderwidth") == 0)
6206 {
6207 montage_info->border_width=SvIV(ST(i));
6208 break;
6209 }
6210 MagickError(OptionError,UnrecognizedAttribute,attribute);
6211 break;
6212 }
6213 case 'C':
6214 case 'c':
6215 {
6216 if (LocaleCompare(attribute,"compose") == 0)
6217 {
6218 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) :
6219 LookupStr(CompositeTypes,SvPV(ST(i),na));
6220 if (sp < 0)
6221 {
6222 MagickError(OptionError,UnrecognizedType,
6223 SvPV(ST(i),na));
6224 break;
6225 }
6226 for (next=image; next; next=next->next)
6227 next->compose=(CompositeOperator) sp;
6228 break;
6229 }
6230 MagickError(OptionError,UnrecognizedAttribute,attribute);
6231 break;
6232 }
6233 case 'F':
6234 case 'f':
6235 {
6236 if (LocaleCompare(attribute,"fill") == 0)
6237 {
6238 (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
6239 &exception);
6240 break;
6241 }
6242 if (LocaleCompare(attribute,"font") == 0)
6243 {
6244 (void) CloneString(&montage_info->font,SvPV(ST(i),na));
6245 break;
6246 }
6247 if (LocaleCompare(attribute,"frame") == 0)
6248 {
6249 char
6250 *p;
6251
6252 p=SvPV(ST(i),na);
6253 if (!IsGeometry(p))
6254 {
6255 MagickError(OptionError,MissingGeometry,p);
6256 break;
6257 }
6258 (void) CloneString(&montage_info->frame,p);
6259 if (*p == '\0')
6260 montage_info->frame=(char *) NULL;
6261 break;
6262 }
6263 MagickError(OptionError,UnrecognizedAttribute,attribute);
6264 break;
6265 }
6266 case 'G':
6267 case 'g':
6268 {
6269 if (LocaleCompare(attribute,"geometry") == 0)
6270 {
6271 char
6272 *p;
6273
6274 p=SvPV(ST(i),na);
6275 if (!IsGeometry(p))
6276 {
6277 MagickError(OptionError,MissingGeometry,p);
6278 break;
6279 }
6280 (void) CloneString(&montage_info->geometry,p);
6281 if (*p == '\0')
6282 montage_info->geometry=(char *) NULL;
6283 break;
6284 }
6285 if (LocaleCompare(attribute,"gravity") == 0)
6286 {
6287 int
6288 in;
6289
6290 in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
6291 LookupStr(GravityTypes,SvPV(ST(i),na));
6292 if (in < 0)
6293 {
6294 MagickError(OptionError,UnrecognizedType,SvPV(ST(i),na));
6295 return;
6296 }
6297 montage_info->gravity=(GravityType) in;
6298 for (next=image; next; next=next->next)
6299 next->gravity=(GravityType) in;
6300 break;
6301 }
6302 MagickError(OptionError,UnrecognizedAttribute,attribute);
6303 break;
6304 }
6305 case 'L':
6306 case 'l':
6307 {
6308 if (LocaleCompare(attribute,"label") == 0)
6309 {
6310 for (next=image; next; next=next->next)
6311 (void) SetImageAttribute(next,"label",SvPV(ST(i),na));
6312 break;
6313 }
6314 MagickError(OptionError,UnrecognizedAttribute,attribute);
6315 break;
6316 }
6317 case 'M':
6318 case 'm':
6319 {
6320 if (LocaleCompare(attribute,"mattecolor") == 0)
6321 {
6322 (void) QueryColorDatabase(SvPV(ST(i),na),
6323 &montage_info->matte_color,&exception);
6324 break;
6325 }
6326 if (LocaleCompare(attribute,"mode") == 0)
6327 {
6328 int
6329 in;
6330
6331 in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
6332 LookupStr(ModeTypes,SvPV(ST(i),na));
6333 switch (in)
6334 {
6335 default:
6336 {
6337 MagickError(OptionError,UnrecognizedModeType,
6338 SvPV(ST(i),na));
6339 break;
6340 }
6341 case FrameMode:
6342 {
6343 (void) CloneString(&montage_info->frame,"15x15+3+3");
6344 montage_info->shadow=True;
6345 break;
6346 }
6347 case UnframeMode:
6348 {
6349 montage_info->frame=(char *) NULL;
6350 montage_info->shadow=False;
6351 montage_info->border_width=0;
6352 break;
6353 }
6354 case ConcatenateMode:
6355 {
6356 montage_info->frame=(char *) NULL;
6357 montage_info->shadow=False;
6358 (void) CloneString(&montage_info->geometry,"+0+0");
6359 montage_info->border_width=0;
6360 }
6361 }
6362 break;
6363 }
6364 MagickError(OptionError,UnrecognizedAttribute,attribute);
6365 break;
6366 }
6367 case 'P':
6368 case 'p':
6369 {
6370 if (LocaleCompare(attribute,"pointsize") == 0)
6371 {
6372 montage_info->pointsize=SvIV(ST(i));
6373 break;
6374 }
6375 MagickError(OptionError,UnrecognizedAttribute,attribute);
6376 break;
6377 }
6378 case 'S':
6379 case 's':
6380 {
6381 if (LocaleCompare(attribute,"shadow") == 0)
6382 {
6383 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) :
6384 LookupStr(BooleanTypes,SvPV(ST(i),na));
6385 if (sp < 0)
6386 {
6387 MagickError(OptionError,UnrecognizedType,SvPV(ST(i),na));
6388 break;
6389 }
6390 montage_info->shadow=sp != 0;
6391 break;
6392 }
6393 if (LocaleCompare(attribute,"stroke") == 0)
6394 {
6395 (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
6396 &exception);
6397 break;
6398 }
6399 MagickError(OptionError,UnrecognizedAttribute,attribute);
6400 break;
6401 }
6402 case 'T':
6403 case 't':
6404 {
6405 if (LocaleCompare(attribute,"texture") == 0)
6406 {
6407 (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
6408 break;
6409 }
6410 if (LocaleCompare(attribute,"tile") == 0)
6411 {
6412 char *p=SvPV(ST(i),na);
6413 if (!IsGeometry(p))
6414 {
6415 MagickError(OptionError,MissingGeometry,p);
6416 break;
6417 }
6418 (void) CloneString(&montage_info->tile,p);
6419 if (*p == '\0')
6420 montage_info->tile=(char *) NULL;
6421 break;
6422 }
6423 if (LocaleCompare(attribute,"title") == 0)
6424 {
6425 (void) CloneString(&montage_info->title,SvPV(ST(i),na));
6426 break;
6427 }
6428 if (LocaleCompare(attribute,"transparent") == 0)
6429 {
6430 (void) AcquireOnePixelByReference(image,&transparent_color,0,0,&exception);
6431 QueryColorDatabase(SvPV(ST(i),na),&transparent_color,
6432 &exception);
6433 for (next=image; next; next=next->next)
6434 TransparentImage(next,transparent_color,TransparentOpacity);
6435 break;
6436 }
6437 MagickError(OptionError,UnrecognizedAttribute,attribute);
6438 break;
6439 }
6440 default:
6441 {
6442 MagickError(OptionError,UnrecognizedAttribute,attribute);
6443 break;
6444 }
6445 }
6446 }
6447 image=MontageImages(image,montage_info,&exception);
6448 if (exception.severity != UndefinedException)
6449 CatchException(&exception);
6450 DestroyExceptionInfo(&exception);
6451 DestroyMontageInfo(montage_info);
6452 if (transparent_color.opacity != TransparentOpacity)
6453 for (next=image; next; next=next->next)
6454 TransparentImage(next,transparent_color,TransparentOpacity);
6455 for ( ; image; image=image->next)
6456 {
6457 sv=newSViv((IV) (magick_uintptr_t)image);
6458 rv=newRV(sv);
6459 av_push(av,sv_bless(rv,hv));
6460 SvREFCNT_dec(sv);
6461 }
6462 ST(0)=av_reference;
6463 MY_CXT.error_jump=NULL;
6464 SvREFCNT_dec(MY_CXT.error_list);
6465 MY_CXT.error_list=NULL;
6466 XSRETURN(1);
6467
6468 MethodException:
6469 sv_setiv(MY_CXT.error_list,(IV) (status ? status : SvCUR(MY_CXT.error_list) != 0));
6470 SvPOK_on(MY_CXT.error_list);
6471 ST(0)=sv_2mortal(MY_CXT.error_list);
6472 MY_CXT.error_list=NULL;
6473 MY_CXT.error_jump=NULL;
6474 XSRETURN(1);
6475 }
6476
6477 #
6478 ###############################################################################
6479 # #
6480 # #
6481 # #
6482 # M o r p h #
6483 # #
6484 # #
6485 # #
6486 ###############################################################################
6487 #
6488 #
6489 void
Morph(ref,...)6490 Morph(ref,...)
6491 Graphics::Magick ref=NO_INIT
6492 ALIAS:
6493 MorphImage = 1
6494 morph = 2
6495 morphimage = 3
6496 PPCODE:
6497 {
6498 AV
6499 *av;
6500
6501 char
6502 *attribute;
6503
6504 ExceptionInfo
6505 exception;
6506
6507 HV
6508 *hv;
6509
6510 Image
6511 *image;
6512
6513 jmp_buf
6514 error_jmp;
6515
6516 int
6517 number_frames;
6518
6519 register int
6520 i;
6521
6522 struct PackageInfo
6523 *info;
6524
6525 SV
6526 *av_reference,
6527 *reference,
6528 *rv,
6529 *sv;
6530
6531 volatile int
6532 status;
6533
6534 dMY_CXT;
6535 MY_CXT.error_list=newSVpv("",0);
6536 av=NULL;
6537 status=0;
6538 attribute=NULL;
6539 if (!sv_isobject(ST(0)))
6540 {
6541 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
6542 goto MethodException;
6543 }
6544 reference=SvRV(ST(0));
6545 hv=SvSTASH(reference);
6546 av=newAV();
6547 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6548 SvREFCNT_dec(av);
6549 MY_CXT.error_jump=(&error_jmp);
6550 status=setjmp(error_jmp);
6551 if (status)
6552 goto MethodException;
6553 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
6554 if (!image)
6555 {
6556 MagickError(OptionError,NoImagesDefined,NULL);
6557 goto MethodException;
6558 }
6559 info=GetPackageInfo(aTHX_ (void *) av,info);
6560 /*
6561 Get attribute.
6562 */
6563 number_frames=30;
6564 for (i=2; i < items; i+=2)
6565 {
6566 attribute=(char *) SvPV(ST(i-1),na);
6567 switch (*attribute)
6568 {
6569 case 'F':
6570 case 'f':
6571 {
6572 if (LocaleCompare(attribute,"frames") == 0)
6573 {
6574 number_frames=SvIV(ST(i));
6575 break;
6576 }
6577 MagickError(OptionError,UnrecognizedAttribute,attribute);
6578 break;
6579 }
6580 default:
6581 {
6582 MagickError(OptionError,UnrecognizedAttribute,attribute);
6583 break;
6584 }
6585 }
6586 }
6587 GetExceptionInfo(&exception);
6588 image=MorphImages(image,number_frames,&exception);
6589 if (exception.severity != UndefinedException)
6590 CatchException(&exception);
6591 DestroyExceptionInfo(&exception);
6592 for ( ; image; image=image->next)
6593 {
6594 sv=newSViv((IV) (magick_uintptr_t)image);
6595 rv=newRV(sv);
6596 av_push(av,sv_bless(rv,hv));
6597 SvREFCNT_dec(sv);
6598 }
6599 ST(0)=av_reference;
6600 MY_CXT.error_jump=NULL;
6601 SvREFCNT_dec(MY_CXT.error_list); /* can't return warning messages */
6602 MY_CXT.error_list=NULL;
6603 XSRETURN(1);
6604
6605 MethodException:
6606 MY_CXT.error_jump=NULL;
6607 sv_setiv(MY_CXT.error_list,(IV) (status ? status : SvCUR(MY_CXT.error_list) != 0));
6608 SvPOK_on(MY_CXT.error_list);
6609 ST(0)=sv_2mortal(MY_CXT.error_list);
6610 MY_CXT.error_list=NULL;
6611 MY_CXT.error_jump=NULL;
6612 XSRETURN(1);
6613 }
6614
6615 #
6616 ###############################################################################
6617 # #
6618 # #
6619 # #
6620 # M o s a i c #
6621 # #
6622 # #
6623 # #
6624 ###############################################################################
6625 #
6626 #
6627 void
Mosaic(ref)6628 Mosaic(ref)
6629 Graphics::Magick ref=NO_INIT
6630 ALIAS:
6631 MosaicImage = 1
6632 mosaic = 2
6633 mosaicimage = 3
6634 PPCODE:
6635 {
6636 AV
6637 *av;
6638
6639 ExceptionInfo
6640 exception;
6641
6642 HV
6643 *hv;
6644
6645 jmp_buf
6646 error_jmp;
6647
6648 Image
6649 *image;
6650
6651 struct PackageInfo
6652 *info;
6653
6654 SV
6655 *reference,
6656 *rv,
6657 *sv;
6658
6659 volatile int
6660 status;
6661
6662 dMY_CXT;
6663 MY_CXT.error_list=newSVpv("",0);
6664 status=0;
6665 if (!sv_isobject(ST(0)))
6666 {
6667 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
6668 goto MethodException;
6669 }
6670 reference=SvRV(ST(0));
6671 hv=SvSTASH(reference);
6672 MY_CXT.error_jump=(&error_jmp);
6673 status=setjmp(error_jmp);
6674 if (status)
6675 goto MethodException;
6676 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
6677 if (!image)
6678 {
6679 MagickError(OptionError,NoImagesDefined,NULL);
6680 goto MethodException;
6681 }
6682 GetExceptionInfo(&exception);
6683 image=MosaicImages(image,&exception);
6684 if (exception.severity != UndefinedException)
6685 CatchException(&exception);
6686 /*
6687 Create blessed Perl array for the returned image.
6688 */
6689 av=newAV();
6690 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6691 SvREFCNT_dec(av);
6692 sv=newSViv((IV) (magick_uintptr_t)image);
6693 rv=newRV(sv);
6694 av_push(av,sv_bless(rv,hv));
6695 SvREFCNT_dec(sv);
6696 info=GetPackageInfo(aTHX_ (void *) av,info);
6697 (void) strncpy(image->filename,info->image_info->filename,MaxTextExtent-1);
6698 SetImageInfo(info->image_info,SETMAGICK_WRITE,&image->exception);
6699 if (exception.severity != UndefinedException)
6700 CatchException(&exception);
6701 DestroyExceptionInfo(&exception);
6702 SvREFCNT_dec(MY_CXT.error_list);
6703 MY_CXT.error_jump=NULL;
6704 XSRETURN(1);
6705
6706 MethodException:
6707 sv_setiv(MY_CXT.error_list,(IV) (status ? status : SvCUR(MY_CXT.error_list) != 0));
6708 SvPOK_on(MY_CXT.error_list); /* return messages in string context */
6709 ST(0)=sv_2mortal(MY_CXT.error_list);
6710 MY_CXT.error_list=NULL;
6711 MY_CXT.error_jump=NULL;
6712 XSRETURN(1);
6713 }
6714
6715 #
6716 ###############################################################################
6717 # #
6718 # #
6719 # #
6720 # P i n g #
6721 # #
6722 # #
6723 # #
6724 ###############################################################################
6725 #
6726 #
6727 void
Ping(ref,...)6728 Ping(ref,...)
6729 Graphics::Magick ref=NO_INIT
6730 ALIAS:
6731 PingImage = 1
6732 ping = 2
6733 pingimage = 3
6734 PPCODE:
6735 {
6736 AV
6737 *av;
6738
6739 char
6740 **keep,
6741 **list,
6742 message[MaxTextExtent];
6743
6744 ExceptionInfo
6745 exception;
6746
6747 /*
6748 HV
6749 *hv;
6750 */
6751
6752 Image
6753 *image,
6754 *next;
6755
6756 int
6757 ac,
6758 n;
6759
6760 jmp_buf
6761 error_jmp;
6762
6763 register char
6764 **p;
6765
6766 register int
6767 i;
6768
6769 struct PackageInfo
6770 *info,
6771 *package_info;
6772
6773 SV
6774 *reference;
6775
6776 unsigned int
6777 status;
6778
6779 unsigned long
6780 count;
6781
6782 dMY_CXT;
6783 MY_CXT.error_list=newSVpv("",0);
6784 package_info=(struct PackageInfo *) NULL;
6785 ac=(items < 2) ? 1 : items-1;
6786 list=MagickAllocateMemory(char **,(ac+1)*sizeof(*list));
6787 reference=SvRV(ST(0));
6788 /* hv= SvSTASH(reference); */
6789 av=(AV *) reference;
6790 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL);
6791 package_info=ClonePackageInfo(info);
6792 n=1;
6793 if (items <= 1)
6794 *list=(char *) (*package_info->image_info->filename ?
6795 package_info->image_info->filename : "XC:black");
6796 else
6797 for (n=0, i=0; i < ac; i++)
6798 {
6799 STRLEN
6800 length;
6801
6802 list[n]=(char *) SvPV(ST(i+1),length);
6803 if ((items >= 3) && strEQcase(list[n],"blob"))
6804 {
6805 package_info->image_info->blob=(void *) (SvPV(ST(i+2),length));
6806 package_info->image_info->length=(size_t) length;
6807 continue;
6808 }
6809 if ((items >= 3) && strEQcase(list[n],"filename"))
6810 continue;
6811 if ((items >= 3) && strEQcase(list[n],"file"))
6812 {
6813 package_info->image_info->file=
6814 PerlIO_findFILE(IoIFP(sv_2io(ST(i+2))));
6815 continue;
6816 }
6817 n++;
6818 }
6819 list[n]=(char *) NULL;
6820 keep=list;
6821 MY_CXT.error_jump=(&error_jmp);
6822 if (setjmp(error_jmp))
6823 goto ReturnIt;
6824 status=ExpandFilenames(&n,&list);
6825 if (status == False)
6826 {
6827 MagickError(ResourceLimitError,MemoryAllocationFailed,NULL);
6828 goto ReturnIt;
6829 }
6830 count=0;
6831 GetExceptionInfo(&exception);
6832 for (i=0; i < n; i++)
6833 {
6834 (void) strncpy(package_info->image_info->filename,list[i],
6835 MaxTextExtent-1);
6836 image=PingImage(package_info->image_info,&exception);
6837 if (exception.severity != UndefinedException)
6838 CatchException(&exception);
6839 count+=GetImageListLength(image);
6840 EXTEND(sp,4*count);
6841 for (next=image; next; next=next->next)
6842 {
6843 FormatString(message,"%lu",next->columns);
6844 PUSHs(sv_2mortal(newSVpv(message,0)));
6845 FormatString(message,"%lu",next->rows);
6846 PUSHs(sv_2mortal(newSVpv(message,0)));
6847 FormatString(message,"%lu",(unsigned long) GetBlobSize(next));
6848 PUSHs(sv_2mortal(newSVpv(message,0)));
6849 PUSHs(sv_2mortal(newSVpv(next->magick,0)));
6850 }
6851 DestroyImageList(image);
6852 }
6853 DestroyExceptionInfo(&exception);
6854 /*
6855 Free resources.
6856 */
6857 for (i=0; i < n; i++)
6858 if (list[i])
6859 for (p=keep; list[i] != *p++; )
6860 if (*p == NULL)
6861 {
6862 MagickFreeMemory(list[i]);
6863 break;
6864 }
6865
6866 ReturnIt:
6867 if (package_info)
6868 DestroyPackageInfo(package_info);
6869 MagickFreeMemory(list);
6870 SvREFCNT_dec(MY_CXT.error_list); /* throw away all errors */
6871 MY_CXT.error_list=NULL;
6872 }
6873
6874 #
6875 ###############################################################################
6876 # #
6877 # #
6878 # #
6879 # Q u e r y C o l o r #
6880 # #
6881 # #
6882 # #
6883 ###############################################################################
6884 #
6885 #
6886 void
QueryColor(ref,...)6887 QueryColor(ref,...)
6888 Graphics::Magick ref=NO_INIT
6889 ALIAS:
6890 querycolor = 1
6891 PPCODE:
6892 {
6893 char
6894 *name,
6895 message[MaxTextExtent];
6896
6897 ExceptionInfo
6898 exception;
6899
6900 PixelPacket
6901 color;
6902
6903 register int
6904 i;
6905
6906 dMY_CXT;
6907 MY_CXT.error_list=newSVpv("",0);
6908 if (items == 1)
6909 {
6910 char
6911 **colorlist;
6912
6913 unsigned long
6914 colors;
6915
6916 colorlist=GetColorList("*",&colors);
6917 EXTEND(sp,colors);
6918 for (i=0; i < (long) colors; i++)
6919 {
6920 PUSHs(sv_2mortal(newSVpv(colorlist[i],0)));
6921 MagickFreeMemory(colorlist[i]);
6922 }
6923 MagickFreeMemory(colorlist);
6924 goto MethodException;
6925 }
6926 EXTEND(sp,4*items);
6927 GetExceptionInfo(&exception);
6928 for (i=1; i < items; i++)
6929 {
6930 name=(char *) SvPV(ST(i),na);
6931 if (!QueryColorDatabase(name,&color,&exception))
6932 {
6933 PUSHs(&sv_undef);
6934 continue;
6935 }
6936 FormatString(message,"%u",color.red);
6937 PUSHs(sv_2mortal(newSVpv(message,0)));
6938 FormatString(message,"%u",color.green);
6939 PUSHs(sv_2mortal(newSVpv(message,0)));
6940 FormatString(message,"%u",color.blue);
6941 PUSHs(sv_2mortal(newSVpv(message,0)));
6942 FormatString(message,"%u",color.opacity);
6943 PUSHs(sv_2mortal(newSVpv(message,0)));
6944 }
6945 DestroyExceptionInfo(&exception);
6946
6947 MethodException:
6948 SvREFCNT_dec(MY_CXT.error_list);
6949 MY_CXT.error_list=NULL;
6950 }
6951
6952 #
6953 ###############################################################################
6954 # #
6955 # #
6956 # #
6957 # Q u e r y C o l o r N a m e #
6958 # #
6959 # #
6960 # #
6961 ###############################################################################
6962 #
6963 #
6964 void
QueryColorname(ref,...)6965 QueryColorname(ref,...)
6966 Graphics::Magick ref=NO_INIT
6967 ALIAS:
6968 querycolorname = 1
6969 PPCODE:
6970 {
6971 AV
6972 *av;
6973
6974 char
6975 message[MaxTextExtent];
6976
6977 ExceptionInfo
6978 exception;
6979
6980 Image
6981 *image;
6982
6983 PixelPacket
6984 target_color;
6985
6986 register int
6987 i;
6988
6989 struct PackageInfo
6990 *info;
6991
6992 SV
6993 *reference; /* reference is the SV* of ref=SvIV(reference) */
6994
6995 dMY_CXT;
6996 MY_CXT.error_list=newSVpv("",0);
6997 reference=SvRV(ST(0));
6998 av=(AV *) reference;
6999 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL);
7000 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
7001 EXTEND(sp,items);
7002 GetExceptionInfo(&exception);
7003 for (i=1; i < items; i++)
7004 {
7005 (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,&exception);
7006 (void) QueryColorname(image,&target_color,SVGCompliance,message,
7007 &image->exception);
7008 PUSHs(sv_2mortal(newSVpv(message,0)));
7009 }
7010 DestroyExceptionInfo(&exception);
7011 SvREFCNT_dec(MY_CXT.error_list);
7012 MY_CXT.error_list=NULL;
7013 }
7014
7015 #
7016 ###############################################################################
7017 # #
7018 # #
7019 # #
7020 # Q u e r y F o n t #
7021 # #
7022 # #
7023 # #
7024 ###############################################################################
7025 #
7026 #
7027 void
QueryFont(ref,...)7028 QueryFont(ref,...)
7029 Graphics::Magick ref=NO_INIT
7030 ALIAS:
7031 queryfont = 1
7032 PPCODE:
7033 {
7034 char
7035 *name,
7036 message[MaxTextExtent];
7037
7038 ExceptionInfo
7039 exception;
7040
7041 register int
7042 i;
7043
7044 volatile const TypeInfo
7045 *type_info;
7046
7047 dMY_CXT;
7048 MY_CXT.error_list=newSVpv("",0);
7049 if (items == 1)
7050 {
7051 char
7052 **typelist;
7053
7054 unsigned long
7055 types;
7056
7057 typelist=GetTypeList("*",&types);
7058 EXTEND(sp,types);
7059 for (i=0; i < (long) types; i++)
7060 {
7061 PUSHs(sv_2mortal(newSVpv(typelist[i],0)));
7062 MagickFreeMemory(typelist[i]);
7063 }
7064 MagickFreeMemory(typelist);
7065 goto MethodException;
7066 }
7067 EXTEND(sp,10*items);
7068 GetExceptionInfo(&exception);
7069 for (i=1; i < items; i++)
7070 {
7071 name=(char *) SvPV(ST(i),na);
7072 type_info=GetTypeInfo(name,&exception);
7073 if (exception.severity != UndefinedException)
7074 CatchException(&exception);
7075 if (type_info == (TypeInfo *) NULL)
7076 {
7077 PUSHs(&sv_undef);
7078 continue;
7079 }
7080 if (type_info->name == (char *) NULL)
7081 PUSHs(&sv_undef);
7082 else
7083 PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
7084 if (type_info->description == (char *) NULL)
7085 PUSHs(&sv_undef);
7086 else
7087 PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
7088 if (type_info->family == (char *) NULL)
7089 PUSHs(&sv_undef);
7090 else
7091 PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
7092 PUSHs(sv_2mortal(newSVpv(StyleTypes[(long) type_info->style],0)));
7093 PUSHs(sv_2mortal(newSVpv(StretchTypes[(long) type_info->stretch],0)));
7094 FormatString(message,"%lu",type_info->weight);
7095 PUSHs(sv_2mortal(newSVpv(message,0)));
7096 if (type_info->encoding == (char *) NULL)
7097 PUSHs(&sv_undef);
7098 else
7099 PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
7100 if (type_info->foundry == (char *) NULL)
7101 PUSHs(&sv_undef);
7102 else
7103 PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
7104 if (type_info->format == (char *) NULL)
7105 PUSHs(&sv_undef);
7106 else
7107 PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
7108 if (type_info->metrics == (char *) NULL)
7109 PUSHs(&sv_undef);
7110 else
7111 PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
7112 if (type_info->glyphs == (char *) NULL)
7113 PUSHs(&sv_undef);
7114 else
7115 PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
7116 }
7117 DestroyExceptionInfo(&exception);
7118
7119 MethodException:
7120 SvREFCNT_dec(MY_CXT.error_list);
7121 MY_CXT.error_list=NULL;
7122 }
7123
7124 #
7125 ###############################################################################
7126 # #
7127 # #
7128 # #
7129 # Q u e r y F o n t M e t r i c s #
7130 # #
7131 # #
7132 # #
7133 ###############################################################################
7134 #
7135 #
7136 void
QueryFontMetrics(ref,...)7137 QueryFontMetrics(ref,...)
7138 Graphics::Magick ref=NO_INIT
7139 ALIAS:
7140 queryfontmetrics = 1
7141 PPCODE:
7142 {
7143 AffineMatrix
7144 affine,
7145 current;
7146
7147 AV
7148 *av;
7149
7150 char
7151 *attribute,
7152 message[MaxTextExtent];
7153
7154 double
7155 x,
7156 y;
7157
7158 DrawInfo
7159 *draw_info;
7160
7161 Image
7162 *image;
7163
7164 register int
7165 i;
7166
7167 struct PackageInfo
7168 *info;
7169
7170 SV
7171 *reference; /* reference is the SV* of ref=SvIV(reference) */
7172
7173 TypeMetric
7174 metrics;
7175
7176 unsigned int
7177 status;
7178
7179 dMY_CXT;
7180 MY_CXT.error_list=newSVpv("",0);
7181 reference=SvRV(ST(0));
7182 av=(AV *) reference;
7183 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL);
7184 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
7185 if (!image)
7186 {
7187 MagickError(OptionError,NoImagesDefined,NULL);
7188 goto MethodException;
7189 }
7190 draw_info=CloneDrawInfo(info->image_info,info->draw_info);
7191 CloneString(&draw_info->text,"");
7192 current=draw_info->affine;
7193 IdentityAffine(&affine);
7194 x=0.0;
7195 y=0.0;
7196 EXTEND(sp,7*items);
7197 for (i=2; i < items; i+=2)
7198 {
7199 attribute=(char *) SvPV(ST(i-1),na);
7200 switch (*attribute)
7201 {
7202 case 'd':
7203 case 'D':
7204 {
7205 if (LocaleCompare(attribute,"density") == 0)
7206 {
7207 CloneString(&draw_info->density,SvPV(ST(i),na));
7208 break;
7209 }
7210 MagickError(OptionError,UnrecognizedAttribute,attribute);
7211 break;
7212 }
7213 case 'e':
7214 case 'E':
7215 {
7216 if (LocaleCompare(attribute,"encoding") == 0)
7217 {
7218 CloneString(&draw_info->encoding,SvPV(ST(i),na));
7219 break;
7220 }
7221 MagickError(OptionError,UnrecognizedAttribute,attribute);
7222 break;
7223 }
7224 case 'f':
7225 case 'F':
7226 {
7227 if (LocaleCompare(attribute,"font") == 0)
7228 {
7229 CloneString(&draw_info->font,SvPV(ST(i),na));
7230 break;
7231 }
7232 MagickError(OptionError,UnrecognizedAttribute,attribute);
7233 break;
7234 }
7235 case 'g':
7236 case 'G':
7237 {
7238 if (LocaleCompare(attribute,"geometry") == 0)
7239 {
7240 CloneString(&draw_info->geometry,SvPV(ST(i),na));
7241 break;
7242 }
7243 if (LocaleCompare(attribute,"gravity") == 0)
7244 {
7245 draw_info->gravity=(GravityType)
7246 LookupStr(GravityTypes,SvPV(ST(i),na));
7247 break;
7248 }
7249 MagickError(OptionError,UnrecognizedAttribute,attribute);
7250 break;
7251 }
7252 case 'p':
7253 case 'P':
7254 {
7255 if (LocaleCompare(attribute,"pointsize") == 0)
7256 {
7257 (void) sscanf(SvPV(ST(i),na),"%lf",&draw_info->pointsize);
7258 break;
7259 }
7260 MagickError(OptionError,UnrecognizedAttribute,attribute);
7261 break;
7262 }
7263 case 'r':
7264 case 'R':
7265 {
7266 if (LocaleCompare(attribute,"rotate") == 0)
7267 {
7268 (void) sscanf(SvPV(ST(i),na),"%lf%*[,/]%lf",&affine.rx,
7269 &affine.ry);
7270 break;
7271 }
7272 MagickError(OptionError,UnrecognizedAttribute,attribute);
7273 break;
7274 }
7275 case 's':
7276 case 'S':
7277 {
7278 if (LocaleCompare(attribute,"scale") == 0)
7279 {
7280 (void) sscanf(SvPV(ST(i),na),"%lf%*[,/]%lf",&affine.sx,
7281 &affine.sy);
7282 break;
7283 }
7284 if (LocaleCompare(attribute,"skew") == 0)
7285 {
7286 double
7287 x_angle,
7288 y_angle;
7289
7290 x_angle=0.0;
7291 y_angle=0.0;
7292 (void) sscanf(SvPV(ST(i),na),"%lf%*[,/]%lf",&x_angle,&y_angle);
7293 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
7294 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
7295 break;
7296 }
7297 MagickError(OptionError,UnrecognizedAttribute,attribute);
7298 break;
7299 }
7300 case 't':
7301 case 'T':
7302 {
7303 if (LocaleCompare(attribute,"text") == 0)
7304 {
7305 CloneString(&draw_info->text,SvPV(ST(i),na));
7306 break;
7307 }
7308 if (LocaleCompare(attribute,"translate") == 0)
7309 {
7310 (void) sscanf(SvPV(ST(i),na),"%lf%*[,/]%lf",&affine.tx,
7311 &affine.ty);
7312 break;
7313 }
7314 MagickError(OptionError,UnrecognizedAttribute,attribute);
7315 break;
7316 }
7317 case 'x':
7318 case 'X':
7319 {
7320 if (LocaleCompare(attribute,"x") == 0)
7321 {
7322 (void) sscanf(SvPV(ST(i),na),"%lf",&x);
7323 break;
7324 }
7325 MagickError(OptionError,UnrecognizedAttribute,attribute);
7326 break;
7327 }
7328 case 'y':
7329 case 'Y':
7330 {
7331 if (LocaleCompare(attribute,"y") == 0)
7332 {
7333 (void) sscanf(SvPV(ST(i),na),"%lf",&y);
7334 break;
7335 }
7336 MagickError(OptionError,UnrecognizedAttribute,attribute);
7337 break;
7338 }
7339 default:
7340 {
7341 MagickError(OptionError,UnrecognizedAttribute,attribute);
7342 break;
7343 }
7344 }
7345 }
7346 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
7347 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
7348 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
7349 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
7350 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
7351 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
7352 if (draw_info->geometry == (char *) NULL)
7353 {
7354 draw_info->geometry=AllocateString((char *) NULL);
7355 FormatString(draw_info->geometry,"%g,%g",x,y);
7356 }
7357 status=GetTypeMetrics(image,draw_info,&metrics);
7358 (void) CatchImageException(image);
7359 if (status == False)
7360 PUSHs(&sv_undef);
7361 else
7362 {
7363 FormatString(message,"%g",metrics.pixels_per_em.x);
7364 PUSHs(sv_2mortal(newSVpv(message,0)));
7365 FormatString(message,"%g",metrics.pixels_per_em.y);
7366 PUSHs(sv_2mortal(newSVpv(message,0)));
7367 FormatString(message,"%g",metrics.ascent);
7368 PUSHs(sv_2mortal(newSVpv(message,0)));
7369 FormatString(message,"%g",metrics.descent);
7370 PUSHs(sv_2mortal(newSVpv(message,0)));
7371 FormatString(message,"%g",metrics.width);
7372 PUSHs(sv_2mortal(newSVpv(message,0)));
7373 FormatString(message,"%g",metrics.height);
7374 PUSHs(sv_2mortal(newSVpv(message,0)));
7375 FormatString(message,"%g",metrics.max_advance);
7376 PUSHs(sv_2mortal(newSVpv(message,0)));
7377 }
7378 DestroyDrawInfo(draw_info);
7379
7380 MethodException:
7381 SvREFCNT_dec(MY_CXT.error_list);
7382 MY_CXT.error_list=NULL;
7383 }
7384
7385 #
7386 ###############################################################################
7387 # #
7388 # #
7389 # #
7390 # Q u e r y F o r m a t #
7391 # #
7392 # #
7393 # #
7394 ###############################################################################
7395 #
7396 #
7397 void
QueryFormat(ref,...)7398 QueryFormat(ref,...)
7399 Graphics::Magick ref=NO_INIT
7400 ALIAS:
7401 queryformat = 1
7402 PPCODE:
7403 {
7404 char
7405 message[MaxTextExtent],
7406 *name;
7407
7408 ExceptionInfo
7409 exception;
7410
7411 register int
7412 i;
7413
7414 volatile const MagickInfo
7415 *magick_info;
7416
7417 dMY_CXT;
7418 MY_CXT.error_list=newSVpv("",0);
7419 GetExceptionInfo(&exception);
7420 if (items == 1)
7421 {
7422 register volatile const MagickInfo
7423 *p;
7424
7425 magick_info=GetMagickInfo("*",&exception);
7426 if (magick_info == (const MagickInfo *) NULL)
7427 {
7428 PUSHs(&sv_undef);
7429 goto MethodException;
7430 }
7431 i=0;
7432 for (p=magick_info; p != (MagickInfo *) NULL; p=p->next)
7433 i++;
7434 EXTEND(sp,i);
7435 for (p=magick_info; p != (MagickInfo *) NULL; p=p->next)
7436 {
7437 if (p->stealth)
7438 continue;
7439 if (p->name == (char *) NULL)
7440 {
7441 PUSHs(&sv_undef);
7442 continue;
7443 }
7444 (void) strncpy(message,p->name,MaxTextExtent-1);
7445 LocaleLower(message);
7446 PUSHs(sv_2mortal(newSVpv(message,0)));
7447 }
7448 goto MethodException;
7449 }
7450 EXTEND(sp,8*items);
7451 for (i=1; i < items; i++)
7452 {
7453 name=(char *) SvPV(ST(i),na);
7454 magick_info=GetMagickInfo(name,&exception);
7455 if (exception.severity != UndefinedException)
7456 CatchException(&exception);
7457 if (magick_info == (const MagickInfo *) NULL)
7458 {
7459 PUSHs(&sv_undef);
7460 continue;
7461 }
7462 PUSHs(sv_2mortal(newSVpv(magick_info->adjoin ? "1" : "0",0)));
7463 PUSHs(sv_2mortal(newSVpv(magick_info->blob_support ? "1" : "0",0)));
7464 PUSHs(sv_2mortal(newSVpv(magick_info->raw ? "1" : "0",0)));
7465 PUSHs(sv_2mortal(newSVpv(magick_info->decoder ? "1" : "0",0)));
7466 PUSHs(sv_2mortal(newSVpv(magick_info->encoder ? "1" : "0",0)));
7467 if (magick_info->description == (char *) NULL)
7468 PUSHs(&sv_undef);
7469 else
7470 PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
7471 if (magick_info->module == (char *) NULL)
7472 PUSHs(&sv_undef);
7473 else
7474 PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
7475 }
7476 DestroyExceptionInfo(&exception);
7477
7478 MethodException:
7479 SvREFCNT_dec(MY_CXT.error_list);
7480 MY_CXT.error_list=NULL;
7481 }
7482
7483 #
7484 ###############################################################################
7485 # #
7486 # #
7487 # #
7488 # R e a d #
7489 # #
7490 # #
7491 # #
7492 ###############################################################################
7493 #
7494 #
7495 void
Read(ref,...)7496 Read(ref,...)
7497 Graphics::Magick ref=NO_INIT
7498 ALIAS:
7499 ReadImage = 1
7500 read = 2
7501 readimage = 3
7502 PPCODE:
7503 {
7504 AV
7505 *av;
7506
7507 char
7508 **keep,
7509 **list;
7510
7511 ExceptionInfo
7512 exception;
7513
7514 HV
7515 *hv;
7516
7517 Image
7518 *image;
7519
7520 int
7521 ac,
7522 n;
7523
7524 jmp_buf
7525 error_jmp;
7526
7527 register char
7528 **p;
7529
7530 register int
7531 i;
7532
7533 struct PackageInfo
7534 *info,
7535 *package_info;
7536
7537 SV
7538 *reference,
7539 *rv,
7540 *sv;
7541
7542 unsigned int
7543 status;
7544
7545 volatile int
7546 number_images;
7547
7548 dMY_CXT;
7549 MY_CXT.error_list=newSVpv("",0);
7550 package_info=(struct PackageInfo *) NULL;
7551 number_images=0;
7552 ac=(items < 2) ? 1 : items-1;
7553 list=MagickAllocateMemory(char **,(ac+1)*sizeof(*list));
7554 if (!sv_isobject(ST(0)))
7555 {
7556 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
7557 goto ReturnIt;
7558 }
7559 reference=SvRV(ST(0));
7560 hv=SvSTASH(reference);
7561 if (SvTYPE(reference) != SVt_PVAV)
7562 {
7563 MagickError(OptionError,ReferenceIsNotMyType,NULL);
7564 goto ReturnIt;
7565 }
7566 av=(AV *) reference;
7567 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL);
7568 package_info=ClonePackageInfo(info);
7569 n=1;
7570 if (items <= 1)
7571 *list=(char *) (*package_info->image_info->filename ?
7572 package_info->image_info->filename : "XC:black");
7573 else
7574 for (n=0, i=0; i < ac; i++)
7575 {
7576 list[n]=(char *) SvPV(ST(i+1),na);
7577 if ((items >= 3) &&
7578 strEQcase(package_info->image_info->filename,"blob"))
7579 {
7580 STRLEN
7581 length;
7582
7583 i++;
7584 package_info->image_info->blob=(void *) (SvPV(ST(i),length));
7585 package_info->image_info->length=length;
7586 }
7587 if ((items >= 3) && strEQcase(list[n],"filename"))
7588 continue;
7589 if ((items >= 3) && strEQcase(list[n],"file"))
7590 {
7591 package_info->image_info->file=
7592 PerlIO_findFILE(IoIFP(sv_2io(ST(i+2))));
7593 continue;
7594 }
7595 n++;
7596 }
7597 list[n]=(char *) NULL;
7598 keep=list;
7599 MY_CXT.error_jump=(&error_jmp);
7600 if (setjmp(error_jmp))
7601 goto ReturnIt;
7602 status=ExpandFilenames(&n,&list);
7603 if (status == False)
7604 {
7605 MagickError(ResourceLimitError,MemoryAllocationFailed,NULL);
7606 goto ReturnIt;
7607 }
7608 GetExceptionInfo(&exception);
7609 number_images=0;
7610 for (i=0; i < n; i++)
7611 {
7612 (void) strncpy(package_info->image_info->filename,list[i],
7613 MaxTextExtent-1);
7614 image=ReadImage(package_info->image_info,&exception);
7615 if (exception.severity != UndefinedException)
7616 CatchException(&exception);
7617 for ( ; image; image=image->next)
7618 {
7619 sv=newSViv((IV) (magick_uintptr_t)image);
7620 rv=newRV(sv);
7621 av_push(av,sv_bless(rv,hv));
7622 SvREFCNT_dec(sv);
7623 number_images++;
7624 }
7625 }
7626 DestroyExceptionInfo(&exception);
7627 /*
7628 Free resources.
7629 */
7630 for (i=0; i < n; i++)
7631 if (list[i])
7632 for (p=keep; list[i] != *p++; )
7633 if (*p == NULL)
7634 {
7635 MagickFreeMemory(list[i]);
7636 break;
7637 }
7638
7639 ReturnIt:
7640 if (package_info)
7641 DestroyPackageInfo(package_info);
7642 MagickFreeMemory(list);
7643 sv_setiv(MY_CXT.error_list,(IV) number_images);
7644 SvPOK_on(MY_CXT.error_list);
7645 ST(0)=sv_2mortal(MY_CXT.error_list);
7646 MY_CXT.error_list=NULL;
7647 MY_CXT.error_jump=NULL;
7648 XSRETURN(1);
7649 }
7650
7651 #
7652 ###############################################################################
7653 # #
7654 # #
7655 # #
7656 # R e m o t e #
7657 # #
7658 # #
7659 # #
7660 ###############################################################################
7661 #
7662 #
7663 void
Remote(ref,...)7664 Remote(ref,...)
7665 Graphics::Magick ref=NO_INIT
7666 ALIAS:
7667 RemoteCommand = 1
7668 remote = 2
7669 remoteCommand = 3
7670 PPCODE:
7671 {
7672 AV
7673 *av;
7674
7675 SV
7676 *reference;
7677
7678 /*struct PackageInfo
7679 *info;*/
7680
7681 dMY_CXT;
7682 MY_CXT.error_list=newSVpv("",0);
7683 reference=SvRV(ST(0));
7684 av=(AV *) reference;
7685 /*info=*/GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL);
7686 #if defined(XlibSpecificationRelease)
7687 {
7688 Display
7689 *display;
7690
7691 register int
7692 i;
7693
7694 display=XOpenDisplay(info->image_info->server_name);
7695 for (i=1; i < items; i++)
7696 XRemoteCommand(display,(char *) NULL,(char *) SvPV(ST(i),na));
7697 }
7698 #endif
7699 SvREFCNT_dec(MY_CXT.error_list); /* throw away all errors */
7700 MY_CXT.error_list=NULL;
7701 }
7702
7703 #
7704 ###############################################################################
7705 # #
7706 # #
7707 # #
7708 # S e t #
7709 # #
7710 # #
7711 # #
7712 ###############################################################################
7713 #
7714 #
7715 void
Set(ref,...)7716 Set(ref,...)
7717 Graphics::Magick ref=NO_INIT
7718 ALIAS:
7719 SetAttributes = 1
7720 SetAttribute = 2
7721 set = 3
7722 setattributes = 4
7723 setattribute = 5
7724 PPCODE:
7725 {
7726 Image
7727 *image;
7728
7729 register int
7730 i;
7731
7732 struct PackageInfo
7733 *info;
7734
7735 SV
7736 *reference; /* reference is the SV* of ref=SvIV(reference) */
7737
7738 dMY_CXT;
7739 MY_CXT.error_list=newSVpv("",0);
7740 if (!sv_isobject(ST(0)))
7741 {
7742 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
7743 goto MethodException;
7744 }
7745 reference=SvRV(ST(0));
7746 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
7747 if (items == 2)
7748 SetAttribute(aTHX_ info,image,"size",ST(1));
7749 else
7750 for (i=2; i < items; i+=2)
7751 SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i));
7752
7753 MethodException:
7754 sv_setiv(MY_CXT.error_list,(IV) (SvCUR(MY_CXT.error_list) != 0));
7755 SvPOK_on(MY_CXT.error_list);
7756 ST(0)=sv_2mortal(MY_CXT.error_list);
7757 MY_CXT.error_list=NULL;
7758 XSRETURN(1);
7759 }
7760
7761 #
7762 ###############################################################################
7763 # #
7764 # #
7765 # #
7766 # T r a n s f o r m #
7767 # #
7768 # #
7769 # #
7770 ###############################################################################
7771 #
7772 #
7773 void
Transform(ref,...)7774 Transform(ref,...)
7775 Graphics::Magick ref=NO_INIT
7776 ALIAS:
7777 TransformImage = 1
7778 transform = 2
7779 transformimage = 3
7780 PPCODE:
7781 {
7782 AV
7783 *av;
7784
7785 char
7786 *attribute,
7787 *crop_geometry,
7788 *geometry;
7789
7790 ExceptionInfo
7791 exception;
7792
7793 HV
7794 *hv;
7795
7796 Image
7797 *clone,
7798 *image;
7799
7800 jmp_buf
7801 error_jmp;
7802
7803 register int
7804 i;
7805
7806 struct PackageInfo
7807 *info;
7808
7809 SV
7810 *av_reference,
7811 *reference,
7812 *rv,
7813 *sv;
7814
7815 volatile int
7816 status;
7817
7818 dMY_CXT;
7819 MY_CXT.error_list=newSVpv("",0);
7820 av=NULL;
7821 status=0;
7822 attribute=NULL;
7823 if (!sv_isobject(ST(0)))
7824 {
7825 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
7826 goto MethodException;
7827 }
7828 reference=SvRV(ST(0));
7829 hv=SvSTASH(reference);
7830 av=newAV();
7831 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7832 SvREFCNT_dec(av);
7833 MY_CXT.error_jump=(&error_jmp);
7834 status=setjmp(error_jmp);
7835 if (status)
7836 goto MethodException;
7837 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
7838 if (!image)
7839 {
7840 MagickError(OptionError,NoImagesDefined,NULL);
7841 goto MethodException;
7842 }
7843 info=GetPackageInfo(aTHX_ (void *) av,info);
7844 /*
7845 Get attribute.
7846 */
7847 crop_geometry=(char *) NULL;
7848 geometry=(char *) NULL;
7849 for (i=2; i < items; i+=2)
7850 {
7851 attribute=(char *) SvPV(ST(i-1),na);
7852 switch (*attribute)
7853 {
7854 case 'c':
7855 case 'C':
7856 {
7857 if (LocaleCompare(attribute,"crop") == 0)
7858 {
7859 crop_geometry=SvPV(ST(i),na);
7860 break;
7861 }
7862 MagickError(OptionError,UnrecognizedAttribute,attribute);
7863 break;
7864 }
7865 case 'g':
7866 case 'G':
7867 {
7868 if (LocaleCompare(attribute,"geometry") == 0)
7869 {
7870 geometry=SvPV(ST(i),na);
7871 break;
7872 }
7873 MagickError(OptionError,UnrecognizedAttribute,attribute);
7874 break;
7875 }
7876 default:
7877 {
7878 MagickError(OptionError,UnrecognizedAttribute,attribute);
7879 break;
7880 }
7881 }
7882 }
7883 GetExceptionInfo(&exception);
7884 for ( ; image; image=image->next)
7885 {
7886 clone=CloneImage(image,0,0,True,&exception);
7887 if (exception.severity != UndefinedException)
7888 CatchException(&exception);
7889 if (clone == (Image *) NULL)
7890 goto MethodException;
7891 TransformImage(&clone,crop_geometry,geometry);
7892 (void) CatchImageException(clone);
7893 for ( ; clone; clone=clone->next)
7894 {
7895 sv=newSViv((IV) (magick_uintptr_t)clone);
7896 rv=newRV(sv);
7897 av_push(av,sv_bless(rv,hv));
7898 SvREFCNT_dec(sv);
7899 }
7900 }
7901 DestroyExceptionInfo(&exception);
7902 ST(0)=av_reference;
7903 MY_CXT.error_jump=NULL;
7904 SvREFCNT_dec(MY_CXT.error_list); /* can't return warning messages */
7905 MY_CXT.error_list=NULL;
7906 XSRETURN(1);
7907
7908 MethodException:
7909 MY_CXT.error_jump=NULL;
7910 sv_setiv(MY_CXT.error_list,(IV) (status ? status : SvCUR(MY_CXT.error_list) != 0));
7911 SvPOK_on(MY_CXT.error_list);
7912 ST(0)=sv_2mortal(MY_CXT.error_list);
7913 MY_CXT.error_list=NULL;
7914 MY_CXT.error_jump=NULL;
7915 XSRETURN(1);
7916 }
7917
7918 #
7919 ###############################################################################
7920 # #
7921 # #
7922 # #
7923 # W r i t e #
7924 # #
7925 # #
7926 # #
7927 ###############################################################################
7928 #
7929 #
7930 void
Write(ref,...)7931 Write(ref,...)
7932 Graphics::Magick ref=NO_INIT
7933 ALIAS:
7934 WriteImage = 1
7935 write = 2
7936 writeimage = 3
7937 PPCODE:
7938 {
7939 char
7940 filename[MaxTextExtent];
7941
7942 Image
7943 *image,
7944 *next;
7945
7946 int
7947 scene;
7948
7949 register int
7950 i;
7951
7952 jmp_buf
7953 error_jmp;
7954
7955 struct PackageInfo
7956 *info,
7957 *package_info;
7958
7959 SV
7960 *reference;
7961
7962 volatile int
7963 number_images;
7964
7965 dMY_CXT;
7966 MY_CXT.error_list=newSVpv("",0);
7967 number_images=0;
7968 package_info=(struct PackageInfo *) NULL;
7969 if (!sv_isobject(ST(0)))
7970 {
7971 MagickError(OptionError,ReferenceIsNotMyType,PackageName);
7972 goto MethodException;
7973 }
7974 reference=SvRV(ST(0));
7975 MY_CXT.error_jump=(&error_jmp);
7976 if (setjmp(error_jmp))
7977 goto MethodException;
7978 image=SetupList(aTHX_ reference,&info,(SV ***) NULL);
7979 if (!image)
7980 {
7981 MagickError(OptionError,NoImagesDefined,NULL);
7982 goto MethodException;
7983 }
7984 package_info=ClonePackageInfo(info);
7985 if (items == 2)
7986 SetAttribute(aTHX_ package_info,NULL,"filename",ST(1));
7987 else
7988 if (items > 2)
7989 for (i=2; i < items; i+=2)
7990 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i));
7991 (void) strncpy(filename,package_info->image_info->filename,MaxTextExtent-1);
7992 scene=0;
7993 for (next=image; next; next=next->next)
7994 {
7995 (void) strncpy(next->filename,filename,MaxTextExtent-1);
7996 next->scene=scene++;
7997 }
7998 (void) SetImageInfo(package_info->image_info,
7999 (SETMAGICK_WRITE |
8000 (!package_info->image_info->adjoin ? SETMAGICK_RECTIFY: 0U)),
8001 &image->exception);
8002 for (next=image; next; next=next->next)
8003 {
8004 (void) WriteImage(package_info->image_info,next);
8005 (void) CatchImageException(next);
8006 number_images++;
8007 if (package_info->image_info->adjoin)
8008 break;
8009 }
8010 package_info->image_info->file=(FILE *) NULL;
8011
8012 MethodException:
8013 if (package_info)
8014 DestroyPackageInfo(package_info);
8015 sv_setiv(MY_CXT.error_list,(IV) number_images);
8016 SvPOK_on(MY_CXT.error_list);
8017 ST(0)=sv_2mortal(MY_CXT.error_list);
8018 MY_CXT.error_list=NULL;
8019 MY_CXT.error_jump=NULL;
8020 XSRETURN(1);
8021 }
8022
8023 # Local Variables:
8024 # mode: c
8025 # c-basic-offset: 2
8026 # fill-column: 78
8027 # End:
8028