blob: 7633093e6264f1991bd6d156ad1d2d4dd1659f2a [file] [log] [blame]
cristy4a3ce0a2013-08-03 20:06:59 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% PPPP EEEEE RRRR L %
6% P P E R R L %
7% PPPP EEE RRRR L %
8% P E R R L %
9% P EEEEE R R LLLLL %
10% %
11% M M AAA GGGG IIIII CCCC K K %
12% MM MM A A G I C K K %
13% M M M AAAAA G GGG I C KKK %
14% M M A A G G I C K K %
15% M M A A GGGG IIIII CCCC K K %
16% %
17% %
18% Object-oriented Perl interface to ImageMagick %
19% %
20% Software Design %
21% Kyle Shorter %
cristyde984cd2013-12-01 14:49:27 +000022% Cristy %
cristy4a3ce0a2013-08-03 20:06:59 +000023% February 1997 %
24% %
25% %
Cristy93b707b2017-12-06 07:05:51 -050026% Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
cristy4a3ce0a2013-08-03 20:06:59 +000027% dedicated to making software imaging solutions freely available. %
28% %
29% You may not use this file except in compliance with the License. You may %
30% obtain a copy of the License at %
31% %
32% http://www.imagemagick.org/script/license.php %
33% %
34% Unless required by applicable law or agreed to in writing, software %
35% distributed under the License is distributed on an "AS IS" BASIS, %
36% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
37% See the License for the specific language governing permissions and %
38% limitations under the License. %
39% %
40%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41%
42% PerlMagick is an objected-oriented Perl interface to ImageMagick. Use
43% the module to read, manipulate, or write an image or image sequence from
44% within a Perl script. This makes PerlMagick suitable for Web CGI scripts.
45%
46*/
47
48/*
49 Include declarations.
50*/
51#if defined(__cplusplus) || defined(c_plusplus)
52extern "C" {
53#endif
54
55#define PERL_NO_GET_CONTEXT
dirk190cc1c2015-06-16 11:48:37 +000056#include <MagickCore/MagickCore.h>
cristy4a3ce0a2013-08-03 20:06:59 +000057#include "EXTERN.h"
58#include "perl.h"
59#include "XSUB.h"
60#include <math.h>
cristy4a3ce0a2013-08-03 20:06:59 +000061#undef tainted
62
63#if defined(__cplusplus) || defined(c_plusplus)
64}
65#endif
66
67/*
68 Define declarations.
69*/
70#ifndef aTHX_
71#define aTHX_
72#define pTHX_
73#define dTHX
74#endif
75#define DegreesToRadians(x) (MagickPI*(x)/180.0)
76#define EndOf(array) (&array[NumberOf(array)])
cristy3249b7b2014-02-09 21:43:14 +000077#define MagickPI 3.14159265358979323846264338327950288419716939937510
cristy4a3ce0a2013-08-03 20:06:59 +000078#define MaxArguments 33
79#ifndef na
80#define na PL_na
81#endif
82#define NumberOf(array) (sizeof(array)/sizeof(*array))
83#define PackageName "Image::Magick"
84#if PERL_VERSION <= 6
85#define PerlIO FILE
86#define PerlIO_importFILE(f, fl) (f)
87#define PerlIO_findFILE(f) NULL
88#endif
89#ifndef sv_undef
90#define sv_undef PL_sv_undef
91#endif
92
93#define AddImageToRegistry(sv,image) \
94{ \
95 if (magick_registry != (SplayTreeInfo *) NULL) \
96 { \
97 (void) AddValueToSplayTree(magick_registry,image,image); \
98 (sv)=newSViv(PTR2IV(image)); \
99 } \
100}
101
102#define DeleteImageFromRegistry(reference,image) \
103{ \
104 if (magick_registry != (SplayTreeInfo *) NULL) \
105 { \
106 if (GetImageReferenceCount(image) == 1) \
107 (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
108 image=DestroyImage(image); \
109 sv_setiv(reference,0); \
110 } \
111}
112
113#define InheritPerlException(exception,perl_exception) \
114{ \
115 char \
cristy151b66d2015-04-15 10:50:31 +0000116 message[MagickPathExtent]; \
cristy4a3ce0a2013-08-03 20:06:59 +0000117 \
118 if ((exception)->severity != UndefinedException) \
119 { \
cristy151b66d2015-04-15 10:50:31 +0000120 (void) FormatLocaleString(message,MagickPathExtent,"Exception %d: %s%s%s%s",\
cristy4a3ce0a2013-08-03 20:06:59 +0000121 (exception)->severity, (exception)->reason ? \
122 GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
123 "Unknown", (exception)->description ? " (" : "", \
124 (exception)->description ? GetLocaleExceptionMessage( \
125 (exception)->severity,(exception)->description) : "", \
126 (exception)->description ? ")" : ""); \
127 if ((perl_exception) != (SV *) NULL) \
128 { \
129 if (SvCUR(perl_exception)) \
130 sv_catpv(perl_exception,"\n"); \
131 sv_catpv(perl_exception,message); \
132 } \
133 } \
134}
135
136#define ThrowPerlException(exception,severity,tag,reason) \
137 (void) ThrowMagickException(exception,GetMagickModule(),severity, \
138 tag,"`%s'",reason); \
139
140/*
141 Typedef and structure declarations.
142*/
143typedef enum
144{
Cristya9a04772018-01-16 11:44:34 -0500145 NullReference = 0,
cristy4a3ce0a2013-08-03 20:06:59 +0000146 ArrayReference = (~0),
147 RealReference = (~0)-1,
148 FileReference = (~0)-2,
149 ImageReference = (~0)-3,
150 IntegerReference = (~0)-4,
151 StringReference = (~0)-5
152} MagickReference;
153
154typedef struct _Arguments
155{
156 const char
157 *method;
158
159 ssize_t
160 type;
161} Arguments;
162
163struct ArgumentList
164{
165 ssize_t
166 integer_reference;
167
168 double
169 real_reference;
170
171 const char
172 *string_reference;
173
174 Image
175 *image_reference;
176
177 SV
178 *array_reference;
179
180 FILE
181 *file_reference;
182
183 size_t
184 length;
185};
186
187struct PackageInfo
188{
189 ImageInfo
190 *image_info;
191};
192
193typedef void
194 *Image__Magick; /* data type for the Image::Magick package */
195
196/*
197 Static declarations.
198*/
199static struct
200 Methods
201 {
202 const char
203 *name;
204
205 Arguments
206 arguments[MaxArguments];
207 } Methods[] =
208 {
209 { "Comment", { {"comment", StringReference} } },
210 { "Label", { {"label", StringReference} } },
211 { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
212 {"channel", MagickChannelOptions} } },
213 { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
214 { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
215 {"height", IntegerReference}, {"fill", StringReference},
216 {"bordercolor", StringReference}, {"color", StringReference},
217 {"compose", MagickComposeOptions} } },
218 { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
219 {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
220 { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
221 {"height", IntegerReference}, {"x", IntegerReference},
cristy260bd762014-08-15 12:46:34 +0000222 {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000223 { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
224 {"height", IntegerReference}, {"x", IntegerReference},
225 {"y", IntegerReference}, {"fuzz", StringReference},
226 {"gravity", MagickGravityOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500227 { "Despeckle", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000228 { "Edge", { {"radius", RealReference} } },
229 { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
230 {"sigma", RealReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500231 { "Enhance", { { (const char *) NULL, NullReference } } },
232 { "Flip", { { (const char *) NULL, NullReference } } },
233 { "Flop", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000234 { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
235 {"height", IntegerReference}, {"inner", IntegerReference},
236 {"outer", IntegerReference}, {"fill", StringReference},
237 {"color", StringReference}, {"compose", MagickComposeOptions} } },
238 { "Implode", { {"amount", RealReference},
239 {"interpolate", MagickInterpolateOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500240 { "Magnify", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000241 { "MedianFilter", { {"geometry", StringReference},
242 {"width", IntegerReference}, {"height", IntegerReference},
243 {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500244 { "Minify", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000245 { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
246 { "ReduceNoise", { {"geometry", StringReference},
247 {"width", IntegerReference},{"height", IntegerReference},
248 {"channel", MagickChannelOptions} } },
249 { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
250 {"y", IntegerReference} } },
cristy83a28a02013-08-03 20:25:48 +0000251 { "Rotate", { {"degrees", RealReference},
cristy4a3ce0a2013-08-03 20:06:59 +0000252 {"background", StringReference} } },
253 { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
254 {"height", IntegerReference} } },
255 { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
256 {"height", IntegerReference} } },
257 { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
258 {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
259 { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
260 {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
261 { "Shear", { {"geometry", StringReference}, {"x", RealReference},
262 {"y", RealReference}, { "fill", StringReference},
263 {"color", StringReference} } },
Cristye3319c12015-08-24 07:11:48 -0400264 { "Spread", { {"radius", RealReference},
Cristy3ca633e2016-02-13 12:49:01 -0500265 {"interpolate", MagickInterpolateOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000266 { "Swirl", { {"degrees", RealReference},
267 {"interpolate", MagickInterpolateOptions} } },
268 { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
269 {"height", IntegerReference}, {"filter", MagickFilterOptions},
270 {"support", StringReference } } },
271 { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
272 {"height", IntegerReference}, {"filter", MagickFilterOptions},
273 {"support", RealReference } } },
274 { "Annotate", { {"text", StringReference}, {"font", StringReference},
275 {"pointsize", RealReference}, {"density", StringReference},
276 {"undercolor", StringReference}, {"stroke", StringReference},
277 {"fill", StringReference}, {"geometry", StringReference},
278 {"sans", StringReference}, {"x", RealReference},
279 {"y", RealReference}, {"gravity", MagickGravityOptions},
280 {"translate", StringReference}, {"scale", StringReference},
281 {"rotate", RealReference}, {"skewX", RealReference},
282 {"skewY", RealReference}, {"strokewidth", RealReference},
283 {"antialias", MagickBooleanOptions}, {"family", StringReference},
284 {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
285 {"weight", IntegerReference}, {"align", MagickAlignOptions},
286 {"encoding", StringReference}, {"affine", ArrayReference},
287 {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
288 {"tile", ImageReference}, {"kerning", RealReference},
289 {"interline-spacing", RealReference},
290 {"interword-spacing", RealReference},
291 {"direction", MagickDirectionOptions} } },
292 { "ColorFloodfill", { {"geometry", StringReference},
293 {"x", IntegerReference}, {"y", IntegerReference},
294 {"fill", StringReference}, {"bordercolor", StringReference},
295 {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
296 { "Composite", { {"image", ImageReference},
297 {"compose", MagickComposeOptions}, {"geometry", StringReference},
298 {"x", IntegerReference}, {"y", IntegerReference},
299 {"gravity", MagickGravityOptions}, {"opacity", StringReference},
300 {"tile", MagickBooleanOptions}, {"rotate", RealReference},
301 {"color", StringReference}, {"mask", ImageReference},
302 {"channel", MagickChannelOptions},
303 {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
Cristy74e39292018-07-08 13:13:20 -0400304 {"blend", StringReference}, {"clip-to-self", MagickBooleanOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000305 { "Contrast", { {"sharpen", MagickBooleanOptions} } },
306 { "CycleColormap", { {"display", IntegerReference} } },
307 { "Draw", { {"primitive", MagickPrimitiveOptions},
308 {"points", StringReference}, {"method", MagickMethodOptions},
309 {"stroke", StringReference}, {"fill", StringReference},
310 {"strokewidth", RealReference}, {"font", StringReference},
311 {"bordercolor", StringReference}, {"x", RealReference},
312 {"y", RealReference}, {"translate", StringReference},
313 {"scale", StringReference}, {"rotate", RealReference},
314 {"skewX", RealReference}, {"skewY", RealReference},
315 {"tile", ImageReference}, {"pointsize", RealReference},
316 {"antialias", MagickBooleanOptions}, {"density", StringReference},
317 {"linewidth", RealReference}, {"affine", ArrayReference},
318 {"stroke-dashoffset", RealReference},
319 {"stroke-dasharray", ArrayReference},
320 {"interpolate", MagickInterpolateOptions},
321 {"origin", StringReference}, {"text", StringReference},
322 {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
323 {"vector-graphics", StringReference}, {"kerning", RealReference},
324 {"interline-spacing", RealReference},
325 {"interword-spacing", RealReference},
326 {"direction", MagickDirectionOptions} } },
327 { "Equalize", { {"channel", MagickChannelOptions} } },
328 { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
329 {"red", RealReference}, {"green", RealReference},
330 {"blue", RealReference} } },
331 { "Map", { {"image", ImageReference},
332 {"dither-method", MagickDitherOptions} } },
333 { "MatteFloodfill", { {"geometry", StringReference},
334 {"x", IntegerReference}, {"y", IntegerReference},
335 {"opacity", StringReference}, {"bordercolor", StringReference},
336 {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
337 { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
338 {"saturation", RealReference}, {"whiteness", RealReference},
339 {"brightness", RealReference}, {"lightness", RealReference},
340 {"blackness", RealReference} } },
341 { "Negate", { {"gray", MagickBooleanOptions},
342 {"channel", MagickChannelOptions} } },
343 { "Normalize", { {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500344 { "NumberColors", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000345 { "Opaque", { {"color", StringReference}, {"fill", StringReference},
346 {"fuzz", StringReference}, {"channel", MagickChannelOptions},
347 {"invert", MagickBooleanOptions} } },
348 { "Quantize", { {"colors", IntegerReference},
349 {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
350 {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
351 {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
352 {"dither-method", MagickDitherOptions} } },
353 { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
354 {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
355 { "Segment", { {"geometry", StringReference},
356 {"cluster-threshold", RealReference},
357 {"smoothing-threshold", RealReference},
358 {"colorspace", MagickColorspaceOptions},
359 {"verbose", MagickBooleanOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500360 { "Signature", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000361 { "Solarize", { {"geometry", StringReference},
362 {"threshold", StringReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500363 { "Sync", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000364 { "Texture", { {"texture", ImageReference} } },
365 { "Evaluate", { {"value", RealReference},
366 {"operator", MagickEvaluateOptions},
367 {"channel", MagickChannelOptions} } },
368 { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
369 {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
370 { "Threshold", { {"threshold", StringReference},
371 {"channel", MagickChannelOptions} } },
372 { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
373 {"sigma", RealReference} } },
374 { "Trim", { {"fuzz", StringReference} } },
375 { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
376 {"wavelength", RealReference},
377 {"interpolate", MagickInterpolateOptions} } },
378 { "Separate", { {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500379 { "Condense", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000380 { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
381 {"y", IntegerReference} } },
382 { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500383 { "Deconstruct", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000384 { "GaussianBlur", { {"geometry", StringReference},
385 {"radius", RealReference}, {"sigma", RealReference},
386 {"channel", MagickChannelOptions} } },
387 { "Convolve", { {"coefficients", ArrayReference},
388 {"channel", MagickChannelOptions}, {"bias", StringReference},
389 {"kernel", StringReference} } },
390 { "Profile", { {"name", StringReference}, {"profile", StringReference},
391 { "rendering-intent", MagickIntentOptions},
392 { "black-point-compensation", MagickBooleanOptions} } },
393 { "UnsharpMask", { {"geometry", StringReference},
394 {"radius", RealReference}, {"sigma", RealReference},
395 {"gain", RealReference}, {"threshold", RealReference},
396 {"channel", MagickChannelOptions} } },
397 { "MotionBlur", { {"geometry", StringReference},
398 {"radius", RealReference}, {"sigma", RealReference},
399 {"angle", RealReference}, {"channel", MagickChannelOptions} } },
400 { "OrderedDither", { {"threshold", StringReference},
401 {"channel", MagickChannelOptions} } },
402 { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
403 {"height", IntegerReference} } },
404 { "Level", { {"levels", StringReference}, {"black-point", RealReference},
405 {"white-point", RealReference}, {"gamma", RealReference},
406 {"channel", MagickChannelOptions}, {"level", StringReference} } },
407 { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
408 { "AffineTransform", { {"affine", ArrayReference},
409 {"translate", StringReference}, {"scale", StringReference},
410 {"rotate", RealReference}, {"skewX", RealReference},
411 {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
412 {"background", StringReference} } },
413 { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
414 { "AdaptiveThreshold", { {"geometry", StringReference},
415 {"width", IntegerReference}, {"height", IntegerReference} } },
416 { "Resample", { {"density", StringReference}, {"x", RealReference},
417 {"y", RealReference}, {"filter", MagickFilterOptions},
418 {"support", RealReference } } },
419 { "Describe", { {"file", FileReference} } },
420 { "BlackThreshold", { {"threshold", StringReference},
421 {"channel", MagickChannelOptions} } },
422 { "WhiteThreshold", { {"threshold", StringReference},
423 {"channel", MagickChannelOptions} } },
cristy60c73c02014-03-25 12:09:58 +0000424 { "RotationalBlur", { {"geometry", StringReference},
425 {"angle", RealReference}, {"channel", MagickChannelOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000426 { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
427 {"height", IntegerReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500428 { "Strip", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000429 { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
430 { "Channel", { {"channel", MagickChannelOptions} } },
431 { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
432 {"height", IntegerReference}, {"x", IntegerReference},
433 {"y", IntegerReference}, {"fuzz", StringReference},
434 {"background", StringReference}, {"gravity", MagickGravityOptions} } },
435 { "Posterize", { {"levels", IntegerReference},
436 {"dither", MagickBooleanOptions} } },
437 { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
438 {"sigma", RealReference}, {"x", IntegerReference},
439 {"y", IntegerReference} } },
440 { "Identify", { {"file", FileReference}, {"features", StringReference},
441 {"unique", MagickBooleanOptions} } },
442 { "SepiaTone", { {"threshold", RealReference} } },
443 { "SigmoidalContrast", { {"geometry", StringReference},
444 {"contrast", RealReference}, {"mid-point", RealReference},
445 {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
446 { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
447 {"height", IntegerReference}, {"x", IntegerReference},
448 {"y", IntegerReference}, {"fuzz", StringReference},
449 {"background", StringReference}, {"gravity", MagickGravityOptions} } },
450 { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
451 {"sigma", RealReference}, {"x", IntegerReference},
452 {"y", IntegerReference}, {"background", StringReference} } },
453 { "ContrastStretch", { {"levels", StringReference},
454 {"black-point", RealReference},{"white-point", RealReference},
455 {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500456 { "Sans0", { { (const char *) NULL, NullReference } } },
457 { "Sans1", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000458 { "AdaptiveSharpen", { {"geometry", StringReference},
459 {"radius", RealReference}, {"sigma", RealReference},
460 {"bias", RealReference}, {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500461 { "Transpose", { { (const char *) NULL, NullReference } } },
462 { "Transverse", { { (const char *) NULL, NullReference } } },
463 { "AutoOrient", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000464 { "AdaptiveBlur", { {"geometry", StringReference},
465 {"radius", RealReference}, {"sigma", RealReference},
466 {"channel", MagickChannelOptions} } },
467 { "Sketch", { {"geometry", StringReference},
468 {"radius", RealReference}, {"sigma", RealReference},
469 {"angle", RealReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500470 { "UniqueColors", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000471 { "AdaptiveResize", { {"geometry", StringReference},
472 {"width", IntegerReference}, {"height", IntegerReference},
473 {"filter", MagickFilterOptions}, {"support", StringReference },
474 {"blur", RealReference } } },
475 { "ClipMask", { {"mask", ImageReference} } },
476 { "LinearStretch", { {"levels", StringReference},
477 {"black-point", RealReference},{"white-point", RealReference} } },
478 { "ColorMatrix", { {"matrix", ArrayReference} } },
479 { "Mask", { {"mask", ImageReference} } },
480 { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
481 {"font", StringReference}, {"stroke", StringReference},
482 {"fill", StringReference}, {"strokewidth", RealReference},
483 {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
484 {"background", StringReference},
485 {"interpolate", MagickInterpolateOptions} } },
486 { "FloodfillPaint", { {"geometry", StringReference},
487 {"x", IntegerReference}, {"y", IntegerReference},
488 {"fill", StringReference}, {"bordercolor", StringReference},
489 {"fuzz", StringReference}, {"channel", MagickChannelOptions},
490 {"invert", MagickBooleanOptions} } },
491 { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
492 {"virtual-pixel", MagickVirtualPixelOptions},
493 {"best-fit", MagickBooleanOptions} } },
494 { "Clut", { {"image", ImageReference},
495 {"interpolate", MagickInterpolateOptions},
496 {"channel", MagickChannelOptions} } },
497 { "LiquidRescale", { {"geometry", StringReference},
498 {"width", IntegerReference}, {"height", IntegerReference},
499 {"delta-x", RealReference}, {"rigidity", RealReference } } },
500 { "Encipher", { {"passphrase", StringReference} } },
501 { "Decipher", { {"passphrase", StringReference} } },
502 { "Deskew", { {"geometry", StringReference},
503 {"threshold", StringReference} } },
504 { "Remap", { {"image", ImageReference},
505 {"dither-method", MagickDitherOptions} } },
506 { "SparseColor", { {"points", ArrayReference},
507 {"method", MagickSparseColorOptions},
508 {"virtual-pixel", MagickVirtualPixelOptions},
509 {"channel", MagickChannelOptions} } },
510 { "Function", { {"parameters", ArrayReference},
511 {"function", MagickFunctionOptions},
512 {"virtual-pixel", MagickVirtualPixelOptions} } },
513 { "SelectiveBlur", { {"geometry", StringReference},
514 {"radius", RealReference}, {"sigma", RealReference},
515 {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
516 { "HaldClut", { {"image", ImageReference},
517 {"channel", MagickChannelOptions} } },
518 { "BlueShift", { {"factor", StringReference} } },
519 { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520 { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
521 { "ColorDecisionList", {
522 {"color-correction-collection", StringReference} } },
523 { "AutoGamma", { {"channel", MagickChannelOptions} } },
524 { "AutoLevel", { {"channel", MagickChannelOptions} } },
525 { "LevelColors", { {"invert", MagickBooleanOptions},
526 {"black-point", StringReference}, {"white-point", StringReference},
527 {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
528 { "Clamp", { {"channel", MagickChannelOptions} } },
529 { "BrightnessContrast", { {"levels", StringReference},
530 {"brightness", RealReference},{"contrast", RealReference},
531 {"channel", MagickChannelOptions} } },
532 { "Morphology", { {"kernel", StringReference},
533 {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
534 {"iterations", IntegerReference} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000535 { "Mode", { {"geometry", StringReference},
536 {"width", IntegerReference},{"height", IntegerReference},
537 {"channel", MagickChannelOptions} } },
538 { "Statistic", { {"geometry", StringReference},
539 {"width", IntegerReference},{"height", IntegerReference},
540 {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
541 { "Perceptible", { {"epsilon", RealReference},
542 {"channel", MagickChannelOptions} } },
543 { "Poly", { {"terms", ArrayReference},
544 {"channel", MagickChannelOptions} } },
545 { "Grayscale", { {"method", MagickNoiseOptions} } },
cristy4ceadb82014-03-29 15:30:43 +0000546 { "CannyEdge", { {"geometry", StringReference},
547 {"radius", RealReference}, {"sigma", RealReference},
cristycfe7bf02014-04-04 15:31:52 +0000548 {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
cristy2fc10e52014-04-26 14:13:53 +0000549 { "HoughLine", { {"geometry", StringReference},
cristy4e215022014-04-19 18:02:35 +0000550 {"width", IntegerReference}, {"height", IntegerReference},
551 {"threshold", IntegerReference} } },
cristy2fc10e52014-04-26 14:13:53 +0000552 { "MeanShift", { {"geometry", StringReference},
553 {"width", IntegerReference}, {"height", IntegerReference},
cristy1309fc32014-04-26 18:48:37 +0000554 {"distance", RealReference} } },
cristy3b207f82014-09-27 14:21:20 +0000555 { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
556 {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
Cristy2ca0e9a2016-01-01 08:36:14 -0500557 { "ConnectedComponents", { {"connectivity", IntegerReference} } },
cristyf3a724a2015-06-25 13:02:53 +0000558 { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
559 {"width", IntegerReference}, {"height", IntegerReference},
560 {"x", IntegerReference}, {"y", IntegerReference},
Cristy532b3382018-08-05 17:56:56 -0400561 {"gravity", MagickGravityOptions}, {"offset", StringReference},
cristyf3a724a2015-06-25 13:02:53 +0000562 {"dx", IntegerReference}, {"dy", IntegerReference} } },
Cristy5488c982016-02-13 14:07:50 -0500563 { "Color", { {"color", StringReference} } },
Cristyc1759412016-02-27 12:17:58 -0500564 { "WaveletDenoise", { {"geometry", StringReference},
565 {"threshold", RealReference}, {"softness", RealReference},
Cristy2d830ed2016-02-21 10:54:16 -0500566 {"channel", MagickChannelOptions} } },
Cristy99a57162016-12-05 11:47:57 -0500567 { "Colorspace", { {"colorspace", MagickColorspaceOptions} } },
Cristy53353872017-07-02 12:24:24 -0400568 { "AutoThreshold", { {"method", MagickAutoThresholdOptions} } },
Cristy532b3382018-08-05 17:56:56 -0400569 { "RangeThreshold", { {"geometry", StringReference},
570 {"low-soft", RealReference}, {"high-soft", RealReference},
571 {"low-hard", RealReference}, {"high-hard", RealReference},
572 {"channel", MagickChannelOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000573 };
574
575static SplayTreeInfo
576 *magick_registry = (SplayTreeInfo *) NULL;
577
578/*
579 Forward declarations.
580*/
581static Image
582 *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
583
584static ssize_t
585 strEQcase(const char *,const char *);
586
587/*
588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589% %
590% %
591% %
592% C l o n e P a c k a g e I n f o %
593% %
594% %
595% %
596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597%
598% ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
599% a new one.
600%
601% The format of the ClonePackageInfo routine is:
602%
603% struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
604% exception)
605%
606% A description of each parameter follows:
607%
608% o info: a structure of type info.
609%
610% o exception: Return any errors or warnings in this structure.
611%
612*/
613static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
614 ExceptionInfo *exception)
615{
616 struct PackageInfo
617 *clone_info;
618
619 clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
620 if (clone_info == (struct PackageInfo *) NULL)
621 {
622 ThrowPerlException(exception,ResourceLimitError,
623 "UnableToClonePackageInfo",PackageName);
624 return((struct PackageInfo *) NULL);
625 }
626 if (info == (struct PackageInfo *) NULL)
627 {
628 clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
629 return(clone_info);
630 }
631 *clone_info=(*info);
632 clone_info->image_info=CloneImageInfo(info->image_info);
633 return(clone_info);
634}
635
636/*
637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638% %
639% %
640% %
641% c o n s t a n t %
642% %
643% %
644% %
645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646%
647% constant() returns a double value for the specified name.
648%
649% The format of the constant routine is:
650%
651% double constant(char *name,ssize_t sans)
652%
653% A description of each parameter follows:
654%
655% o value: Method constant returns a double value for the specified name.
656%
657% o name: The name of the constant.
658%
659% o sans: This integer value is not used.
660%
661*/
662static double constant(char *name,ssize_t sans)
663{
664 (void) sans;
665 errno=0;
666 switch (*name)
667 {
668 case 'B':
669 {
670 if (strEQ(name,"BlobError"))
671 return(BlobError);
672 if (strEQ(name,"BlobWarning"))
673 return(BlobWarning);
674 break;
675 }
676 case 'C':
677 {
678 if (strEQ(name,"CacheError"))
679 return(CacheError);
680 if (strEQ(name,"CacheWarning"))
681 return(CacheWarning);
682 if (strEQ(name,"CoderError"))
683 return(CoderError);
684 if (strEQ(name,"CoderWarning"))
685 return(CoderWarning);
686 if (strEQ(name,"ConfigureError"))
687 return(ConfigureError);
688 if (strEQ(name,"ConfigureWarning"))
689 return(ConfigureWarning);
690 if (strEQ(name,"CorruptImageError"))
691 return(CorruptImageError);
692 if (strEQ(name,"CorruptImageWarning"))
693 return(CorruptImageWarning);
694 break;
695 }
696 case 'D':
697 {
698 if (strEQ(name,"DelegateError"))
699 return(DelegateError);
700 if (strEQ(name,"DelegateWarning"))
701 return(DelegateWarning);
702 if (strEQ(name,"DrawError"))
703 return(DrawError);
704 if (strEQ(name,"DrawWarning"))
705 return(DrawWarning);
706 break;
707 }
708 case 'E':
709 {
710 if (strEQ(name,"ErrorException"))
711 return(ErrorException);
712 if (strEQ(name,"ExceptionError"))
713 return(CoderError);
714 if (strEQ(name,"ExceptionWarning"))
715 return(CoderWarning);
716 break;
717 }
718 case 'F':
719 {
720 if (strEQ(name,"FatalErrorException"))
721 return(FatalErrorException);
722 if (strEQ(name,"FileOpenError"))
723 return(FileOpenError);
724 if (strEQ(name,"FileOpenWarning"))
725 return(FileOpenWarning);
726 break;
727 }
728 case 'I':
729 {
730 if (strEQ(name,"ImageError"))
731 return(ImageError);
732 if (strEQ(name,"ImageWarning"))
733 return(ImageWarning);
734 break;
735 }
736 case 'M':
737 {
738 if (strEQ(name,"MaxRGB"))
739 return(QuantumRange);
740 if (strEQ(name,"MissingDelegateError"))
741 return(MissingDelegateError);
742 if (strEQ(name,"MissingDelegateWarning"))
743 return(MissingDelegateWarning);
744 if (strEQ(name,"ModuleError"))
745 return(ModuleError);
746 if (strEQ(name,"ModuleWarning"))
747 return(ModuleWarning);
748 break;
749 }
750 case 'O':
751 {
752 if (strEQ(name,"Opaque"))
753 return(OpaqueAlpha);
754 if (strEQ(name,"OptionError"))
755 return(OptionError);
756 if (strEQ(name,"OptionWarning"))
757 return(OptionWarning);
758 break;
759 }
760 case 'Q':
761 {
762 if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
763 return(MAGICKCORE_QUANTUM_DEPTH);
764 if (strEQ(name,"QuantumDepth"))
765 return(MAGICKCORE_QUANTUM_DEPTH);
766 if (strEQ(name,"QuantumRange"))
767 return(QuantumRange);
768 break;
769 }
770 case 'R':
771 {
772 if (strEQ(name,"ResourceLimitError"))
773 return(ResourceLimitError);
774 if (strEQ(name,"ResourceLimitWarning"))
775 return(ResourceLimitWarning);
776 if (strEQ(name,"RegistryError"))
777 return(RegistryError);
778 if (strEQ(name,"RegistryWarning"))
779 return(RegistryWarning);
780 break;
781 }
782 case 'S':
783 {
784 if (strEQ(name,"StreamError"))
785 return(StreamError);
786 if (strEQ(name,"StreamWarning"))
787 return(StreamWarning);
788 if (strEQ(name,"Success"))
789 return(0);
790 break;
791 }
792 case 'T':
793 {
794 if (strEQ(name,"Transparent"))
795 return(TransparentAlpha);
796 if (strEQ(name,"TypeError"))
797 return(TypeError);
798 if (strEQ(name,"TypeWarning"))
799 return(TypeWarning);
800 break;
801 }
802 case 'W':
803 {
804 if (strEQ(name,"WarningException"))
805 return(WarningException);
806 break;
807 }
808 case 'X':
809 {
810 if (strEQ(name,"XServerError"))
811 return(XServerError);
812 if (strEQ(name,"XServerWarning"))
813 return(XServerWarning);
814 break;
815 }
816 }
817 errno=EINVAL;
818 return(0);
819}
820
821/*
822%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823% %
824% %
825% %
826% D e s t r o y P a c k a g e I n f o %
827% %
828% %
829% %
830%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831%
832% Method DestroyPackageInfo frees a previously created info structure.
833%
834% The format of the DestroyPackageInfo routine is:
835%
836% DestroyPackageInfo(struct PackageInfo *info)
837%
838% A description of each parameter follows:
839%
840% o info: a structure of type info.
841%
842*/
843static void DestroyPackageInfo(struct PackageInfo *info)
844{
845 info->image_info=DestroyImageInfo(info->image_info);
846 info=(struct PackageInfo *) RelinquishMagickMemory(info);
847}
848
849/*
850%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
851% %
852% %
853% %
854% G e t L i s t %
855% %
856% %
857% %
858%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
859%
860% Method GetList is recursively called by SetupList to traverse the
861% Image__Magick reference. If building an reference_vector (see SetupList),
862% *current is the current position in *reference_vector and *last is the final
863% entry in *reference_vector.
864%
865% The format of the GetList routine is:
866%
867% GetList(info)
868%
869% A description of each parameter follows:
870%
871% o info: a structure of type info.
872%
873*/
874static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
875 ssize_t *current,ssize_t *last,ExceptionInfo *exception)
876{
877 Image
878 *image;
879
880 if (reference == (SV *) NULL)
881 return(NULL);
882 switch (SvTYPE(reference))
883 {
884 case SVt_PVAV:
885 {
886 AV
887 *av;
888
889 Image
890 *head,
891 *previous;
892
893 register ssize_t
894 i;
895
896 ssize_t
897 n;
898
899 /*
900 Array of images.
901 */
902 previous=(Image *) NULL;
903 head=(Image *) NULL;
904 av=(AV *) reference;
905 n=av_len(av);
906 for (i=0; i <= n; i++)
907 {
908 SV
909 **rv;
910
911 rv=av_fetch(av,i,0);
912 if (rv && *rv && sv_isobject(*rv))
913 {
914 image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
915 exception);
916 if (image == (Image *) NULL)
917 continue;
918 if (image == previous)
919 {
920 image=CloneImage(image,0,0,MagickTrue,exception);
921 if (image == (Image *) NULL)
922 return(NULL);
923 }
924 image->previous=previous;
925 *(previous ? &previous->next : &head)=image;
926 for (previous=image; previous->next; previous=previous->next) ;
927 }
928 }
929 return(head);
930 }
931 case SVt_PVMG:
932 {
933 /*
934 Blessed scalar, one image.
935 */
936 image=INT2PTR(Image *,SvIV(reference));
937 if (image == (Image *) NULL)
938 return(NULL);
939 image->previous=(Image *) NULL;
940 image->next=(Image *) NULL;
941 if (reference_vector)
942 {
943 if (*current == *last)
944 {
945 *last+=256;
946 if (*reference_vector == (SV **) NULL)
947 *reference_vector=(SV **) AcquireQuantumMemory(*last,
948 sizeof(*reference_vector));
949 else
950 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
951 *last,sizeof(*reference_vector));
952 }
953 if (*reference_vector == (SV **) NULL)
954 {
955 ThrowPerlException(exception,ResourceLimitError,
956 "MemoryAllocationFailed",PackageName);
957 return((Image *) NULL);
958 }
959 (*reference_vector)[*current]=reference;
960 (*reference_vector)[++(*current)]=NULL;
961 }
962 return(image);
963 }
964 default:
965 break;
966 }
967 (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
968 (double) SvTYPE(reference));
969 return((Image *) NULL);
970}
971
972/*
973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
974% %
975% %
976% %
977% G e t P a c k a g e I n f o %
978% %
979% %
980% %
981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
982%
983% Method GetPackageInfo looks up or creates an info structure for the given
984% Image__Magick reference. If it does create a new one, the information in
985% package_info is used to initialize it.
986%
987% The format of the GetPackageInfo routine is:
988%
989% struct PackageInfo *GetPackageInfo(void *reference,
990% struct PackageInfo *package_info,ExceptionInfo *exception)
991%
992% A description of each parameter follows:
993%
994% o info: a structure of type info.
995%
996% o exception: Return any errors or warnings in this structure.
997%
998*/
999static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
1000 struct PackageInfo *package_info,ExceptionInfo *exception)
1001{
1002 char
cristy151b66d2015-04-15 10:50:31 +00001003 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00001004
1005 struct PackageInfo
1006 *clone_info;
1007
1008 SV
1009 *sv;
1010
cristy151b66d2015-04-15 10:50:31 +00001011 (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
cristy4a3ce0a2013-08-03 20:06:59 +00001012 PackageName,XS_VERSION,reference);
1013 sv=perl_get_sv(message,(TRUE | 0x02));
1014 if (sv == (SV *) NULL)
1015 {
1016 ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1017 message);
1018 return(package_info);
1019 }
1020 if (SvREFCNT(sv) == 0)
1021 (void) SvREFCNT_inc(sv);
1022 if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1023 return(clone_info);
1024 clone_info=ClonePackageInfo(package_info,exception);
1025 sv_setiv(sv,PTR2IV(clone_info));
1026 return(clone_info);
1027}
1028
1029/*
1030%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1031% %
1032% %
1033% %
1034% S e t A t t r i b u t e %
1035% %
1036% %
1037% %
1038%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1039%
1040% SetAttribute() sets the attribute to the value in sval. This can change
1041% either or both of image or info.
1042%
1043% The format of the SetAttribute routine is:
1044%
1045% SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1046% SV *sval,ExceptionInfo *exception)
1047%
1048% A description of each parameter follows:
1049%
1050% o list: a list of strings.
1051%
1052% o string: a character string.
1053%
1054*/
1055
1056static double SiPrefixToDoubleInterval(const char *string,const double interval)
1057{
1058 char
1059 *q;
1060
1061 double
1062 value;
1063
1064 value=InterpretSiPrefixValue(string,&q);
1065 if (*q == '%')
1066 value*=interval/100.0;
1067 return(value);
1068}
1069
1070static inline double StringToDouble(const char *string,char **sentinal)
1071{
1072 return(InterpretLocaleValue(string,sentinal));
1073}
1074
1075static double StringToDoubleInterval(const char *string,const double interval)
1076{
1077 char
1078 *q;
1079
1080 double
1081 value;
1082
1083 value=InterpretLocaleValue(string,&q);
1084 if (*q == '%')
1085 value*=interval/100.0;
1086 return(value);
1087}
1088
1089static inline ssize_t StringToLong(const char *value)
1090{
1091 return(strtol(value,(char **) NULL,10));
1092}
1093
1094static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1095 const char *attribute,SV *sval,ExceptionInfo *exception)
1096{
1097 GeometryInfo
1098 geometry_info;
1099
1100 long
1101 x,
1102 y;
1103
1104 PixelInfo
1105 pixel;
1106
1107 MagickStatusType
1108 flags;
1109
1110 PixelInfo
1111 *color,
1112 target_color;
1113
1114 ssize_t
1115 sp;
1116
1117 switch (*attribute)
1118 {
1119 case 'A':
1120 case 'a':
1121 {
1122 if (LocaleCompare(attribute,"adjoin") == 0)
1123 {
1124 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1125 SvPV(sval,na)) : SvIV(sval);
1126 if (sp < 0)
1127 {
1128 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1129 SvPV(sval,na));
1130 break;
1131 }
1132 if (info)
1133 info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1134 break;
1135 }
1136 if (LocaleCompare(attribute,"alpha") == 0)
1137 {
1138 sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1139 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1140 if (sp < 0)
1141 {
1142 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1143 SvPV(sval,na));
1144 break;
1145 }
1146 for ( ; image; image=image->next)
1147 (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1148 exception);
1149 break;
1150 }
1151 if (LocaleCompare(attribute,"antialias") == 0)
1152 {
1153 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1154 SvPV(sval,na)) : SvIV(sval);
1155 if (sp < 0)
1156 {
1157 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1158 SvPV(sval,na));
1159 break;
1160 }
1161 if (info)
1162 info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1163 break;
1164 }
1165 if (LocaleCompare(attribute,"area-limit") == 0)
1166 {
1167 MagickSizeType
1168 limit;
1169
1170 limit=MagickResourceInfinity;
1171 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1172 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1173 100.0);
1174 (void) SetMagickResourceLimit(AreaResource,limit);
1175 break;
1176 }
1177 if (LocaleCompare(attribute,"attenuate") == 0)
1178 {
1179 if (info)
1180 (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1181 break;
1182 }
1183 if (LocaleCompare(attribute,"authenticate") == 0)
1184 {
1185 if (info)
1186 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1187 break;
1188 }
1189 if (info)
1190 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1191 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001192 {
1193 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstra337c9bc2017-04-03 16:04:21 +02001194 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001195 }
cristy4a3ce0a2013-08-03 20:06:59 +00001196 break;
1197 }
1198 case 'B':
1199 case 'b':
1200 {
1201 if (LocaleCompare(attribute,"background") == 0)
1202 {
1203 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1204 exception);
1205 if (info)
1206 info->image_info->background_color=target_color;
1207 for ( ; image; image=image->next)
1208 image->background_color=target_color;
1209 break;
1210 }
1211 if (LocaleCompare(attribute,"blue-primary") == 0)
1212 {
1213 for ( ; image; image=image->next)
1214 {
1215 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1216 image->chromaticity.blue_primary.x=geometry_info.rho;
1217 image->chromaticity.blue_primary.y=geometry_info.sigma;
1218 if ((flags & SigmaValue) == 0)
1219 image->chromaticity.blue_primary.y=
1220 image->chromaticity.blue_primary.x;
1221 }
1222 break;
1223 }
1224 if (LocaleCompare(attribute,"bordercolor") == 0)
1225 {
1226 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1227 exception);
1228 if (info)
1229 info->image_info->border_color=target_color;
1230 for ( ; image; image=image->next)
1231 image->border_color=target_color;
1232 break;
1233 }
1234 if (info)
1235 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1236 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001237 {
1238 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001239 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001240 }
cristy4a3ce0a2013-08-03 20:06:59 +00001241 break;
1242 }
1243 case 'C':
1244 case 'c':
1245 {
1246 if (LocaleCompare(attribute,"cache-threshold") == 0)
1247 {
1248 (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1249 SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1250 (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1251 (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1252 break;
1253 }
1254 if (LocaleCompare(attribute,"clip-mask") == 0)
1255 {
1256 Image
1257 *clip_mask;
1258
1259 clip_mask=(Image *) NULL;
1260 if (SvPOK(sval))
1261 clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1262 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001263 SetImageMask(image,ReadPixelMask,clip_mask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001264 break;
1265 }
1266 if (LocaleNCompare(attribute,"colormap",8) == 0)
1267 {
1268 for ( ; image; image=image->next)
1269 {
1270 int
1271 items;
1272
1273 long
1274 i;
1275
1276 if (image->storage_class == DirectClass)
1277 continue;
1278 i=0;
1279 items=sscanf(attribute,"%*[^[][%ld",&i);
1280 (void) items;
1281 if (i > (ssize_t) image->colors)
1282 i%=image->colors;
1283 if ((strchr(SvPV(sval,na),',') == 0) ||
1284 (strchr(SvPV(sval,na),')') != 0))
1285 QueryColorCompliance(SvPV(sval,na),AllCompliance,
1286 image->colormap+i,exception);
1287 else
1288 {
1289 color=image->colormap+i;
1290 pixel.red=color->red;
1291 pixel.green=color->green;
1292 pixel.blue=color->blue;
1293 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1294 pixel.red=geometry_info.rho;
1295 pixel.green=geometry_info.sigma;
1296 pixel.blue=geometry_info.xi;
1297 color->red=ClampToQuantum(pixel.red);
1298 color->green=ClampToQuantum(pixel.green);
1299 color->blue=ClampToQuantum(pixel.blue);
1300 }
1301 }
1302 break;
1303 }
1304 if (LocaleCompare(attribute,"colorspace") == 0)
1305 {
1306 sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1307 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1308 if (sp < 0)
1309 {
1310 ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1311 SvPV(sval,na));
1312 break;
1313 }
1314 for ( ; image; image=image->next)
Cristy59262d92016-12-05 15:21:50 -05001315 (void) SetImageColorspace(image,(ColorspaceType) sp,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001316 break;
1317 }
1318 if (LocaleCompare(attribute,"comment") == 0)
1319 {
1320 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001321 (void) SetImageProperty(image,"Comment",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00001322 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04001323 SvPV(sval,na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001324 break;
1325 }
1326 if (LocaleCompare(attribute,"compression") == 0)
1327 {
1328 sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1329 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1330 if (sp < 0)
1331 {
1332 ThrowPerlException(exception,OptionError,
1333 "UnrecognizedImageCompression",SvPV(sval,na));
1334 break;
1335 }
1336 if (info)
1337 info->image_info->compression=(CompressionType) sp;
1338 for ( ; image; image=image->next)
1339 image->compression=(CompressionType) sp;
1340 break;
1341 }
1342 if (info)
1343 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1344 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001345 {
1346 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001347 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001348 }
cristy4a3ce0a2013-08-03 20:06:59 +00001349 break;
1350 }
1351 case 'D':
1352 case 'd':
1353 {
1354 if (LocaleCompare(attribute,"debug") == 0)
1355 {
1356 SetLogEventMask(SvPV(sval,na));
1357 break;
1358 }
1359 if (LocaleCompare(attribute,"delay") == 0)
1360 {
1361 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1362 for ( ; image; image=image->next)
1363 {
1364 image->delay=(size_t) floor(geometry_info.rho+0.5);
1365 if ((flags & SigmaValue) != 0)
1366 image->ticks_per_second=(ssize_t)
1367 floor(geometry_info.sigma+0.5);
1368 }
1369 break;
1370 }
1371 if (LocaleCompare(attribute,"disk-limit") == 0)
1372 {
1373 MagickSizeType
1374 limit;
1375
1376 limit=MagickResourceInfinity;
1377 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1378 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1379 100.0);
1380 (void) SetMagickResourceLimit(DiskResource,limit);
1381 break;
1382 }
1383 if (LocaleCompare(attribute,"density") == 0)
1384 {
1385 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1386 {
1387 ThrowPerlException(exception,OptionError,"MissingGeometry",
1388 SvPV(sval,na));
1389 break;
1390 }
1391 if (info)
1392 (void) CloneString(&info->image_info->density,SvPV(sval,na));
1393 for ( ; image; image=image->next)
1394 {
1395 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1396 image->resolution.x=geometry_info.rho;
1397 image->resolution.y=geometry_info.sigma;
1398 if ((flags & SigmaValue) == 0)
1399 image->resolution.y=image->resolution.x;
1400 }
1401 break;
1402 }
1403 if (LocaleCompare(attribute,"depth") == 0)
1404 {
1405 if (info)
1406 info->image_info->depth=SvIV(sval);
1407 for ( ; image; image=image->next)
1408 (void) SetImageDepth(image,SvIV(sval),exception);
1409 break;
1410 }
1411 if (LocaleCompare(attribute,"dispose") == 0)
1412 {
1413 sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1414 SvPV(sval,na)) : SvIV(sval);
1415 if (sp < 0)
1416 {
1417 ThrowPerlException(exception,OptionError,
1418 "UnrecognizedDisposeMethod",SvPV(sval,na));
1419 break;
1420 }
1421 for ( ; image; image=image->next)
1422 image->dispose=(DisposeType) sp;
1423 break;
1424 }
1425 if (LocaleCompare(attribute,"dither") == 0)
1426 {
1427 if (info)
1428 {
1429 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1430 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1431 if (sp < 0)
1432 {
1433 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1434 SvPV(sval,na));
1435 break;
1436 }
1437 info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1438 }
1439 break;
1440 }
1441 if (LocaleCompare(attribute,"display") == 0)
1442 {
1443 display:
1444 if (info)
1445 (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1446 break;
1447 }
1448 if (info)
1449 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1450 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001451 {
1452 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001453 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001454 }
cristy4a3ce0a2013-08-03 20:06:59 +00001455 break;
1456 }
1457 case 'E':
1458 case 'e':
1459 {
1460 if (LocaleCompare(attribute,"endian") == 0)
1461 {
1462 sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1463 SvPV(sval,na)) : SvIV(sval);
1464 if (sp < 0)
1465 {
1466 ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1467 SvPV(sval,na));
1468 break;
1469 }
1470 if (info)
1471 info->image_info->endian=(EndianType) sp;
1472 for ( ; image; image=image->next)
1473 image->endian=(EndianType) sp;
1474 break;
1475 }
1476 if (LocaleCompare(attribute,"extract") == 0)
1477 {
1478 /*
1479 Set image extract geometry.
1480 */
1481 (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1482 break;
1483 }
1484 if (info)
1485 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1486 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001487 {
1488 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001489 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001490 }
cristy4a3ce0a2013-08-03 20:06:59 +00001491 break;
1492 }
1493 case 'F':
1494 case 'f':
1495 {
1496 if (LocaleCompare(attribute,"filename") == 0)
1497 {
1498 if (info)
1499 (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
cristy151b66d2015-04-15 10:50:31 +00001500 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001501 for ( ; image; image=image->next)
1502 (void) CopyMagickString(image->filename,SvPV(sval,na),
cristy151b66d2015-04-15 10:50:31 +00001503 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001504 break;
1505 }
1506 if (LocaleCompare(attribute,"file") == 0)
1507 {
1508 FILE
1509 *file;
1510
1511 PerlIO
1512 *io_info;
1513
1514 if (info == (struct PackageInfo *) NULL)
1515 break;
1516 io_info=IoIFP(sv_2io(sval));
1517 if (io_info == (PerlIO *) NULL)
1518 {
1519 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1520 PackageName);
1521 break;
1522 }
1523 file=PerlIO_findFILE(io_info);
1524 if (file == (FILE *) NULL)
1525 {
1526 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1527 PackageName);
1528 break;
1529 }
1530 SetImageInfoFile(info->image_info,file);
1531 break;
1532 }
1533 if (LocaleCompare(attribute,"fill") == 0)
1534 {
1535 if (info)
1536 (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1537 break;
1538 }
1539 if (LocaleCompare(attribute,"font") == 0)
1540 {
1541 if (info)
1542 (void) CloneString(&info->image_info->font,SvPV(sval,na));
1543 break;
1544 }
1545 if (LocaleCompare(attribute,"foreground") == 0)
1546 break;
1547 if (LocaleCompare(attribute,"fuzz") == 0)
1548 {
1549 if (info)
1550 info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1551 QuantumRange+1.0);
1552 for ( ; image; image=image->next)
1553 image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1554 QuantumRange+1.0);
1555 break;
1556 }
1557 if (info)
1558 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1559 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001560 {
1561 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001562 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001563 }
cristy4a3ce0a2013-08-03 20:06:59 +00001564 break;
1565 }
1566 case 'G':
1567 case 'g':
1568 {
1569 if (LocaleCompare(attribute,"gamma") == 0)
1570 {
1571 for ( ; image; image=image->next)
1572 image->gamma=SvNV(sval);
1573 break;
1574 }
1575 if (LocaleCompare(attribute,"gravity") == 0)
1576 {
1577 sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1578 SvPV(sval,na)) : SvIV(sval);
1579 if (sp < 0)
1580 {
1581 ThrowPerlException(exception,OptionError,
1582 "UnrecognizedGravityType",SvPV(sval,na));
1583 break;
1584 }
1585 if (info)
1586 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1587 for ( ; image; image=image->next)
1588 image->gravity=(GravityType) sp;
1589 break;
1590 }
1591 if (LocaleCompare(attribute,"green-primary") == 0)
1592 {
1593 for ( ; image; image=image->next)
1594 {
1595 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1596 image->chromaticity.green_primary.x=geometry_info.rho;
1597 image->chromaticity.green_primary.y=geometry_info.sigma;
1598 if ((flags & SigmaValue) == 0)
1599 image->chromaticity.green_primary.y=
1600 image->chromaticity.green_primary.x;
1601 }
1602 break;
1603 }
1604 if (info)
1605 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1606 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001607 {
1608 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001609 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001610 }
cristy4a3ce0a2013-08-03 20:06:59 +00001611 break;
1612 }
1613 case 'I':
1614 case 'i':
1615 {
1616 if (LocaleNCompare(attribute,"index",5) == 0)
1617 {
1618 int
1619 items;
1620
1621 long
1622 index;
1623
1624 register Quantum
1625 *q;
1626
1627 CacheView
1628 *image_view;
1629
1630 for ( ; image; image=image->next)
1631 {
1632 if (image->storage_class != PseudoClass)
1633 continue;
1634 x=0;
1635 y=0;
1636 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1637 (void) items;
1638 image_view=AcquireAuthenticCacheView(image,exception);
1639 q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1640 if (q != (Quantum *) NULL)
1641 {
1642 items=sscanf(SvPV(sval,na),"%ld",&index);
1643 if ((index >= 0) && (index < (ssize_t) image->colors))
1644 SetPixelIndex(image,index,q);
1645 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1646 }
1647 image_view=DestroyCacheView(image_view);
1648 }
1649 break;
1650 }
1651 if (LocaleCompare(attribute,"iterations") == 0)
1652 {
1653 iterations:
1654 for ( ; image; image=image->next)
1655 image->iterations=SvIV(sval);
1656 break;
1657 }
1658 if (LocaleCompare(attribute,"interlace") == 0)
1659 {
1660 sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1661 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1662 if (sp < 0)
1663 {
1664 ThrowPerlException(exception,OptionError,
1665 "UnrecognizedInterlaceType",SvPV(sval,na));
1666 break;
1667 }
1668 if (info)
1669 info->image_info->interlace=(InterlaceType) sp;
1670 for ( ; image; image=image->next)
1671 image->interlace=(InterlaceType) sp;
1672 break;
1673 }
1674 if (info)
1675 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1676 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001677 {
1678 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001679 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001680 }
cristy4a3ce0a2013-08-03 20:06:59 +00001681 break;
1682 }
1683 case 'L':
1684 case 'l':
1685 {
1686 if (LocaleCompare(attribute,"label") == 0)
1687 {
1688 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001689 (void) SetImageProperty(image,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00001690 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04001691 SvPV(sval,na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001692 break;
1693 }
1694 if (LocaleCompare(attribute,"loop") == 0)
1695 goto iterations;
1696 if (info)
1697 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1698 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001699 {
1700 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001701 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001702 }
cristy4a3ce0a2013-08-03 20:06:59 +00001703 break;
1704 }
1705 case 'M':
1706 case 'm':
1707 {
1708 if (LocaleCompare(attribute,"magick") == 0)
1709 {
1710 if (info)
Cristyb5b1f5d2017-03-31 16:42:35 -04001711 (void) FormatLocaleString(info->image_info->filename,
1712 MagickPathExtent,"%s:",SvPV(sval,na));
cristy4a3ce0a2013-08-03 20:06:59 +00001713 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001714 (void) CopyMagickString(image->magick,SvPV(sval,na),
1715 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001716 break;
1717 }
1718 if (LocaleCompare(attribute,"map-limit") == 0)
1719 {
1720 MagickSizeType
1721 limit;
1722
1723 limit=MagickResourceInfinity;
1724 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1725 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1726 100.0);
1727 (void) SetMagickResourceLimit(MapResource,limit);
1728 break;
1729 }
1730 if (LocaleCompare(attribute,"mask") == 0)
1731 {
1732 Image
1733 *mask;
1734
1735 mask=(Image *) NULL;
1736 if (SvPOK(sval))
1737 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1738 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001739 SetImageMask(image,ReadPixelMask,mask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001740 break;
1741 }
1742 if (LocaleCompare(attribute,"mattecolor") == 0)
1743 {
1744 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1745 exception);
1746 if (info)
Cristy8645e042016-02-03 16:35:29 -05001747 info->image_info->alpha_color=target_color;
cristy4a3ce0a2013-08-03 20:06:59 +00001748 for ( ; image; image=image->next)
Cristy8645e042016-02-03 16:35:29 -05001749 image->alpha_color=target_color;
cristy4a3ce0a2013-08-03 20:06:59 +00001750 break;
1751 }
1752 if (LocaleCompare(attribute,"matte") == 0)
1753 {
1754 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1755 SvPV(sval,na)) : SvIV(sval);
1756 if (sp < 0)
1757 {
1758 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1759 SvPV(sval,na));
1760 break;
1761 }
1762 for ( ; image; image=image->next)
1763 image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1764 break;
1765 }
1766 if (LocaleCompare(attribute,"memory-limit") == 0)
1767 {
1768 MagickSizeType
1769 limit;
1770
1771 limit=MagickResourceInfinity;
1772 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1773 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1774 100.0);
1775 (void) SetMagickResourceLimit(MemoryResource,limit);
1776 break;
1777 }
1778 if (LocaleCompare(attribute,"monochrome") == 0)
1779 {
1780 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1781 SvPV(sval,na)) : SvIV(sval);
1782 if (sp < 0)
1783 {
1784 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1785 SvPV(sval,na));
1786 break;
1787 }
1788 if (info)
1789 info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1790 for ( ; image; image=image->next)
1791 (void) SetImageType(image,BilevelType,exception);
1792 break;
1793 }
1794 if (info)
1795 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1796 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001797 {
1798 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001799 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001800 }
cristy4a3ce0a2013-08-03 20:06:59 +00001801 break;
1802 }
1803 case 'O':
1804 case 'o':
1805 {
1806 if (LocaleCompare(attribute,"option") == 0)
1807 {
1808 if (info)
1809 DefineImageOption(info->image_info,SvPV(sval,na));
1810 break;
1811 }
1812 if (LocaleCompare(attribute,"orientation") == 0)
1813 {
1814 sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1815 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1816 if (sp < 0)
1817 {
1818 ThrowPerlException(exception,OptionError,
1819 "UnrecognizedOrientationType",SvPV(sval,na));
1820 break;
1821 }
1822 if (info)
1823 info->image_info->orientation=(OrientationType) sp;
1824 for ( ; image; image=image->next)
1825 image->orientation=(OrientationType) sp;
1826 break;
1827 }
1828 if (info)
1829 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1830 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001831 {
1832 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001833 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001834 }
cristy4a3ce0a2013-08-03 20:06:59 +00001835 break;
1836 }
1837 case 'P':
1838 case 'p':
1839 {
1840 if (LocaleCompare(attribute,"page") == 0)
1841 {
1842 char
1843 *geometry;
1844
1845 geometry=GetPageGeometry(SvPV(sval,na));
1846 if (info)
1847 (void) CloneString(&info->image_info->page,geometry);
1848 for ( ; image; image=image->next)
1849 (void) ParsePageGeometry(image,geometry,&image->page,exception);
1850 geometry=(char *) RelinquishMagickMemory(geometry);
1851 break;
1852 }
1853 if (LocaleNCompare(attribute,"pixel",5) == 0)
1854 {
1855 int
1856 items;
1857
1858 PixelInfo
1859 pixel;
1860
1861 register Quantum
1862 *q;
1863
1864 CacheView
1865 *image_view;
1866
1867 for ( ; image; image=image->next)
1868 {
1869 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1870 break;
1871 x=0;
1872 y=0;
1873 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1874 (void) items;
1875 image_view=AcquireVirtualCacheView(image,exception);
1876 q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1877 if (q != (Quantum *) NULL)
1878 {
1879 if ((strchr(SvPV(sval,na),',') == 0) ||
1880 (strchr(SvPV(sval,na),')') != 0))
1881 QueryColorCompliance(SvPV(sval,na),AllCompliance,
1882 &pixel,exception);
1883 else
1884 {
1885 GetPixelInfo(image,&pixel);
1886 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1887 pixel.red=geometry_info.rho;
1888 if ((flags & SigmaValue) != 0)
1889 pixel.green=geometry_info.sigma;
1890 if ((flags & XiValue) != 0)
1891 pixel.blue=geometry_info.xi;
1892 if ((flags & PsiValue) != 0)
1893 pixel.alpha=geometry_info.psi;
1894 if ((flags & ChiValue) != 0)
1895 pixel.black=geometry_info.chi;
1896 }
1897 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1898 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1899 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1900 if (image->colorspace == CMYKColorspace)
1901 SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1902 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1903 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1904 }
1905 image_view=DestroyCacheView(image_view);
1906 }
1907 break;
1908 }
1909 if (LocaleCompare(attribute,"pointsize") == 0)
1910 {
1911 if (info)
1912 {
1913 (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1914 info->image_info->pointsize=geometry_info.rho;
1915 }
1916 break;
1917 }
cristy4a3ce0a2013-08-03 20:06:59 +00001918 if (info)
1919 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1920 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001921 {
1922 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001923 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001924 }
cristy4a3ce0a2013-08-03 20:06:59 +00001925 break;
1926 }
1927 case 'Q':
1928 case 'q':
1929 {
1930 if (LocaleCompare(attribute,"quality") == 0)
1931 {
1932 if (info)
1933 info->image_info->quality=SvIV(sval);
1934 for ( ; image; image=image->next)
1935 image->quality=SvIV(sval);
1936 break;
1937 }
1938 if (info)
1939 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1940 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001941 {
1942 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001943 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001944 }
cristy4a3ce0a2013-08-03 20:06:59 +00001945 break;
1946 }
1947 case 'R':
1948 case 'r':
1949 {
cristyc0fe4752015-07-27 18:02:39 +00001950 if (LocaleCompare(attribute,"read-mask") == 0)
1951 {
1952 Image
1953 *mask;
1954
1955 mask=(Image *) NULL;
1956 if (SvPOK(sval))
1957 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1958 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001959 SetImageMask(image,ReadPixelMask,mask,exception);
cristyc0fe4752015-07-27 18:02:39 +00001960 break;
1961 }
cristy4a3ce0a2013-08-03 20:06:59 +00001962 if (LocaleCompare(attribute,"red-primary") == 0)
1963 {
1964 for ( ; image; image=image->next)
1965 {
1966 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1967 image->chromaticity.red_primary.x=geometry_info.rho;
1968 image->chromaticity.red_primary.y=geometry_info.sigma;
1969 if ((flags & SigmaValue) == 0)
1970 image->chromaticity.red_primary.y=
1971 image->chromaticity.red_primary.x;
1972 }
1973 break;
1974 }
1975 if (LocaleCompare(attribute,"render") == 0)
1976 {
1977 sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1978 SvPV(sval,na)) : SvIV(sval);
1979 if (sp < 0)
1980 {
1981 ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1982 SvPV(sval,na));
1983 break;
1984 }
1985 for ( ; image; image=image->next)
1986 image->rendering_intent=(RenderingIntent) sp;
1987 break;
1988 }
1989 if (LocaleCompare(attribute,"repage") == 0)
1990 {
1991 RectangleInfo
1992 geometry;
1993
1994 for ( ; image; image=image->next)
1995 {
1996 flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1997 if ((flags & WidthValue) != 0)
1998 {
1999 if ((flags & HeightValue) == 0)
2000 geometry.height=geometry.width;
2001 image->page.width=geometry.width;
2002 image->page.height=geometry.height;
2003 }
2004 if ((flags & AspectValue) != 0)
2005 {
2006 if ((flags & XValue) != 0)
2007 image->page.x+=geometry.x;
2008 if ((flags & YValue) != 0)
2009 image->page.y+=geometry.y;
2010 }
2011 else
2012 {
2013 if ((flags & XValue) != 0)
2014 {
2015 image->page.x=geometry.x;
2016 if (((flags & WidthValue) != 0) && (geometry.x > 0))
2017 image->page.width=image->columns+geometry.x;
2018 }
2019 if ((flags & YValue) != 0)
2020 {
2021 image->page.y=geometry.y;
2022 if (((flags & HeightValue) != 0) && (geometry.y > 0))
2023 image->page.height=image->rows+geometry.y;
2024 }
2025 }
2026 }
2027 break;
2028 }
2029 if (info)
2030 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2031 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002032 {
2033 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002034 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002035 }
cristy4a3ce0a2013-08-03 20:06:59 +00002036 break;
2037 }
2038 case 'S':
2039 case 's':
2040 {
2041 if (LocaleCompare(attribute,"sampling-factor") == 0)
2042 {
2043 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2044 {
2045 ThrowPerlException(exception,OptionError,"MissingGeometry",
2046 SvPV(sval,na));
2047 break;
2048 }
2049 if (info)
2050 (void) CloneString(&info->image_info->sampling_factor,
2051 SvPV(sval,na));
2052 break;
2053 }
2054 if (LocaleCompare(attribute,"scene") == 0)
2055 {
2056 for ( ; image; image=image->next)
2057 image->scene=SvIV(sval);
2058 break;
2059 }
2060 if (LocaleCompare(attribute,"server") == 0)
2061 goto display;
2062 if (LocaleCompare(attribute,"size") == 0)
2063 {
2064 if (info)
2065 {
2066 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2067 {
2068 ThrowPerlException(exception,OptionError,"MissingGeometry",
2069 SvPV(sval,na));
2070 break;
2071 }
2072 (void) CloneString(&info->image_info->size,SvPV(sval,na));
2073 }
2074 break;
2075 }
2076 if (LocaleCompare(attribute,"stroke") == 0)
2077 {
2078 if (info)
2079 (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2080 break;
2081 }
2082 if (info)
2083 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2084 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002085 {
2086 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002087 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002088 }
cristy4a3ce0a2013-08-03 20:06:59 +00002089 break;
2090 }
2091 case 'T':
2092 case 't':
2093 {
2094 if (LocaleCompare(attribute,"texture") == 0)
2095 {
2096 if (info)
2097 (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2098 break;
2099 }
2100 if (LocaleCompare(attribute,"thread-limit") == 0)
2101 {
2102 MagickSizeType
2103 limit;
2104
2105 limit=MagickResourceInfinity;
2106 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2107 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2108 100.0);
2109 (void) SetMagickResourceLimit(ThreadResource,limit);
2110 break;
2111 }
2112 if (LocaleCompare(attribute,"tile-offset") == 0)
2113 {
2114 char
2115 *geometry;
2116
2117 geometry=GetPageGeometry(SvPV(sval,na));
2118 if (info)
2119 (void) CloneString(&info->image_info->page,geometry);
2120 for ( ; image; image=image->next)
2121 (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2122 exception);
2123 geometry=(char *) RelinquishMagickMemory(geometry);
2124 break;
2125 }
2126 if (LocaleCompare(attribute,"time-limit") == 0)
2127 {
2128 MagickSizeType
2129 limit;
2130
2131 limit=MagickResourceInfinity;
2132 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2133 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2134 100.0);
2135 (void) SetMagickResourceLimit(TimeResource,limit);
2136 break;
2137 }
2138 if (LocaleCompare(attribute,"transparent-color") == 0)
2139 {
2140 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2141 exception);
2142 if (info)
2143 info->image_info->transparent_color=target_color;
2144 for ( ; image; image=image->next)
2145 image->transparent_color=target_color;
2146 break;
2147 }
2148 if (LocaleCompare(attribute,"type") == 0)
2149 {
2150 sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2151 SvPV(sval,na)) : SvIV(sval);
2152 if (sp < 0)
2153 {
2154 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2155 SvPV(sval,na));
2156 break;
2157 }
2158 if (info)
2159 info->image_info->type=(ImageType) sp;
2160 for ( ; image; image=image->next)
2161 SetImageType(image,(ImageType) sp,exception);
2162 break;
2163 }
2164 if (info)
2165 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2166 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002167 {
2168 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002169 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002170 }
cristy4a3ce0a2013-08-03 20:06:59 +00002171 break;
2172 }
2173 case 'U':
2174 case 'u':
2175 {
2176 if (LocaleCompare(attribute,"units") == 0)
2177 {
2178 sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2179 MagickFalse,SvPV(sval,na)) : SvIV(sval);
2180 if (sp < 0)
2181 {
2182 ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2183 SvPV(sval,na));
2184 break;
2185 }
2186 if (info)
2187 info->image_info->units=(ResolutionType) sp;
2188 for ( ; image; image=image->next)
2189 {
2190 ResolutionType
2191 units;
2192
2193 units=(ResolutionType) sp;
2194 if (image->units != units)
2195 switch (image->units)
2196 {
2197 case UndefinedResolution:
2198 case PixelsPerInchResolution:
2199 {
2200 if (units == PixelsPerCentimeterResolution)
2201 {
2202 image->resolution.x*=2.54;
2203 image->resolution.y*=2.54;
2204 }
2205 break;
2206 }
2207 case PixelsPerCentimeterResolution:
2208 {
2209 if (units == PixelsPerInchResolution)
2210 {
2211 image->resolution.x/=2.54;
2212 image->resolution.y/=2.54;
2213 }
2214 break;
2215 }
2216 }
2217 image->units=units;
2218 }
2219 break;
2220 }
2221 if (info)
2222 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2223 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002224 {
2225 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002226 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002227 }
cristy4a3ce0a2013-08-03 20:06:59 +00002228 break;
2229 }
2230 case 'V':
2231 case 'v':
2232 {
2233 if (LocaleCompare(attribute,"verbose") == 0)
2234 {
2235 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2236 SvPV(sval,na)) : SvIV(sval);
2237 if (sp < 0)
2238 {
2239 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2240 SvPV(sval,na));
2241 break;
2242 }
2243 if (info)
2244 info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2245 break;
2246 }
cristy4a3ce0a2013-08-03 20:06:59 +00002247 if (LocaleCompare(attribute,"virtual-pixel") == 0)
2248 {
2249 sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2250 MagickFalse,SvPV(sval,na)) : SvIV(sval);
2251 if (sp < 0)
2252 {
2253 ThrowPerlException(exception,OptionError,
2254 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2255 break;
2256 }
2257 for ( ; image; image=image->next)
2258 SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2259 break;
2260 }
2261 if (info)
2262 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2263 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002264 {
2265 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002266 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002267 }
cristy4a3ce0a2013-08-03 20:06:59 +00002268 break;
2269 }
2270 case 'W':
2271 case 'w':
2272 {
2273 if (LocaleCompare(attribute,"white-point") == 0)
2274 {
2275 for ( ; image; image=image->next)
2276 {
2277 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2278 image->chromaticity.white_point.x=geometry_info.rho;
2279 image->chromaticity.white_point.y=geometry_info.sigma;
2280 if ((flags & SigmaValue) == 0)
2281 image->chromaticity.white_point.y=
2282 image->chromaticity.white_point.x;
2283 }
2284 break;
2285 }
cristyc0fe4752015-07-27 18:02:39 +00002286 if (LocaleCompare(attribute,"write-mask") == 0)
2287 {
2288 Image
2289 *mask;
2290
2291 mask=(Image *) NULL;
2292 if (SvPOK(sval))
2293 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2294 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00002295 SetImageMask(image,WritePixelMask,mask,exception);
cristyc0fe4752015-07-27 18:02:39 +00002296 break;
2297 }
cristy4a3ce0a2013-08-03 20:06:59 +00002298 if (info)
2299 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2300 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002301 {
2302 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002303 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002304 }
cristy4a3ce0a2013-08-03 20:06:59 +00002305 break;
2306 }
2307 default:
2308 {
2309 if (info)
2310 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2311 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002312 {
2313 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002314 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002315 }
cristy4a3ce0a2013-08-03 20:06:59 +00002316 break;
2317 }
2318 }
2319}
2320
2321/*
2322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2323% %
2324% %
2325% %
2326% S e t u p L i s t %
2327% %
2328% %
2329% %
2330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2331%
2332% Method SetupList returns the list of all the images linked by their
2333% image->next and image->previous link lists for use with ImageMagick. If
2334% info is non-NULL, an info structure is returned in *info. If
2335% reference_vector is non-NULL,an array of SV* are returned in
2336% *reference_vector. Reference_vector is used when the images are going to be
2337% replaced with new Image*'s.
2338%
2339% The format of the SetupList routine is:
2340%
2341% Image *SetupList(SV *reference,struct PackageInfo **info,
2342% SV ***reference_vector,ExceptionInfo *exception)
2343%
2344% A description of each parameter follows:
2345%
2346% o list: a list of strings.
2347%
2348% o string: a character string.
2349%
2350% o exception: Return any errors or warnings in this structure.
2351%
2352*/
2353static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2354 SV ***reference_vector,ExceptionInfo *exception)
2355{
2356 Image
2357 *image;
2358
2359 ssize_t
2360 current,
2361 last;
2362
2363 if (reference_vector)
2364 *reference_vector=NULL;
2365 if (info)
2366 *info=NULL;
2367 current=0;
2368 last=0;
2369 image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2370 if (info && (SvTYPE(reference) == SVt_PVAV))
2371 *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2372 exception);
2373 return(image);
2374}
2375
2376/*
2377%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2378% %
2379% %
2380% %
2381% s t r E Q c a s e %
2382% %
2383% %
2384% %
2385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2386%
2387% strEQcase() compares two strings and returns 0 if they are the
2388% same or if the second string runs out first. The comparison is case
2389% insensitive.
2390%
2391% The format of the strEQcase routine is:
2392%
2393% ssize_t strEQcase(const char *p,const char *q)
2394%
2395% A description of each parameter follows:
2396%
2397% o p: a character string.
2398%
2399% o q: a character string.
2400%
2401%
2402*/
2403static ssize_t strEQcase(const char *p,const char *q)
2404{
2405 char
2406 c;
2407
2408 register ssize_t
2409 i;
2410
2411 for (i=0 ; (c=(*q)) != 0; i++)
2412 {
2413 if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2414 (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2415 return(0);
2416 p++;
2417 q++;
2418 }
2419 return(((*q == 0) && (*p == 0)) ? i : 0);
2420}
2421
2422/*
2423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2424% %
2425% %
2426% %
2427% I m a g e : : M a g i c k %
2428% %
2429% %
2430% %
2431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2432%
2433%
2434*/
2435MODULE = Image::Magick PACKAGE = Image::Magick
2436
2437PROTOTYPES: ENABLE
2438
2439BOOT:
2440 MagickCoreGenesis("PerlMagick",MagickFalse);
2441 SetWarningHandler(NULL);
2442 SetErrorHandler(NULL);
2443 magick_registry=NewSplayTree((int (*)(const void *,const void *))
2444 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2445
2446void
2447UNLOAD()
2448 PPCODE:
2449 {
2450 if (magick_registry != (SplayTreeInfo *) NULL)
2451 magick_registry=DestroySplayTree(magick_registry);
2452 MagickCoreTerminus();
2453 }
2454
2455double
2456constant(name,argument)
2457 char *name
2458 ssize_t argument
2459
2460#
2461###############################################################################
2462# #
2463# #
2464# #
2465# A n i m a t e #
2466# #
2467# #
2468# #
2469###############################################################################
2470#
2471#
2472void
2473Animate(ref,...)
2474 Image::Magick ref=NO_INIT
2475 ALIAS:
2476 AnimateImage = 1
2477 animate = 2
2478 animateimage = 3
2479 PPCODE:
2480 {
2481 ExceptionInfo
2482 *exception;
2483
2484 Image
2485 *image;
2486
2487 register ssize_t
2488 i;
2489
2490 struct PackageInfo
2491 *info,
2492 *package_info;
2493
2494 SV
2495 *perl_exception,
2496 *reference;
2497
2498 PERL_UNUSED_VAR(ref);
2499 PERL_UNUSED_VAR(ix);
2500 exception=AcquireExceptionInfo();
2501 perl_exception=newSVpv("",0);
2502 package_info=(struct PackageInfo *) NULL;
2503 if (sv_isobject(ST(0)) == 0)
2504 {
2505 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2506 PackageName);
2507 goto PerlException;
2508 }
2509 reference=SvRV(ST(0));
2510 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2511 if (image == (Image *) NULL)
2512 {
2513 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2514 PackageName);
2515 goto PerlException;
2516 }
2517 package_info=ClonePackageInfo(info,exception);
2518 if (items == 2)
2519 SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2520 else
2521 if (items > 2)
2522 for (i=2; i < items; i+=2)
2523 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2524 exception);
2525 (void) AnimateImages(package_info->image_info,image,exception);
2526 (void) CatchImageException(image);
2527
2528 PerlException:
2529 if (package_info != (struct PackageInfo *) NULL)
2530 DestroyPackageInfo(package_info);
2531 InheritPerlException(exception,perl_exception);
2532 exception=DestroyExceptionInfo(exception);
2533 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2534 SvPOK_on(perl_exception);
2535 ST(0)=sv_2mortal(perl_exception);
2536 XSRETURN(1);
2537 }
2538
2539#
2540###############################################################################
2541# #
2542# #
2543# #
2544# A p p e n d #
2545# #
2546# #
2547# #
2548###############################################################################
2549#
2550#
2551void
2552Append(ref,...)
2553 Image::Magick ref=NO_INIT
2554 ALIAS:
2555 AppendImage = 1
2556 append = 2
2557 appendimage = 3
2558 PPCODE:
2559 {
2560 AV
2561 *av;
2562
2563 char
2564 *attribute;
2565
2566 ExceptionInfo
2567 *exception;
2568
2569 HV
2570 *hv;
2571
2572 Image
2573 *image;
2574
2575 register ssize_t
2576 i;
2577
2578 ssize_t
2579 stack;
2580
2581 struct PackageInfo
2582 *info;
2583
2584 SV
2585 *av_reference,
2586 *perl_exception,
2587 *reference,
2588 *rv,
2589 *sv;
2590
2591 PERL_UNUSED_VAR(ref);
2592 PERL_UNUSED_VAR(ix);
2593 exception=AcquireExceptionInfo();
2594 perl_exception=newSVpv("",0);
2595 sv=NULL;
2596 attribute=NULL;
2597 av=NULL;
2598 if (sv_isobject(ST(0)) == 0)
2599 {
2600 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2601 PackageName);
2602 goto PerlException;
2603 }
2604 reference=SvRV(ST(0));
2605 hv=SvSTASH(reference);
2606 av=newAV();
2607 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2608 SvREFCNT_dec(av);
2609 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2610 if (image == (Image *) NULL)
2611 {
2612 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2613 PackageName);
2614 goto PerlException;
2615 }
2616 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2617 /*
2618 Get options.
2619 */
2620 stack=MagickTrue;
2621 for (i=2; i < items; i+=2)
2622 {
2623 attribute=(char *) SvPV(ST(i-1),na);
2624 switch (*attribute)
2625 {
2626 case 'S':
2627 case 's':
2628 {
2629 if (LocaleCompare(attribute,"stack") == 0)
2630 {
2631 stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2632 SvPV(ST(i),na));
2633 if (stack < 0)
2634 {
2635 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2636 SvPV(ST(i),na));
2637 return;
2638 }
2639 break;
2640 }
2641 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2642 attribute);
2643 break;
2644 }
2645 default:
2646 {
2647 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2648 attribute);
2649 break;
2650 }
2651 }
2652 }
2653 image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2654 if (image == (Image *) NULL)
2655 goto PerlException;
2656 for ( ; image; image=image->next)
2657 {
2658 AddImageToRegistry(sv,image);
2659 rv=newRV(sv);
2660 av_push(av,sv_bless(rv,hv));
2661 SvREFCNT_dec(sv);
2662 }
2663 exception=DestroyExceptionInfo(exception);
2664 ST(0)=av_reference;
2665 SvREFCNT_dec(perl_exception);
2666 XSRETURN(1);
2667
2668 PerlException:
2669 InheritPerlException(exception,perl_exception);
2670 exception=DestroyExceptionInfo(exception);
2671 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2672 SvPOK_on(perl_exception);
2673 ST(0)=sv_2mortal(perl_exception);
2674 XSRETURN(1);
2675 }
2676
2677#
2678###############################################################################
2679# #
2680# #
2681# #
2682# A v e r a g e #
2683# #
2684# #
2685# #
2686###############################################################################
2687#
2688#
2689void
2690Average(ref)
2691 Image::Magick ref=NO_INIT
2692 ALIAS:
2693 AverageImage = 1
2694 average = 2
2695 averageimage = 3
2696 PPCODE:
2697 {
2698 AV
2699 *av;
2700
2701 char
2702 *p;
2703
2704 ExceptionInfo
2705 *exception;
2706
2707 HV
2708 *hv;
2709
2710 Image
2711 *image;
2712
2713 struct PackageInfo
2714 *info;
2715
2716 SV
2717 *perl_exception,
2718 *reference,
2719 *rv,
2720 *sv;
2721
2722 PERL_UNUSED_VAR(ref);
2723 PERL_UNUSED_VAR(ix);
2724 exception=AcquireExceptionInfo();
2725 perl_exception=newSVpv("",0);
2726 sv=NULL;
2727 if (sv_isobject(ST(0)) == 0)
2728 {
2729 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2730 PackageName);
2731 goto PerlException;
2732 }
2733 reference=SvRV(ST(0));
2734 hv=SvSTASH(reference);
2735 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2736 if (image == (Image *) NULL)
2737 {
2738 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2739 PackageName);
2740 goto PerlException;
2741 }
2742 image=EvaluateImages(image,MeanEvaluateOperator,exception);
2743 if (image == (Image *) NULL)
2744 goto PerlException;
2745 /*
2746 Create blessed Perl array for the returned image.
2747 */
2748 av=newAV();
2749 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2750 SvREFCNT_dec(av);
2751 AddImageToRegistry(sv,image);
2752 rv=newRV(sv);
2753 av_push(av,sv_bless(rv,hv));
2754 SvREFCNT_dec(sv);
2755 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00002756 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2757 "average-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00002758 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2759 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00002760 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00002761 SetImageInfo(info->image_info,0,exception);
2762 exception=DestroyExceptionInfo(exception);
2763 SvREFCNT_dec(perl_exception);
2764 XSRETURN(1);
2765
2766 PerlException:
2767 InheritPerlException(exception,perl_exception);
2768 exception=DestroyExceptionInfo(exception);
2769 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2770 SvPOK_on(perl_exception);
2771 ST(0)=sv_2mortal(perl_exception);
2772 XSRETURN(1);
2773 }
2774
2775#
2776###############################################################################
2777# #
2778# #
2779# #
2780# B l o b T o I m a g e #
2781# #
2782# #
2783# #
2784###############################################################################
2785#
2786#
2787void
2788BlobToImage(ref,...)
2789 Image::Magick ref=NO_INIT
2790 ALIAS:
2791 BlobToImage = 1
2792 blobtoimage = 2
2793 blobto = 3
2794 PPCODE:
2795 {
2796 AV
2797 *av;
2798
2799 char
2800 **keep,
2801 **list;
2802
2803 ExceptionInfo
2804 *exception;
2805
2806 HV
2807 *hv;
2808
2809 Image
2810 *image;
2811
2812 register char
2813 **p;
2814
2815 register ssize_t
2816 i;
2817
2818 ssize_t
2819 ac,
2820 n,
2821 number_images;
2822
2823 STRLEN
2824 *length;
2825
2826 struct PackageInfo
2827 *info;
2828
2829 SV
2830 *perl_exception,
2831 *reference,
2832 *rv,
2833 *sv;
2834
2835 PERL_UNUSED_VAR(ref);
2836 PERL_UNUSED_VAR(ix);
2837 exception=AcquireExceptionInfo();
2838 perl_exception=newSVpv("",0);
2839 sv=NULL;
2840 number_images=0;
2841 ac=(items < 2) ? 1 : items-1;
2842 length=(STRLEN *) NULL;
2843 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2844 if (list == (char **) NULL)
2845 {
2846 ThrowPerlException(exception,ResourceLimitError,
2847 "MemoryAllocationFailed",PackageName);
2848 goto PerlException;
2849 }
2850 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2851 if (length == (STRLEN *) NULL)
2852 {
2853 ThrowPerlException(exception,ResourceLimitError,
2854 "MemoryAllocationFailed",PackageName);
2855 goto PerlException;
2856 }
2857 if (sv_isobject(ST(0)) == 0)
2858 {
2859 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2860 PackageName);
2861 goto PerlException;
2862 }
2863 reference=SvRV(ST(0));
2864 hv=SvSTASH(reference);
2865 if (SvTYPE(reference) != SVt_PVAV)
2866 {
2867 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2868 PackageName);
2869 goto PerlException;
2870 }
2871 av=(AV *) reference;
2872 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2873 exception);
2874 n=1;
2875 if (items <= 1)
2876 {
2877 ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2878 goto PerlException;
2879 }
2880 for (n=0, i=0; i < ac; i++)
2881 {
2882 list[n]=(char *) (SvPV(ST(i+1),length[n]));
2883 if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2884 {
2885 list[n]=(char *) (SvPV(ST(i+2),length[n]));
2886 continue;
2887 }
2888 n++;
2889 }
2890 list[n]=(char *) NULL;
2891 keep=list;
2892 for (i=number_images=0; i < n; i++)
2893 {
2894 image=BlobToImage(info->image_info,list[i],length[i],exception);
2895 if (image == (Image *) NULL)
2896 break;
2897 for ( ; image; image=image->next)
2898 {
2899 AddImageToRegistry(sv,image);
2900 rv=newRV(sv);
2901 av_push(av,sv_bless(rv,hv));
2902 SvREFCNT_dec(sv);
2903 number_images++;
2904 }
2905 }
2906 /*
2907 Free resources.
2908 */
2909 for (i=0; i < n; i++)
2910 if (list[i] != (char *) NULL)
2911 for (p=keep; list[i] != *p++; )
2912 if (*p == (char *) NULL)
2913 {
2914 list[i]=(char *) RelinquishMagickMemory(list[i]);
2915 break;
2916 }
2917
2918 PerlException:
2919 if (list)
2920 list=(char **) RelinquishMagickMemory(list);
2921 if (length)
2922 length=(STRLEN *) RelinquishMagickMemory(length);
2923 InheritPerlException(exception,perl_exception);
2924 exception=DestroyExceptionInfo(exception);
2925 sv_setiv(perl_exception,(IV) number_images);
2926 SvPOK_on(perl_exception);
2927 ST(0)=sv_2mortal(perl_exception);
2928 XSRETURN(1);
2929 }
2930
2931#
2932###############################################################################
2933# #
2934# #
2935# #
2936# C h a n n e l F x #
2937# #
2938# #
2939# #
2940###############################################################################
2941#
2942#
2943void
2944ChannelFx(ref,...)
2945 Image::Magick ref=NO_INIT
2946 ALIAS:
2947 ChannelFxImage = 1
2948 channelfx = 2
2949 channelfximage = 3
2950 PPCODE:
2951 {
2952 AV
2953 *av;
2954
2955 char
2956 *attribute,
cristy151b66d2015-04-15 10:50:31 +00002957 expression[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00002958
2959 ChannelType
2960 channel,
2961 channel_mask;
2962
2963 ExceptionInfo
2964 *exception;
2965
2966 HV
2967 *hv;
2968
2969 Image
2970 *image;
2971
2972 register ssize_t
2973 i;
2974
2975 struct PackageInfo
2976 *info;
2977
2978 SV
2979 *av_reference,
2980 *perl_exception,
2981 *reference,
2982 *rv,
2983 *sv;
2984
2985 PERL_UNUSED_VAR(ref);
2986 PERL_UNUSED_VAR(ix);
2987 exception=AcquireExceptionInfo();
2988 perl_exception=newSVpv("",0);
2989 sv=NULL;
2990 attribute=NULL;
2991 av=NULL;
2992 if (sv_isobject(ST(0)) == 0)
2993 {
2994 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2995 PackageName);
2996 goto PerlException;
2997 }
2998 reference=SvRV(ST(0));
2999 hv=SvSTASH(reference);
3000 av=newAV();
3001 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3002 SvREFCNT_dec(av);
3003 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3004 if (image == (Image *) NULL)
3005 {
3006 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3007 PackageName);
3008 goto PerlException;
3009 }
3010 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3011 /*
3012 Get options.
3013 */
3014 channel=DefaultChannels;
cristy151b66d2015-04-15 10:50:31 +00003015 (void) CopyMagickString(expression,"u",MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003016 if (items == 2)
cristy151b66d2015-04-15 10:50:31 +00003017 (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003018 else
3019 for (i=2; i < items; i+=2)
3020 {
3021 attribute=(char *) SvPV(ST(i-1),na);
3022 switch (*attribute)
3023 {
3024 case 'C':
3025 case 'c':
3026 {
3027 if (LocaleCompare(attribute,"channel") == 0)
3028 {
3029 ssize_t
3030 option;
3031
3032 option=ParseChannelOption(SvPV(ST(i),na));
3033 if (option < 0)
3034 {
3035 ThrowPerlException(exception,OptionError,
3036 "UnrecognizedType",SvPV(ST(i),na));
3037 return;
3038 }
3039 channel=(ChannelType) option;
3040 break;
3041 }
3042 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3043 attribute);
3044 break;
3045 }
3046 case 'E':
3047 case 'e':
3048 {
3049 if (LocaleCompare(attribute,"expression") == 0)
3050 {
3051 (void) CopyMagickString(expression,SvPV(ST(i),na),
cristy151b66d2015-04-15 10:50:31 +00003052 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003053 break;
3054 }
3055 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3056 attribute);
3057 break;
3058 }
3059 default:
3060 {
3061 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3062 attribute);
3063 break;
3064 }
3065 }
3066 }
3067 channel_mask=SetImageChannelMask(image,channel);
3068 image=ChannelFxImage(image,expression,exception);
3069 if (image != (Image *) NULL)
3070 (void) SetImageChannelMask(image,channel_mask);
3071 if (image == (Image *) NULL)
3072 goto PerlException;
3073 for ( ; image; image=image->next)
3074 {
3075 AddImageToRegistry(sv,image);
3076 rv=newRV(sv);
3077 av_push(av,sv_bless(rv,hv));
3078 SvREFCNT_dec(sv);
3079 }
3080 exception=DestroyExceptionInfo(exception);
3081 ST(0)=av_reference;
3082 SvREFCNT_dec(perl_exception); /* can't return warning messages */
3083 XSRETURN(1);
3084
3085 PerlException:
3086 InheritPerlException(exception,perl_exception);
3087 exception=DestroyExceptionInfo(exception);
3088 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3089 SvPOK_on(perl_exception);
3090 ST(0)=sv_2mortal(perl_exception);
3091 XSRETURN(1);
3092 }
3093
3094#
3095###############################################################################
3096# #
3097# #
3098# #
3099# C l o n e #
3100# #
3101# #
3102# #
3103###############################################################################
3104#
3105#
3106void
3107Clone(ref)
3108 Image::Magick ref=NO_INIT
3109 ALIAS:
3110 CopyImage = 1
3111 copy = 2
3112 copyimage = 3
3113 CloneImage = 4
3114 clone = 5
3115 cloneimage = 6
3116 Clone = 7
3117 PPCODE:
3118 {
3119 AV
3120 *av;
3121
3122 ExceptionInfo
3123 *exception;
3124
3125 HV
3126 *hv;
3127
3128 Image
3129 *clone,
3130 *image;
3131
3132 struct PackageInfo
3133 *info;
3134
3135 SV
3136 *perl_exception,
3137 *reference,
3138 *rv,
3139 *sv;
3140
3141 PERL_UNUSED_VAR(ref);
3142 PERL_UNUSED_VAR(ix);
3143 exception=AcquireExceptionInfo();
3144 perl_exception=newSVpv("",0);
3145 sv=NULL;
3146 if (sv_isobject(ST(0)) == 0)
3147 {
3148 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3149 PackageName);
3150 goto PerlException;
3151 }
3152 reference=SvRV(ST(0));
3153 hv=SvSTASH(reference);
3154 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3155 if (image == (Image *) NULL)
3156 {
3157 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3158 PackageName);
3159 goto PerlException;
3160 }
3161 /*
3162 Create blessed Perl array for the returned image.
3163 */
3164 av=newAV();
3165 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3166 SvREFCNT_dec(av);
3167 for ( ; image; image=image->next)
3168 {
3169 clone=CloneImage(image,0,0,MagickTrue,exception);
3170 if (clone == (Image *) NULL)
3171 break;
3172 AddImageToRegistry(sv,clone);
3173 rv=newRV(sv);
3174 av_push(av,sv_bless(rv,hv));
3175 SvREFCNT_dec(sv);
3176 }
3177 exception=DestroyExceptionInfo(exception);
3178 SvREFCNT_dec(perl_exception);
3179 XSRETURN(1);
3180
3181 PerlException:
3182 InheritPerlException(exception,perl_exception);
3183 exception=DestroyExceptionInfo(exception);
3184 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3185 SvPOK_on(perl_exception);
3186 ST(0)=sv_2mortal(perl_exception);
3187 XSRETURN(1);
3188 }
3189
3190#
3191###############################################################################
3192# #
3193# #
3194# #
3195# C L O N E #
3196# #
3197# #
3198# #
3199###############################################################################
3200#
3201#
3202void
3203CLONE(ref,...)
3204 SV *ref;
3205 CODE:
3206 {
3207 PERL_UNUSED_VAR(ref);
3208 if (magick_registry != (SplayTreeInfo *) NULL)
3209 {
3210 register Image
3211 *p;
3212
3213 ResetSplayTreeIterator(magick_registry);
3214 p=(Image *) GetNextKeyInSplayTree(magick_registry);
3215 while (p != (Image *) NULL)
3216 {
3217 ReferenceImage(p);
3218 p=(Image *) GetNextKeyInSplayTree(magick_registry);
3219 }
3220 }
3221 }
3222
3223#
3224###############################################################################
3225# #
3226# #
3227# #
3228# C o a l e s c e #
3229# #
3230# #
3231# #
3232###############################################################################
3233#
3234#
3235void
3236Coalesce(ref)
3237 Image::Magick ref=NO_INIT
3238 ALIAS:
3239 CoalesceImage = 1
3240 coalesce = 2
3241 coalesceimage = 3
3242 PPCODE:
3243 {
3244 AV
3245 *av;
3246
3247 ExceptionInfo
3248 *exception;
3249
3250 HV
3251 *hv;
3252
3253 Image
3254 *image;
3255
3256 struct PackageInfo
3257 *info;
3258
3259 SV
3260 *av_reference,
3261 *perl_exception,
3262 *reference,
3263 *rv,
3264 *sv;
3265
3266 PERL_UNUSED_VAR(ref);
3267 PERL_UNUSED_VAR(ix);
3268 exception=AcquireExceptionInfo();
3269 perl_exception=newSVpv("",0);
3270 sv=NULL;
3271 if (sv_isobject(ST(0)) == 0)
3272 {
3273 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3274 PackageName);
3275 goto PerlException;
3276 }
3277 reference=SvRV(ST(0));
3278 hv=SvSTASH(reference);
3279 av=newAV();
3280 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3281 SvREFCNT_dec(av);
3282 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3283 if (image == (Image *) NULL)
3284 {
3285 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3286 PackageName);
3287 goto PerlException;
3288 }
3289 image=CoalesceImages(image,exception);
3290 if (image == (Image *) NULL)
3291 goto PerlException;
3292 for ( ; image; image=image->next)
3293 {
3294 AddImageToRegistry(sv,image);
3295 rv=newRV(sv);
3296 av_push(av,sv_bless(rv,hv));
3297 SvREFCNT_dec(sv);
3298 }
3299 exception=DestroyExceptionInfo(exception);
3300 ST(0)=av_reference;
3301 SvREFCNT_dec(perl_exception);
3302 XSRETURN(1);
3303
3304 PerlException:
3305 InheritPerlException(exception,perl_exception);
3306 exception=DestroyExceptionInfo(exception);
3307 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3308 SvPOK_on(perl_exception);
3309 ST(0)=sv_2mortal(perl_exception);
3310 XSRETURN(1);
3311 }
3312
3313#
3314###############################################################################
3315# #
3316# #
3317# #
3318# C o m p a r e #
3319# #
3320# #
3321# #
3322###############################################################################
3323#
3324#
3325void
3326Compare(ref,...)
3327 Image::Magick ref=NO_INIT
3328 ALIAS:
3329 CompareImages = 1
3330 compare = 2
3331 compareimage = 3
3332 PPCODE:
3333 {
3334 AV
3335 *av;
3336
3337 char
3338 *attribute;
3339
3340 double
3341 distortion;
3342
3343 ExceptionInfo
3344 *exception;
3345
3346 HV
3347 *hv;
3348
3349 Image
3350 *difference_image,
3351 *image,
3352 *reconstruct_image;
3353
3354 MetricType
3355 metric;
3356
3357 register ssize_t
3358 i;
3359
3360 ssize_t
3361 option;
3362
3363 struct PackageInfo
3364 *info;
3365
3366 SV
3367 *av_reference,
3368 *perl_exception,
3369 *reference,
3370 *rv,
3371 *sv;
3372
3373 PERL_UNUSED_VAR(ref);
3374 PERL_UNUSED_VAR(ix);
3375 exception=AcquireExceptionInfo();
3376 perl_exception=newSVpv("",0);
3377 sv=NULL;
3378 av=NULL;
3379 attribute=NULL;
3380 if (sv_isobject(ST(0)) == 0)
3381 {
3382 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3383 PackageName);
3384 goto PerlException;
3385 }
3386 reference=SvRV(ST(0));
3387 hv=SvSTASH(reference);
3388 av=newAV();
3389 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3390 SvREFCNT_dec(av);
3391 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3392 if (image == (Image *) NULL)
3393 {
3394 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3395 PackageName);
3396 goto PerlException;
3397 }
3398 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3399 /*
3400 Get attribute.
3401 */
3402 reconstruct_image=image;
3403 metric=RootMeanSquaredErrorMetric;
3404 for (i=2; i < items; i+=2)
3405 {
3406 attribute=(char *) SvPV(ST(i-1),na);
3407 switch (*attribute)
3408 {
3409 case 'C':
3410 case 'c':
3411 {
3412 if (LocaleCompare(attribute,"channel") == 0)
3413 {
3414 ssize_t
3415 option;
3416
3417 option=ParseChannelOption(SvPV(ST(i),na));
3418 if (option < 0)
3419 {
3420 ThrowPerlException(exception,OptionError,
3421 "UnrecognizedType",SvPV(ST(i),na));
3422 return;
3423 }
cristybcd59342015-06-07 14:07:19 +00003424 (void) SetPixelChannelMask(image,(ChannelType) option);
cristy4a3ce0a2013-08-03 20:06:59 +00003425 break;
3426 }
3427 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3428 attribute);
3429 break;
3430 }
3431 case 'F':
3432 case 'f':
3433 {
3434 if (LocaleCompare(attribute,"fuzz") == 0)
3435 {
3436 image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3437 break;
3438 }
3439 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3440 attribute);
3441 break;
3442 }
3443 case 'I':
3444 case 'i':
3445 {
3446 if (LocaleCompare(attribute,"image") == 0)
3447 {
3448 reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3449 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3450 break;
3451 }
3452 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3453 attribute);
3454 break;
3455 }
3456 case 'M':
3457 case 'm':
3458 {
3459 if (LocaleCompare(attribute,"metric") == 0)
3460 {
3461 option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3462 SvPV(ST(i),na));
3463 if (option < 0)
3464 {
3465 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3466 SvPV(ST(i),na));
3467 break;
3468 }
3469 metric=(MetricType) option;
3470 break;
3471 }
3472 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3473 attribute);
3474 break;
3475 }
3476 default:
3477 {
3478 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3479 attribute);
3480 break;
3481 }
3482 }
3483 }
3484 difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3485 exception);
3486 if (difference_image != (Image *) NULL)
3487 {
3488 difference_image->error.mean_error_per_pixel=distortion;
3489 AddImageToRegistry(sv,difference_image);
3490 rv=newRV(sv);
3491 av_push(av,sv_bless(rv,hv));
3492 SvREFCNT_dec(sv);
3493 }
3494 exception=DestroyExceptionInfo(exception);
3495 ST(0)=av_reference;
3496 SvREFCNT_dec(perl_exception); /* can't return warning messages */
3497 XSRETURN(1);
3498
3499 PerlException:
3500 InheritPerlException(exception,perl_exception);
3501 exception=DestroyExceptionInfo(exception);
3502 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3503 SvPOK_on(perl_exception);
3504 ST(0)=sv_2mortal(perl_exception);
3505 XSRETURN(1);
3506 }
3507
3508#
3509###############################################################################
3510# #
3511# #
3512# #
cristy15655332013-10-06 00:27:33 +00003513# C o m p l e x I m a g e s #
3514# #
3515# #
3516# #
3517###############################################################################
3518#
3519#
3520void
3521ComplexImages(ref)
3522 Image::Magick ref=NO_INIT
3523 ALIAS:
3524 ComplexImages = 1
3525 compleximages = 2
3526 PPCODE:
3527 {
3528 AV
3529 *av;
3530
3531 char
3532 *attribute,
3533 *p;
3534
cristyfa21e9e2013-10-07 10:37:38 +00003535 ComplexOperator
3536 op;
3537
cristy15655332013-10-06 00:27:33 +00003538 ExceptionInfo
3539 *exception;
3540
3541 HV
3542 *hv;
3543
3544 Image
3545 *image;
3546
cristy15655332013-10-06 00:27:33 +00003547 register ssize_t
3548 i;
3549
3550 struct PackageInfo
3551 *info;
3552
3553 SV
3554 *perl_exception,
3555 *reference,
3556 *rv,
3557 *sv;
3558
3559 PERL_UNUSED_VAR(ref);
3560 PERL_UNUSED_VAR(ix);
3561 exception=AcquireExceptionInfo();
3562 perl_exception=newSVpv("",0);
3563 sv=NULL;
3564 if (sv_isobject(ST(0)) == 0)
3565 {
3566 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3567 PackageName);
3568 goto PerlException;
3569 }
3570 reference=SvRV(ST(0));
3571 hv=SvSTASH(reference);
3572 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3573 if (image == (Image *) NULL)
3574 {
3575 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3576 PackageName);
3577 goto PerlException;
3578 }
cristyfd168722013-10-07 15:59:31 +00003579 op=UndefinedComplexOperator;
cristy15655332013-10-06 00:27:33 +00003580 if (items == 2)
3581 {
3582 ssize_t
3583 in;
3584
3585 in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3586 SvPV(ST(1),na));
3587 if (in < 0)
3588 {
3589 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3590 SvPV(ST(1),na));
3591 return;
3592 }
cristyfa21e9e2013-10-07 10:37:38 +00003593 op=(ComplexOperator) in;
cristy15655332013-10-06 00:27:33 +00003594 }
3595 else
3596 for (i=2; i < items; i+=2)
3597 {
3598 attribute=(char *) SvPV(ST(i-1),na);
3599 switch (*attribute)
3600 {
3601 case 'O':
3602 case 'o':
3603 {
3604 if (LocaleCompare(attribute,"operator") == 0)
3605 {
3606 ssize_t
3607 in;
3608
3609 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3610 MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3611 if (in < 0)
3612 {
3613 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3614 SvPV(ST(i),na));
3615 return;
3616 }
cristyfa21e9e2013-10-07 10:37:38 +00003617 op=(ComplexOperator) in;
cristy15655332013-10-06 00:27:33 +00003618 break;
3619 }
3620 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3621 attribute);
3622 break;
3623 }
3624 default:
3625 {
3626 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3627 attribute);
3628 break;
3629 }
3630 }
3631 }
3632 image=ComplexImages(image,op,exception);
3633 if (image == (Image *) NULL)
3634 goto PerlException;
3635 /*
3636 Create blessed Perl array for the returned image.
3637 */
3638 av=newAV();
3639 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3640 SvREFCNT_dec(av);
3641 AddImageToRegistry(sv,image);
3642 rv=newRV(sv);
3643 av_push(av,sv_bless(rv,hv));
3644 SvREFCNT_dec(sv);
3645 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00003646 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3647 "complex-%.*s",(int) (MagickPathExtent-9),
cristy15655332013-10-06 00:27:33 +00003648 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3649 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00003650 MagickPathExtent);
cristy15655332013-10-06 00:27:33 +00003651 SetImageInfo(info->image_info,0,exception);
3652 exception=DestroyExceptionInfo(exception);
3653 SvREFCNT_dec(perl_exception);
3654 XSRETURN(1);
3655
3656 PerlException:
3657 InheritPerlException(exception,perl_exception);
3658 exception=DestroyExceptionInfo(exception);
3659 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3660 SvPOK_on(perl_exception);
3661 ST(0)=sv_2mortal(perl_exception);
3662 XSRETURN(1);
3663 }
3664
3665#
3666###############################################################################
3667# #
3668# #
3669# #
cristy4a3ce0a2013-08-03 20:06:59 +00003670# C o m p a r e L a y e r s #
3671# #
3672# #
3673# #
3674###############################################################################
3675#
3676#
3677void
3678CompareLayers(ref)
3679 Image::Magick ref=NO_INIT
3680 ALIAS:
3681 CompareImagesLayers = 1
3682 comparelayers = 2
3683 compareimagelayers = 3
3684 PPCODE:
3685 {
3686 AV
3687 *av;
3688
3689 char
3690 *attribute;
3691
3692 ExceptionInfo
3693 *exception;
3694
3695 HV
3696 *hv;
3697
3698 Image
3699 *image;
3700
3701 LayerMethod
3702 method;
3703
3704 register ssize_t
3705 i;
3706
3707 ssize_t
3708 option;
3709
3710 struct PackageInfo
3711 *info;
3712
3713 SV
3714 *av_reference,
3715 *perl_exception,
3716 *reference,
3717 *rv,
3718 *sv;
3719
3720 PERL_UNUSED_VAR(ref);
3721 PERL_UNUSED_VAR(ix);
3722 exception=AcquireExceptionInfo();
3723 perl_exception=newSVpv("",0);
3724 sv=NULL;
3725 if (sv_isobject(ST(0)) == 0)
3726 {
3727 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3728 PackageName);
3729 goto PerlException;
3730 }
3731 reference=SvRV(ST(0));
3732 hv=SvSTASH(reference);
3733 av=newAV();
3734 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3735 SvREFCNT_dec(av);
3736 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3737 if (image == (Image *) NULL)
3738 {
3739 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3740 PackageName);
3741 goto PerlException;
3742 }
3743 method=CompareAnyLayer;
3744 for (i=2; i < items; i+=2)
3745 {
3746 attribute=(char *) SvPV(ST(i-1),na);
3747 switch (*attribute)
3748 {
3749 case 'M':
3750 case 'm':
3751 {
3752 if (LocaleCompare(attribute,"method") == 0)
3753 {
3754 option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3755 SvPV(ST(i),na));
3756 if (option < 0)
3757 {
3758 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3759 SvPV(ST(i),na));
3760 break;
3761 }
3762 method=(LayerMethod) option;
3763 break;
3764 }
3765 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3766 attribute);
3767 break;
3768 }
3769 default:
3770 {
3771 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3772 attribute);
3773 break;
3774 }
3775 }
3776 }
3777 image=CompareImagesLayers(image,method,exception);
3778 if (image == (Image *) NULL)
3779 goto PerlException;
3780 for ( ; image; image=image->next)
3781 {
3782 AddImageToRegistry(sv,image);
3783 rv=newRV(sv);
3784 av_push(av,sv_bless(rv,hv));
3785 SvREFCNT_dec(sv);
3786 }
3787 exception=DestroyExceptionInfo(exception);
3788 ST(0)=av_reference;
3789 SvREFCNT_dec(perl_exception);
3790 XSRETURN(1);
3791
3792 PerlException:
3793 InheritPerlException(exception,perl_exception);
3794 exception=DestroyExceptionInfo(exception);
3795 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3796 SvPOK_on(perl_exception);
3797 ST(0)=sv_2mortal(perl_exception);
3798 XSRETURN(1);
3799 }
3800
3801#
3802###############################################################################
3803# #
3804# #
3805# #
3806# D e s t r o y #
3807# #
3808# #
3809# #
3810###############################################################################
3811#
3812#
3813void
3814DESTROY(ref)
3815 Image::Magick ref=NO_INIT
3816 PPCODE:
3817 {
3818 SV
3819 *reference;
3820
3821 PERL_UNUSED_VAR(ref);
3822 if (sv_isobject(ST(0)) == 0)
3823 croak("ReferenceIsNotMyType");
3824 reference=SvRV(ST(0));
3825 switch (SvTYPE(reference))
3826 {
3827 case SVt_PVAV:
3828 {
3829 char
cristy151b66d2015-04-15 10:50:31 +00003830 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00003831
3832 const SV
3833 *key;
3834
3835 HV
3836 *hv;
3837
3838 GV
3839 **gvp;
3840
3841 struct PackageInfo
3842 *info;
3843
3844 SV
3845 *sv;
3846
3847 /*
3848 Array (AV *) reference
3849 */
cristy151b66d2015-04-15 10:50:31 +00003850 (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
cristy4a3ce0a2013-08-03 20:06:59 +00003851 XS_VERSION,reference);
3852 hv=gv_stashpv(PackageName, FALSE);
3853 if (!hv)
3854 break;
3855 gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3856 if (!gvp)
3857 break;
3858 sv=GvSV(*gvp);
3859 if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3860 {
3861 info=INT2PTR(struct PackageInfo *,SvIV(sv));
3862 DestroyPackageInfo(info);
3863 }
3864 key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3865 (void) key;
3866 break;
3867 }
3868 case SVt_PVMG:
3869 {
3870 Image
3871 *image;
3872
3873 /*
3874 Blessed scalar = (Image *) SvIV(reference)
3875 */
3876 image=INT2PTR(Image *,SvIV(reference));
3877 if (image != (Image *) NULL)
3878 DeleteImageFromRegistry(reference,image);
3879 break;
3880 }
3881 default:
3882 break;
3883 }
3884 }
3885
3886#
3887###############################################################################
3888# #
3889# #
3890# #
3891# D i s p l a y #
3892# #
3893# #
3894# #
3895###############################################################################
3896#
3897#
3898void
3899Display(ref,...)
3900 Image::Magick ref=NO_INIT
3901 ALIAS:
3902 DisplayImage = 1
3903 display = 2
3904 displayimage = 3
3905 PPCODE:
3906 {
3907 ExceptionInfo
3908 *exception;
3909
3910 Image
3911 *image;
3912
3913 register ssize_t
3914 i;
3915
3916 struct PackageInfo
3917 *info,
3918 *package_info;
3919
3920 SV
3921 *perl_exception,
3922 *reference;
3923
3924 PERL_UNUSED_VAR(ref);
3925 PERL_UNUSED_VAR(ix);
3926 exception=AcquireExceptionInfo();
3927 perl_exception=newSVpv("",0);
3928 package_info=(struct PackageInfo *) NULL;
3929 if (sv_isobject(ST(0)) == 0)
3930 {
3931 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3932 PackageName);
3933 goto PerlException;
3934 }
3935 reference=SvRV(ST(0));
3936 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3937 if (image == (Image *) NULL)
3938 {
3939 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3940 PackageName);
3941 goto PerlException;
3942 }
3943 package_info=ClonePackageInfo(info,exception);
3944 if (items == 2)
3945 SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3946 else
3947 if (items > 2)
3948 for (i=2; i < items; i+=2)
3949 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3950 exception);
3951 (void) DisplayImages(package_info->image_info,image,exception);
3952 (void) CatchImageException(image);
3953
3954 PerlException:
3955 if (package_info != (struct PackageInfo *) NULL)
3956 DestroyPackageInfo(package_info);
3957 InheritPerlException(exception,perl_exception);
3958 exception=DestroyExceptionInfo(exception);
3959 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3960 SvPOK_on(perl_exception);
3961 ST(0)=sv_2mortal(perl_exception);
3962 XSRETURN(1);
3963 }
3964
3965#
3966###############################################################################
3967# #
3968# #
3969# #
3970# E v a l u a t e I m a g e s #
3971# #
3972# #
3973# #
3974###############################################################################
3975#
3976#
3977void
3978EvaluateImages(ref)
3979 Image::Magick ref=NO_INIT
3980 ALIAS:
3981 EvaluateImages = 1
3982 evaluateimages = 2
3983 PPCODE:
3984 {
3985 AV
3986 *av;
3987
3988 char
3989 *attribute,
3990 *p;
3991
3992 ExceptionInfo
3993 *exception;
3994
3995 HV
3996 *hv;
3997
3998 Image
3999 *image;
4000
4001 MagickEvaluateOperator
4002 op;
4003
4004 register ssize_t
4005 i;
4006
4007 struct PackageInfo
4008 *info;
4009
4010 SV
4011 *perl_exception,
4012 *reference,
4013 *rv,
4014 *sv;
4015
4016 PERL_UNUSED_VAR(ref);
4017 PERL_UNUSED_VAR(ix);
4018 exception=AcquireExceptionInfo();
4019 perl_exception=newSVpv("",0);
4020 sv=NULL;
4021 if (sv_isobject(ST(0)) == 0)
4022 {
4023 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4024 PackageName);
4025 goto PerlException;
4026 }
4027 reference=SvRV(ST(0));
4028 hv=SvSTASH(reference);
4029 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4030 if (image == (Image *) NULL)
4031 {
4032 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4033 PackageName);
4034 goto PerlException;
4035 }
4036 op=MeanEvaluateOperator;
4037 if (items == 2)
4038 {
4039 ssize_t
4040 in;
4041
4042 in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
4043 SvPV(ST(1),na));
4044 if (in < 0)
4045 {
4046 ThrowPerlException(exception,OptionError,"UnrecognizedType",
4047 SvPV(ST(1),na));
4048 return;
4049 }
4050 op=(MagickEvaluateOperator) in;
4051 }
4052 else
4053 for (i=2; i < items; i+=2)
4054 {
4055 attribute=(char *) SvPV(ST(i-1),na);
4056 switch (*attribute)
4057 {
4058 case 'O':
4059 case 'o':
4060 {
4061 if (LocaleCompare(attribute,"operator") == 0)
4062 {
4063 ssize_t
4064 in;
4065
4066 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4067 MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4068 if (in < 0)
4069 {
4070 ThrowPerlException(exception,OptionError,"UnrecognizedType",
4071 SvPV(ST(i),na));
4072 return;
4073 }
4074 op=(MagickEvaluateOperator) in;
4075 break;
4076 }
4077 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4078 attribute);
4079 break;
4080 }
4081 default:
4082 {
4083 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4084 attribute);
4085 break;
4086 }
4087 }
4088 }
4089 image=EvaluateImages(image,op,exception);
4090 if (image == (Image *) NULL)
4091 goto PerlException;
4092 /*
4093 Create blessed Perl array for the returned image.
4094 */
4095 av=newAV();
4096 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4097 SvREFCNT_dec(av);
4098 AddImageToRegistry(sv,image);
4099 rv=newRV(sv);
4100 av_push(av,sv_bless(rv,hv));
4101 SvREFCNT_dec(sv);
4102 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00004103 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4104 "evaluate-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00004105 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4106 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00004107 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004108 SetImageInfo(info->image_info,0,exception);
4109 exception=DestroyExceptionInfo(exception);
4110 SvREFCNT_dec(perl_exception);
4111 XSRETURN(1);
4112
4113 PerlException:
4114 InheritPerlException(exception,perl_exception);
4115 exception=DestroyExceptionInfo(exception);
4116 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4117 SvPOK_on(perl_exception);
4118 ST(0)=sv_2mortal(perl_exception);
4119 XSRETURN(1);
4120 }
4121
4122#
4123###############################################################################
4124# #
4125# #
4126# #
4127# F e a t u r e s #
4128# #
4129# #
4130# #
4131###############################################################################
4132#
4133#
4134void
4135Features(ref,...)
4136 Image::Magick ref=NO_INIT
4137 ALIAS:
4138 FeaturesImage = 1
4139 features = 2
4140 featuresimage = 3
4141 PPCODE:
4142 {
4143#define ChannelFeatures(channel,direction) \
4144{ \
Cristyb1710fe2017-02-11 13:51:48 -05004145 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004146 channel_features[channel].angular_second_moment[direction]); \
4147 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004148 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004149 channel_features[channel].contrast[direction]); \
4150 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004151 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004152 channel_features[channel].contrast[direction]); \
4153 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004154 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004155 channel_features[channel].variance_sum_of_squares[direction]); \
4156 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004157 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004158 channel_features[channel].inverse_difference_moment[direction]); \
4159 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004160 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004161 channel_features[channel].sum_average[direction]); \
4162 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004163 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004164 channel_features[channel].sum_variance[direction]); \
4165 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004166 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004167 channel_features[channel].sum_entropy[direction]); \
4168 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004169 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004170 channel_features[channel].entropy[direction]); \
4171 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004172 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004173 channel_features[channel].difference_variance[direction]); \
4174 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004175 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004176 channel_features[channel].difference_entropy[direction]); \
4177 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004178 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004179 channel_features[channel].measure_of_correlation_1[direction]); \
4180 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004181 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004182 channel_features[channel].measure_of_correlation_2[direction]); \
4183 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004184 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004185 channel_features[channel].maximum_correlation_coefficient[direction]); \
4186 PUSHs(sv_2mortal(newSVpv(message,0))); \
4187}
4188
4189 AV
4190 *av;
4191
4192 char
4193 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004194 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004195
4196 ChannelFeatures
4197 *channel_features;
4198
4199 double
4200 distance;
4201
4202 ExceptionInfo
4203 *exception;
4204
4205 Image
4206 *image;
4207
4208 register ssize_t
4209 i;
4210
4211 ssize_t
4212 count;
4213
4214 struct PackageInfo
4215 *info;
4216
4217 SV
4218 *perl_exception,
4219 *reference;
4220
4221 PERL_UNUSED_VAR(ref);
4222 PERL_UNUSED_VAR(ix);
4223 exception=AcquireExceptionInfo();
4224 perl_exception=newSVpv("",0);
4225 av=NULL;
4226 if (sv_isobject(ST(0)) == 0)
4227 {
4228 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4229 PackageName);
4230 goto PerlException;
4231 }
4232 reference=SvRV(ST(0));
4233 av=newAV();
4234 SvREFCNT_dec(av);
4235 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4236 if (image == (Image *) NULL)
4237 {
4238 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4239 PackageName);
4240 goto PerlException;
4241 }
cristy7dbd9262014-07-02 17:53:42 +00004242 distance=1.0;
cristy4a3ce0a2013-08-03 20:06:59 +00004243 for (i=2; i < items; i+=2)
4244 {
4245 attribute=(char *) SvPV(ST(i-1),na);
4246 switch (*attribute)
4247 {
4248 case 'D':
4249 case 'd':
4250 {
4251 if (LocaleCompare(attribute,"distance") == 0)
4252 {
4253 distance=StringToLong((char *) SvPV(ST(1),na));
4254 break;
4255 }
4256 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4257 attribute);
4258 break;
4259 }
4260 default:
4261 {
4262 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4263 attribute);
4264 break;
4265 }
4266 }
4267 }
4268 count=0;
4269 for ( ; image; image=image->next)
4270 {
Cristy5a854dc2017-02-11 15:43:46 -05004271 register ssize_t
4272 j;
4273
cristy4a3ce0a2013-08-03 20:06:59 +00004274 channel_features=GetImageFeatures(image,distance,exception);
4275 if (channel_features == (ChannelFeatures *) NULL)
4276 continue;
4277 count++;
Cristy5a854dc2017-02-11 15:43:46 -05004278 for (j=0; j < 4; j++)
cristy4a3ce0a2013-08-03 20:06:59 +00004279 {
Cristy5a854dc2017-02-11 15:43:46 -05004280 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
4281 {
4282 PixelChannel channel=GetPixelChannelChannel(image,i);
4283 PixelTrait traits=GetPixelChannelTraits(image,channel);
4284 if (traits == UndefinedPixelTrait)
4285 continue;
4286 EXTEND(sp,14*(i+1)*count);
4287 ChannelFeatures(channel,j);
4288 }
cristy4a3ce0a2013-08-03 20:06:59 +00004289 }
4290 channel_features=(ChannelFeatures *)
4291 RelinquishMagickMemory(channel_features);
4292 }
4293
4294 PerlException:
4295 InheritPerlException(exception,perl_exception);
4296 exception=DestroyExceptionInfo(exception);
4297 SvREFCNT_dec(perl_exception);
4298 }
4299
4300#
4301###############################################################################
4302# #
4303# #
4304# #
4305# F l a t t e n #
4306# #
4307# #
4308# #
4309###############################################################################
4310#
4311#
4312void
4313Flatten(ref)
4314 Image::Magick ref=NO_INIT
4315 ALIAS:
4316 FlattenImage = 1
4317 flatten = 2
4318 flattenimage = 3
4319 PPCODE:
4320 {
4321 AV
4322 *av;
4323
4324 char
4325 *attribute,
4326 *p;
4327
4328 ExceptionInfo
4329 *exception;
4330
4331 HV
4332 *hv;
4333
4334 Image
4335 *image;
4336
4337 PixelInfo
4338 background_color;
4339
4340 register ssize_t
4341 i;
4342
4343 struct PackageInfo
4344 *info;
4345
4346 SV
4347 *perl_exception,
4348 *reference,
4349 *rv,
4350 *sv;
4351
4352 PERL_UNUSED_VAR(ref);
4353 PERL_UNUSED_VAR(ix);
4354 exception=AcquireExceptionInfo();
4355 perl_exception=newSVpv("",0);
4356 sv=NULL;
4357 if (sv_isobject(ST(0)) == 0)
4358 {
4359 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4360 PackageName);
4361 goto PerlException;
4362 }
4363 reference=SvRV(ST(0));
4364 hv=SvSTASH(reference);
4365 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4366 if (image == (Image *) NULL)
4367 {
4368 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4369 PackageName);
4370 goto PerlException;
4371 }
4372 background_color=image->background_color;
4373 if (items == 2)
4374 (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4375 &background_color,exception);
4376 else
4377 for (i=2; i < items; i+=2)
4378 {
4379 attribute=(char *) SvPV(ST(i-1),na);
4380 switch (*attribute)
4381 {
4382 case 'B':
4383 case 'b':
4384 {
4385 if (LocaleCompare(attribute,"background") == 0)
4386 {
4387 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4388 AllCompliance,&background_color,exception);
4389 break;
4390 }
4391 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4392 attribute);
4393 break;
4394 }
4395 default:
4396 {
4397 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4398 attribute);
4399 break;
4400 }
4401 }
4402 }
4403 image->background_color=background_color;
4404 image=MergeImageLayers(image,FlattenLayer,exception);
4405 if (image == (Image *) NULL)
4406 goto PerlException;
4407 /*
4408 Create blessed Perl array for the returned image.
4409 */
4410 av=newAV();
4411 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4412 SvREFCNT_dec(av);
4413 AddImageToRegistry(sv,image);
4414 rv=newRV(sv);
4415 av_push(av,sv_bless(rv,hv));
4416 SvREFCNT_dec(sv);
4417 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00004418 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4419 "flatten-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00004420 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4421 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00004422 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004423 SetImageInfo(info->image_info,0,exception);
4424 exception=DestroyExceptionInfo(exception);
4425 SvREFCNT_dec(perl_exception);
4426 XSRETURN(1);
4427
4428 PerlException:
4429 InheritPerlException(exception,perl_exception);
4430 exception=DestroyExceptionInfo(exception);
4431 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4432 SvPOK_on(perl_exception); /* return messages in string context */
4433 ST(0)=sv_2mortal(perl_exception);
4434 XSRETURN(1);
4435 }
4436
4437#
4438###############################################################################
4439# #
4440# #
4441# #
4442# F x #
4443# #
4444# #
4445# #
4446###############################################################################
4447#
4448#
4449void
4450Fx(ref,...)
4451 Image::Magick ref=NO_INIT
4452 ALIAS:
4453 FxImage = 1
4454 fx = 2
4455 fximage = 3
4456 PPCODE:
4457 {
4458 AV
4459 *av;
4460
4461 char
4462 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004463 expression[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004464
4465 ChannelType
4466 channel,
4467 channel_mask;
4468
4469 ExceptionInfo
4470 *exception;
4471
4472 HV
4473 *hv;
4474
4475 Image
4476 *image;
4477
4478 register ssize_t
4479 i;
4480
4481 struct PackageInfo
4482 *info;
4483
4484 SV
4485 *av_reference,
4486 *perl_exception,
4487 *reference,
4488 *rv,
4489 *sv;
4490
4491 PERL_UNUSED_VAR(ref);
4492 PERL_UNUSED_VAR(ix);
4493 exception=AcquireExceptionInfo();
4494 perl_exception=newSVpv("",0);
4495 sv=NULL;
4496 attribute=NULL;
4497 av=NULL;
4498 if (sv_isobject(ST(0)) == 0)
4499 {
4500 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4501 PackageName);
4502 goto PerlException;
4503 }
4504 reference=SvRV(ST(0));
4505 hv=SvSTASH(reference);
4506 av=newAV();
4507 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4508 SvREFCNT_dec(av);
4509 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4510 if (image == (Image *) NULL)
4511 {
4512 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4513 PackageName);
4514 goto PerlException;
4515 }
4516 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4517 /*
4518 Get options.
4519 */
4520 channel=DefaultChannels;
cristy151b66d2015-04-15 10:50:31 +00004521 (void) CopyMagickString(expression,"u",MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004522 if (items == 2)
cristy151b66d2015-04-15 10:50:31 +00004523 (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004524 else
4525 for (i=2; i < items; i+=2)
4526 {
4527 attribute=(char *) SvPV(ST(i-1),na);
4528 switch (*attribute)
4529 {
4530 case 'C':
4531 case 'c':
4532 {
4533 if (LocaleCompare(attribute,"channel") == 0)
4534 {
4535 ssize_t
4536 option;
4537
4538 option=ParseChannelOption(SvPV(ST(i),na));
4539 if (option < 0)
4540 {
4541 ThrowPerlException(exception,OptionError,
4542 "UnrecognizedType",SvPV(ST(i),na));
4543 return;
4544 }
4545 channel=(ChannelType) option;
4546 break;
4547 }
4548 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4549 attribute);
4550 break;
4551 }
4552 case 'E':
4553 case 'e':
4554 {
4555 if (LocaleCompare(attribute,"expression") == 0)
4556 {
4557 (void) CopyMagickString(expression,SvPV(ST(i),na),
cristy151b66d2015-04-15 10:50:31 +00004558 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004559 break;
4560 }
4561 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4562 attribute);
4563 break;
4564 }
4565 default:
4566 {
4567 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4568 attribute);
4569 break;
4570 }
4571 }
4572 }
4573 channel_mask=SetImageChannelMask(image,channel);
4574 image=FxImage(image,expression,exception);
4575 if (image != (Image *) NULL)
4576 (void) SetImageChannelMask(image,channel_mask);
4577 if (image == (Image *) NULL)
4578 goto PerlException;
4579 for ( ; image; image=image->next)
4580 {
4581 AddImageToRegistry(sv,image);
4582 rv=newRV(sv);
4583 av_push(av,sv_bless(rv,hv));
4584 SvREFCNT_dec(sv);
4585 }
4586 exception=DestroyExceptionInfo(exception);
4587 ST(0)=av_reference;
4588 SvREFCNT_dec(perl_exception); /* can't return warning messages */
4589 XSRETURN(1);
4590
4591 PerlException:
4592 InheritPerlException(exception,perl_exception);
4593 exception=DestroyExceptionInfo(exception);
4594 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4595 SvPOK_on(perl_exception);
4596 ST(0)=sv_2mortal(perl_exception);
4597 XSRETURN(1);
4598 }
4599
4600#
4601###############################################################################
4602# #
4603# #
4604# #
4605# G e t #
4606# #
4607# #
4608# #
4609###############################################################################
4610#
4611#
4612void
4613Get(ref,...)
4614 Image::Magick ref=NO_INIT
4615 ALIAS:
4616 GetAttributes = 1
4617 GetAttribute = 2
4618 get = 3
4619 getattributes = 4
4620 getattribute = 5
4621 PPCODE:
4622 {
4623 char
4624 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004625 color[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004626
4627 const char
4628 *value;
4629
4630 ExceptionInfo
4631 *exception;
4632
4633 Image
4634 *image;
4635
4636 long
4637 j;
4638
4639 register ssize_t
4640 i;
4641
4642 struct PackageInfo
4643 *info;
4644
4645 SV
4646 *perl_exception,
4647 *reference,
4648 *s;
4649
4650 PERL_UNUSED_VAR(ref);
4651 PERL_UNUSED_VAR(ix);
4652 exception=AcquireExceptionInfo();
4653 perl_exception=newSVpv("",0);
4654 if (sv_isobject(ST(0)) == 0)
4655 {
4656 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4657 PackageName);
4658 XSRETURN_EMPTY;
4659 }
4660 reference=SvRV(ST(0));
4661 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4662 if (image == (Image *) NULL && !info)
4663 XSRETURN_EMPTY;
4664 EXTEND(sp,items);
4665 for (i=1; i < items; i++)
4666 {
4667 attribute=(char *) SvPV(ST(i),na);
4668 s=NULL;
4669 switch (*attribute)
4670 {
4671 case 'A':
4672 case 'a':
4673 {
4674 if (LocaleCompare(attribute,"adjoin") == 0)
4675 {
4676 if (info)
4677 s=newSViv((ssize_t) info->image_info->adjoin);
4678 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4679 continue;
4680 }
4681 if (LocaleCompare(attribute,"antialias") == 0)
4682 {
4683 if (info)
4684 s=newSViv((ssize_t) info->image_info->antialias);
4685 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4686 continue;
4687 }
4688 if (LocaleCompare(attribute,"area") == 0)
4689 {
4690 s=newSViv(GetMagickResource(AreaResource));
4691 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4692 continue;
4693 }
4694 if (LocaleCompare(attribute,"attenuate") == 0)
4695 {
4696 const char
4697 *value;
4698
4699 value=GetImageProperty(image,attribute,exception);
4700 if (value != (const char *) NULL)
4701 s=newSVpv(value,0);
4702 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4703 continue;
4704 }
4705 if (LocaleCompare(attribute,"authenticate") == 0)
4706 {
4707 if (info)
4708 {
4709 const char
4710 *option;
4711
4712 option=GetImageOption(info->image_info,attribute);
4713 if (option != (const char *) NULL)
4714 s=newSVpv(option,0);
4715 }
4716 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4717 continue;
4718 }
4719 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4720 attribute);
4721 break;
4722 }
4723 case 'B':
4724 case 'b':
4725 {
4726 if (LocaleCompare(attribute,"background") == 0)
4727 {
4728 if (image == (Image *) NULL)
4729 break;
cristy151b66d2015-04-15 10:50:31 +00004730 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004731 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4732 (double) image->background_color.green,
4733 (double) image->background_color.blue,
4734 (double) image->background_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004735 s=newSVpv(color,0);
4736 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4737 continue;
4738 }
4739 if (LocaleCompare(attribute,"base-columns") == 0)
4740 {
4741 if (image != (Image *) NULL)
4742 s=newSViv((ssize_t) image->magick_columns);
4743 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4744 continue;
4745 }
4746 if (LocaleCompare(attribute,"base-filename") == 0)
4747 {
4748 if (image != (Image *) NULL)
4749 s=newSVpv(image->magick_filename,0);
4750 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4751 continue;
4752 }
4753 if (LocaleCompare(attribute,"base-height") == 0)
4754 {
4755 if (image != (Image *) NULL)
4756 s=newSViv((ssize_t) image->magick_rows);
4757 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4758 continue;
4759 }
4760 if (LocaleCompare(attribute,"base-rows") == 0)
4761 {
4762 if (image != (Image *) NULL)
4763 s=newSViv((ssize_t) image->magick_rows);
4764 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4765 continue;
4766 }
4767 if (LocaleCompare(attribute,"base-width") == 0)
4768 {
4769 if (image != (Image *) NULL)
4770 s=newSViv((ssize_t) image->magick_columns);
4771 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4772 continue;
4773 }
4774 if (LocaleCompare(attribute,"blue-primary") == 0)
4775 {
4776 if (image == (Image *) NULL)
4777 break;
Cristyb1710fe2017-02-11 13:51:48 -05004778 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00004779 image->chromaticity.blue_primary.x,
4780 image->chromaticity.blue_primary.y);
4781 s=newSVpv(color,0);
4782 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4783 continue;
4784 }
4785 if (LocaleCompare(attribute,"bordercolor") == 0)
4786 {
4787 if (image == (Image *) NULL)
4788 break;
cristy151b66d2015-04-15 10:50:31 +00004789 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004790 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4791 (double) image->border_color.green,
4792 (double) image->border_color.blue,
4793 (double) image->border_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004794 s=newSVpv(color,0);
4795 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4796 continue;
4797 }
4798 if (LocaleCompare(attribute,"bounding-box") == 0)
4799 {
4800 char
cristy151b66d2015-04-15 10:50:31 +00004801 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004802
4803 RectangleInfo
4804 page;
4805
4806 if (image == (Image *) NULL)
4807 break;
4808 page=GetImageBoundingBox(image,exception);
cristy151b66d2015-04-15 10:50:31 +00004809 (void) FormatLocaleString(geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00004810 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4811 page.height,(double) page.x,(double) page.y);
4812 s=newSVpv(geometry,0);
4813 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4814 continue;
4815 }
4816 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4817 attribute);
4818 break;
4819 }
4820 case 'C':
4821 case 'c':
4822 {
4823 if (LocaleCompare(attribute,"class") == 0)
4824 {
4825 if (image == (Image *) NULL)
4826 break;
4827 s=newSViv(image->storage_class);
4828 (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4829 image->storage_class));
4830 SvIOK_on(s);
4831 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4832 continue;
4833 }
4834 if (LocaleCompare(attribute,"clip-mask") == 0)
4835 {
4836 if (image != (Image *) NULL)
4837 {
4838 Image
4839 *mask_image;
4840
4841 SV
4842 *sv;
4843
4844 sv=NULL;
4845 if (image->read_mask == MagickFalse)
4846 ClipImage(image,exception);
Cristyda6b91a2016-01-11 16:05:27 -05004847 mask_image=GetImageMask(image,ReadPixelMask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004848 if (mask_image != (Image *) NULL)
4849 {
4850 AddImageToRegistry(sv,mask_image);
4851 s=sv_bless(newRV(sv),SvSTASH(reference));
4852 }
4853 }
4854 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4855 continue;
4856 }
4857 if (LocaleCompare(attribute,"clip-path") == 0)
4858 {
4859 if (image != (Image *) NULL)
4860 {
4861 Image
4862 *mask_image;
4863
4864 SV
4865 *sv;
4866
4867 sv=NULL;
4868 if (image->read_mask != MagickFalse)
4869 ClipImage(image,exception);
Cristyda6b91a2016-01-11 16:05:27 -05004870 mask_image=GetImageMask(image,ReadPixelMask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004871 if (mask_image != (Image *) NULL)
4872 {
4873 AddImageToRegistry(sv,mask_image);
4874 s=sv_bless(newRV(sv),SvSTASH(reference));
4875 }
4876 }
4877 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4878 continue;
4879 }
4880 if (LocaleCompare(attribute,"compression") == 0)
4881 {
4882 j=info ? info->image_info->compression : image ?
4883 image->compression : UndefinedCompression;
4884 if (info)
4885 if (info->image_info->compression == UndefinedCompression)
4886 j=image->compression;
4887 s=newSViv(j);
4888 (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4889 j));
4890 SvIOK_on(s);
4891 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4892 continue;
4893 }
4894 if (LocaleCompare(attribute,"colorspace") == 0)
4895 {
4896 j=image ? image->colorspace : RGBColorspace;
4897 s=newSViv(j);
4898 (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4899 j));
4900 SvIOK_on(s);
4901 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4902 continue;
4903 }
4904 if (LocaleCompare(attribute,"colors") == 0)
4905 {
4906 if (image != (Image *) NULL)
4907 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4908 exception));
4909 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4910 continue;
4911 }
4912 if (LocaleNCompare(attribute,"colormap",8) == 0)
4913 {
4914 int
4915 items;
4916
4917 if (image == (Image *) NULL || !image->colormap)
4918 break;
4919 j=0;
4920 items=sscanf(attribute,"%*[^[][%ld",&j);
4921 (void) items;
4922 if (j > (ssize_t) image->colors)
4923 j%=image->colors;
cristy151b66d2015-04-15 10:50:31 +00004924 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004925 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4926 (double) image->colormap[j].green,
4927 (double) image->colormap[j].blue,
4928 (double) image->colormap[j].alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004929 s=newSVpv(color,0);
4930 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4931 continue;
4932 }
4933 if (LocaleCompare(attribute,"columns") == 0)
4934 {
4935 if (image != (Image *) NULL)
4936 s=newSViv((ssize_t) image->columns);
4937 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4938 continue;
4939 }
4940 if (LocaleCompare(attribute,"comment") == 0)
4941 {
4942 const char
4943 *value;
4944
Cristy935a4052017-03-31 17:45:37 -04004945 value=GetImageProperty(image,attribute,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004946 if (value != (const char *) NULL)
4947 s=newSVpv(value,0);
4948 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4949 continue;
4950 }
4951 if (LocaleCompare(attribute,"copyright") == 0)
4952 {
4953 s=newSVpv(GetMagickCopyright(),0);
4954 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4955 continue;
4956 }
4957 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4958 attribute);
4959 break;
4960 }
4961 case 'D':
4962 case 'd':
4963 {
4964 if (LocaleCompare(attribute,"density") == 0)
4965 {
4966 char
cristy151b66d2015-04-15 10:50:31 +00004967 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004968
4969 if (image == (Image *) NULL)
4970 break;
Cristyb1710fe2017-02-11 13:51:48 -05004971 (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00004972 image->resolution.x,image->resolution.y);
4973 s=newSVpv(geometry,0);
4974 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4975 continue;
4976 }
4977 if (LocaleCompare(attribute,"delay") == 0)
4978 {
4979 if (image != (Image *) NULL)
4980 s=newSViv((ssize_t) image->delay);
4981 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4982 continue;
4983 }
4984 if (LocaleCompare(attribute,"depth") == 0)
4985 {
4986 s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4987 if (image != (Image *) NULL)
4988 s=newSViv((ssize_t) GetImageDepth(image,exception));
4989 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4990 continue;
4991 }
4992 if (LocaleCompare(attribute,"directory") == 0)
4993 {
4994 if (image && image->directory)
4995 s=newSVpv(image->directory,0);
4996 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4997 continue;
4998 }
4999 if (LocaleCompare(attribute,"dispose") == 0)
5000 {
5001 if (image == (Image *) NULL)
5002 break;
5003
5004 s=newSViv(image->dispose);
5005 (void) sv_setpv(s,
5006 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
5007 SvIOK_on(s);
5008 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5009 continue;
5010 }
5011 if (LocaleCompare(attribute,"disk") == 0)
5012 {
5013 s=newSViv(GetMagickResource(DiskResource));
5014 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5015 continue;
5016 }
5017 if (LocaleCompare(attribute,"dither") == 0)
5018 {
5019 if (info)
5020 s=newSViv((ssize_t) info->image_info->dither);
5021 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5022 continue;
5023 }
5024 if (LocaleCompare(attribute,"display") == 0) /* same as server */
5025 {
5026 if (info && info->image_info->server_name)
5027 s=newSVpv(info->image_info->server_name,0);
5028 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5029 continue;
5030 }
5031 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5032 attribute);
5033 break;
5034 }
5035 case 'E':
5036 case 'e':
5037 {
5038 if (LocaleCompare(attribute,"elapsed-time") == 0)
5039 {
5040 if (image != (Image *) NULL)
5041 s=newSVnv(GetElapsedTime(&image->timer));
5042 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5043 continue;
5044 }
5045 if (LocaleCompare(attribute,"endian") == 0)
5046 {
5047 j=info ? info->image_info->endian : image ? image->endian :
5048 UndefinedEndian;
5049 s=newSViv(j);
5050 (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
5051 SvIOK_on(s);
5052 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5053 continue;
5054 }
5055 if (LocaleCompare(attribute,"error") == 0)
5056 {
5057 if (image != (Image *) NULL)
5058 s=newSVnv(image->error.mean_error_per_pixel);
5059 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5060 continue;
5061 }
5062 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5063 attribute);
5064 break;
5065 }
5066 case 'F':
5067 case 'f':
5068 {
5069 if (LocaleCompare(attribute,"filesize") == 0)
5070 {
5071 if (image != (Image *) NULL)
5072 s=newSViv((ssize_t) GetBlobSize(image));
5073 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5074 continue;
5075 }
5076 if (LocaleCompare(attribute,"filename") == 0)
5077 {
Cristy2273d6a2017-07-14 19:19:55 -04005078 if (info && *info->image_info->filename)
cristy4a3ce0a2013-08-03 20:06:59 +00005079 s=newSVpv(info->image_info->filename,0);
5080 if (image != (Image *) NULL)
5081 s=newSVpv(image->filename,0);
5082 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5083 continue;
5084 }
5085 if (LocaleCompare(attribute,"filter") == 0)
5086 {
5087 s=image ? newSViv(image->filter) : newSViv(0);
5088 (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5089 image->filter));
5090 SvIOK_on(s);
5091 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5092 continue;
5093 }
5094 if (LocaleCompare(attribute,"font") == 0)
5095 {
5096 if (info && info->image_info->font)
5097 s=newSVpv(info->image_info->font,0);
5098 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5099 continue;
5100 }
5101 if (LocaleCompare(attribute,"foreground") == 0)
5102 continue;
5103 if (LocaleCompare(attribute,"format") == 0)
5104 {
5105 const MagickInfo
5106 *magick_info;
5107
5108 magick_info=(const MagickInfo *) NULL;
5109 if (info && (*info->image_info->magick != '\0'))
5110 magick_info=GetMagickInfo(info->image_info->magick,exception);
5111 if (image != (Image *) NULL)
5112 magick_info=GetMagickInfo(image->magick,exception);
5113 if ((magick_info != (const MagickInfo *) NULL) &&
5114 (*magick_info->description != '\0'))
5115 s=newSVpv((char *) magick_info->description,0);
5116 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5117 continue;
5118 }
5119 if (LocaleCompare(attribute,"fuzz") == 0)
5120 {
5121 if (info)
5122 s=newSVnv(info->image_info->fuzz);
5123 if (image != (Image *) NULL)
5124 s=newSVnv(image->fuzz);
5125 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5126 continue;
5127 }
5128 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5129 attribute);
5130 break;
5131 }
5132 case 'G':
5133 case 'g':
5134 {
5135 if (LocaleCompare(attribute,"gamma") == 0)
5136 {
5137 if (image != (Image *) NULL)
5138 s=newSVnv(image->gamma);
5139 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5140 continue;
5141 }
5142 if (LocaleCompare(attribute,"geometry") == 0)
5143 {
5144 if (image && image->geometry)
5145 s=newSVpv(image->geometry,0);
5146 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5147 continue;
5148 }
5149 if (LocaleCompare(attribute,"gravity") == 0)
5150 {
5151 s=image ? newSViv(image->gravity) : newSViv(0);
5152 (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5153 image->gravity));
5154 SvIOK_on(s);
5155 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5156 continue;
5157 }
5158 if (LocaleCompare(attribute,"green-primary") == 0)
5159 {
5160 if (image == (Image *) NULL)
5161 break;
Cristyb1710fe2017-02-11 13:51:48 -05005162 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005163 image->chromaticity.green_primary.x,
5164 image->chromaticity.green_primary.y);
5165 s=newSVpv(color,0);
5166 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5167 continue;
5168 }
5169 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5170 attribute);
5171 break;
5172 }
5173 case 'H':
5174 case 'h':
5175 {
5176 if (LocaleCompare(attribute,"height") == 0)
5177 {
5178 if (image != (Image *) NULL)
5179 s=newSViv((ssize_t) image->rows);
5180 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5181 continue;
5182 }
5183 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5184 attribute);
5185 break;
5186 }
5187 case 'I':
5188 case 'i':
5189 {
5190 if (LocaleCompare(attribute,"icc") == 0)
5191 {
5192 if (image != (Image *) NULL)
5193 {
5194 const StringInfo
5195 *profile;
5196
5197 profile=GetImageProfile(image,"icc");
5198 if (profile != (StringInfo *) NULL)
5199 s=newSVpv((const char *) GetStringInfoDatum(profile),
5200 GetStringInfoLength(profile));
5201 }
5202 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5203 continue;
5204 }
5205 if (LocaleCompare(attribute,"icm") == 0)
5206 {
5207 if (image != (Image *) NULL)
5208 {
5209 const StringInfo
5210 *profile;
5211
5212 profile=GetImageProfile(image,"icm");
5213 if (profile != (const StringInfo *) NULL)
5214 s=newSVpv((const char *) GetStringInfoDatum(profile),
5215 GetStringInfoLength(profile));
5216 }
5217 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5218 continue;
5219 }
5220 if (LocaleCompare(attribute,"id") == 0)
5221 {
5222 if (image != (Image *) NULL)
5223 {
5224 char
cristy151b66d2015-04-15 10:50:31 +00005225 key[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005226
5227 MagickBooleanType
5228 status;
5229
5230 static ssize_t
5231 id = 0;
5232
cristy151b66d2015-04-15 10:50:31 +00005233 (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
cristy4a3ce0a2013-08-03 20:06:59 +00005234 id);
5235 status=SetImageRegistry(ImageRegistryType,key,image,
5236 exception);
5237 (void) status;
5238 s=newSViv(id++);
5239 }
5240 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5241 continue;
5242 }
5243 if (LocaleNCompare(attribute,"index",5) == 0)
5244 {
5245 char
cristy151b66d2015-04-15 10:50:31 +00005246 name[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005247
5248 int
5249 items;
5250
5251 long
5252 x,
5253 y;
5254
5255 register const Quantum
5256 *p;
5257
5258 CacheView
5259 *image_view;
5260
5261 if (image == (Image *) NULL)
5262 break;
5263 if (image->storage_class != PseudoClass)
5264 break;
5265 x=0;
5266 y=0;
5267 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5268 (void) items;
5269 image_view=AcquireVirtualCacheView(image,exception);
5270 p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5271 if (p != (const Quantum *) NULL)
5272 {
cristy151b66d2015-04-15 10:50:31 +00005273 (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
cristy4a3ce0a2013-08-03 20:06:59 +00005274 GetPixelIndex(image,p));
5275 s=newSVpv(name,0);
5276 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5277 }
5278 image_view=DestroyCacheView(image_view);
5279 continue;
5280 }
5281 if (LocaleCompare(attribute,"iptc") == 0)
5282 {
5283 if (image != (Image *) NULL)
5284 {
5285 const StringInfo
5286 *profile;
5287
5288 profile=GetImageProfile(image,"iptc");
5289 if (profile != (const StringInfo *) NULL)
5290 s=newSVpv((const char *) GetStringInfoDatum(profile),
5291 GetStringInfoLength(profile));
5292 }
5293 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5294 continue;
5295 }
5296 if (LocaleCompare(attribute,"iterations") == 0) /* same as loop */
5297 {
5298 if (image != (Image *) NULL)
5299 s=newSViv((ssize_t) image->iterations);
5300 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5301 continue;
5302 }
5303 if (LocaleCompare(attribute,"interlace") == 0)
5304 {
5305 j=info ? info->image_info->interlace : image ? image->interlace :
5306 UndefinedInterlace;
5307 s=newSViv(j);
5308 (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5309 j));
5310 SvIOK_on(s);
5311 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5312 continue;
5313 }
5314 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5315 attribute);
5316 break;
5317 }
5318 case 'L':
5319 case 'l':
5320 {
5321 if (LocaleCompare(attribute,"label") == 0)
5322 {
5323 const char
5324 *value;
5325
5326 if (image == (Image *) NULL)
5327 break;
Cristy935a4052017-03-31 17:45:37 -04005328 value=GetImageProperty(image,"Label",exception);
cristy4a3ce0a2013-08-03 20:06:59 +00005329 if (value != (const char *) NULL)
5330 s=newSVpv(value,0);
5331 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5332 continue;
5333 }
5334 if (LocaleCompare(attribute,"loop") == 0) /* same as iterations */
5335 {
5336 if (image != (Image *) NULL)
5337 s=newSViv((ssize_t) image->iterations);
5338 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5339 continue;
5340 }
5341 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5342 attribute);
5343 break;
5344 }
5345 case 'M':
5346 case 'm':
5347 {
5348 if (LocaleCompare(attribute,"magick") == 0)
5349 {
5350 if (info && *info->image_info->magick)
5351 s=newSVpv(info->image_info->magick,0);
5352 if (image != (Image *) NULL)
5353 s=newSVpv(image->magick,0);
5354 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5355 continue;
5356 }
5357 if (LocaleCompare(attribute,"map") == 0)
5358 {
5359 s=newSViv(GetMagickResource(MapResource));
5360 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5361 continue;
5362 }
5363 if (LocaleCompare(attribute,"maximum-error") == 0)
5364 {
5365 if (image != (Image *) NULL)
5366 s=newSVnv(image->error.normalized_maximum_error);
5367 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5368 continue;
5369 }
5370 if (LocaleCompare(attribute,"memory") == 0)
5371 {
5372 s=newSViv(GetMagickResource(MemoryResource));
5373 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5374 continue;
5375 }
5376 if (LocaleCompare(attribute,"mean-error") == 0)
5377 {
5378 if (image != (Image *) NULL)
5379 s=newSVnv(image->error.normalized_mean_error);
5380 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5381 continue;
5382 }
5383 if (LocaleCompare(attribute,"mime") == 0)
5384 {
5385 if (info && *info->image_info->magick)
5386 s=newSVpv(MagickToMime(info->image_info->magick),0);
5387 if (image != (Image *) NULL)
5388 s=newSVpv(MagickToMime(image->magick),0);
5389 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5390 continue;
5391 }
5392 if (LocaleCompare(attribute,"mattecolor") == 0)
5393 {
5394 if (image == (Image *) NULL)
5395 break;
cristy151b66d2015-04-15 10:50:31 +00005396 (void) FormatLocaleString(color,MagickPathExtent,
Cristy8645e042016-02-03 16:35:29 -05005397 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5398 (double) image->alpha_color.green,
5399 (double) image->alpha_color.blue,
5400 (double) image->alpha_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00005401 s=newSVpv(color,0);
5402 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5403 continue;
5404 }
5405 if (LocaleCompare(attribute,"matte") == 0)
5406 {
5407 if (image != (Image *) NULL)
cristy17f11b02014-12-20 19:37:04 +00005408 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
cristy4a3ce0a2013-08-03 20:06:59 +00005409 1 : 0);
5410 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5411 continue;
5412 }
5413 if (LocaleCompare(attribute,"mime") == 0)
5414 {
5415 const char
5416 *magick;
5417
5418 magick=NULL;
5419 if (info && *info->image_info->magick)
5420 magick=info->image_info->magick;
5421 if (image != (Image *) NULL)
5422 magick=image->magick;
5423 if (magick)
5424 {
5425 char
5426 *mime;
5427
5428 mime=MagickToMime(magick);
5429 s=newSVpv(mime,0);
5430 mime=(char *) RelinquishMagickMemory(mime);
5431 }
5432 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5433 continue;
5434 }
5435 if (LocaleCompare(attribute,"monochrome") == 0)
5436 {
5437 if (image == (Image *) NULL)
5438 continue;
5439 j=info ? info->image_info->monochrome :
cristy932cb072015-04-13 20:06:25 +00005440 SetImageMonochrome(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00005441 s=newSViv(j);
5442 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5443 continue;
5444 }
5445 if (LocaleCompare(attribute,"montage") == 0)
5446 {
5447 if (image && image->montage)
5448 s=newSVpv(image->montage,0);
5449 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5450 continue;
5451 }
5452 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5453 attribute);
5454 break;
5455 }
5456 case 'O':
5457 case 'o':
5458 {
5459 if (LocaleCompare(attribute,"orientation") == 0)
5460 {
5461 j=info ? info->image_info->orientation : image ?
5462 image->orientation : UndefinedOrientation;
5463 s=newSViv(j);
5464 (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5465 j));
5466 SvIOK_on(s);
5467 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5468 continue;
5469 }
5470 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5471 attribute);
5472 break;
5473 }
5474 case 'P':
5475 case 'p':
5476 {
5477 if (LocaleCompare(attribute,"page") == 0)
5478 {
5479 if (info && info->image_info->page)
5480 s=newSVpv(info->image_info->page,0);
5481 if (image != (Image *) NULL)
5482 {
5483 char
cristy151b66d2015-04-15 10:50:31 +00005484 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005485
cristy151b66d2015-04-15 10:50:31 +00005486 (void) FormatLocaleString(geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00005487 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5488 (double) image->page.height,(double) image->page.x,(double)
5489 image->page.y);
5490 s=newSVpv(geometry,0);
5491 }
5492 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5493 continue;
5494 }
5495 if (LocaleCompare(attribute,"page.x") == 0)
5496 {
5497 if (image != (Image *) NULL)
5498 s=newSViv((ssize_t) image->page.x);
5499 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5500 continue;
5501 }
5502 if (LocaleCompare(attribute,"page.y") == 0)
5503 {
5504 if (image != (Image *) NULL)
5505 s=newSViv((ssize_t) image->page.y);
5506 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5507 continue;
5508 }
5509 if (LocaleNCompare(attribute,"pixel",5) == 0)
5510 {
5511 char
cristy151b66d2015-04-15 10:50:31 +00005512 tuple[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005513
5514 int
5515 items;
5516
5517 long
5518 x,
5519 y;
5520
5521 register const Quantum
5522 *p;
5523
5524 if (image == (Image *) NULL)
5525 break;
5526 x=0;
5527 y=0;
5528 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5529 (void) items;
5530 p=GetVirtualPixels(image,x,y,1,1,exception);
5531 if (image->colorspace != CMYKColorspace)
cristy151b66d2015-04-15 10:50:31 +00005532 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
cristy4a3ce0a2013-08-03 20:06:59 +00005533 QuantumFormat "," QuantumFormat "," QuantumFormat,
5534 GetPixelRed(image,p),GetPixelGreen(image,p),
5535 GetPixelBlue(image,p),GetPixelAlpha(image,p));
5536 else
cristy151b66d2015-04-15 10:50:31 +00005537 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
cristy4a3ce0a2013-08-03 20:06:59 +00005538 QuantumFormat "," QuantumFormat "," QuantumFormat ","
5539 QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5540 GetPixelBlue(image,p),GetPixelBlack(image,p),
5541 GetPixelAlpha(image,p));
5542 s=newSVpv(tuple,0);
5543 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5544 continue;
5545 }
5546 if (LocaleCompare(attribute,"pointsize") == 0)
5547 {
5548 if (info)
5549 s=newSViv((ssize_t) info->image_info->pointsize);
5550 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5551 continue;
5552 }
cristy4a3ce0a2013-08-03 20:06:59 +00005553 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5554 attribute);
5555 break;
5556 }
5557 case 'Q':
5558 case 'q':
5559 {
5560 if (LocaleCompare(attribute,"quality") == 0)
5561 {
5562 if (info)
5563 s=newSViv((ssize_t) info->image_info->quality);
5564 if (image != (Image *) NULL)
5565 s=newSViv((ssize_t) image->quality);
5566 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5567 continue;
5568 }
5569 if (LocaleCompare(attribute,"quantum") == 0)
5570 {
5571 if (info)
5572 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5573 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5574 continue;
5575 }
5576 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5577 attribute);
5578 break;
5579 }
5580 case 'R':
5581 case 'r':
5582 {
5583 if (LocaleCompare(attribute,"rendering-intent") == 0)
5584 {
5585 s=newSViv(image->rendering_intent);
5586 (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5587 image->rendering_intent));
5588 SvIOK_on(s);
5589 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5590 continue;
5591 }
5592 if (LocaleCompare(attribute,"red-primary") == 0)
5593 {
5594 if (image == (Image *) NULL)
5595 break;
Cristyb1710fe2017-02-11 13:51:48 -05005596 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005597 image->chromaticity.red_primary.x,
5598 image->chromaticity.red_primary.y);
5599 s=newSVpv(color,0);
5600 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5601 continue;
5602 }
5603 if (LocaleCompare(attribute,"rows") == 0)
5604 {
5605 if (image != (Image *) NULL)
5606 s=newSViv((ssize_t) image->rows);
5607 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5608 continue;
5609 }
5610 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5611 attribute);
5612 break;
5613 }
5614 case 'S':
5615 case 's':
5616 {
5617 if (LocaleCompare(attribute,"sampling-factor") == 0)
5618 {
5619 if (info && info->image_info->sampling_factor)
5620 s=newSVpv(info->image_info->sampling_factor,0);
5621 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5622 continue;
5623 }
5624 if (LocaleCompare(attribute,"server") == 0) /* same as display */
5625 {
5626 if (info && info->image_info->server_name)
5627 s=newSVpv(info->image_info->server_name,0);
5628 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5629 continue;
5630 }
5631 if (LocaleCompare(attribute,"size") == 0)
5632 {
5633 if (info && info->image_info->size)
5634 s=newSVpv(info->image_info->size,0);
5635 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5636 continue;
5637 }
5638 if (LocaleCompare(attribute,"scene") == 0)
5639 {
5640 if (image != (Image *) NULL)
5641 s=newSViv((ssize_t) image->scene);
5642 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5643 continue;
5644 }
5645 if (LocaleCompare(attribute,"scenes") == 0)
5646 {
5647 if (image != (Image *) NULL)
5648 s=newSViv((ssize_t) info->image_info->number_scenes);
5649 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5650 continue;
5651 }
5652 if (LocaleCompare(attribute,"signature") == 0)
5653 {
5654 const char
5655 *value;
5656
5657 if (image == (Image *) NULL)
5658 break;
5659 (void) SignatureImage(image,exception);
5660 value=GetImageProperty(image,"Signature",exception);
5661 if (value != (const char *) NULL)
5662 s=newSVpv(value,0);
5663 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5664 continue;
5665 }
5666 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5667 attribute);
5668 break;
5669 }
5670 case 'T':
5671 case 't':
5672 {
5673 if (LocaleCompare(attribute,"taint") == 0)
5674 {
5675 if (image != (Image *) NULL)
5676 s=newSViv((ssize_t) IsTaintImage(image));
5677 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5678 continue;
5679 }
5680 if (LocaleCompare(attribute,"texture") == 0)
5681 {
5682 if (info && info->image_info->texture)
5683 s=newSVpv(info->image_info->texture,0);
5684 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5685 continue;
5686 }
5687 if (LocaleCompare(attribute,"total-ink-density") == 0)
5688 {
5689 s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5690 if (image != (Image *) NULL)
5691 s=newSVnv(GetImageTotalInkDensity(image,exception));
5692 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5693 continue;
5694 }
5695 if (LocaleCompare(attribute,"transparent-color") == 0)
5696 {
5697 if (image == (Image *) NULL)
5698 break;
cristy151b66d2015-04-15 10:50:31 +00005699 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00005700 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5701 (double) image->transparent_color.green,
5702 (double) image->transparent_color.blue,
5703 (double) image->transparent_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00005704 s=newSVpv(color,0);
5705 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5706 continue;
5707 }
5708 if (LocaleCompare(attribute,"type") == 0)
5709 {
5710 if (image == (Image *) NULL)
5711 break;
cristya26f54c2015-07-29 12:26:12 +00005712 j=(ssize_t) GetImageType(image);
cristy4a3ce0a2013-08-03 20:06:59 +00005713 s=newSViv(j);
5714 (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5715 SvIOK_on(s);
5716 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5717 continue;
5718 }
5719 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5720 attribute);
5721 break;
5722 }
5723 case 'U':
5724 case 'u':
5725 {
5726 if (LocaleCompare(attribute,"units") == 0)
5727 {
5728 j=info ? info->image_info->units : image ? image->units :
5729 UndefinedResolution;
5730 if (info && (info->image_info->units == UndefinedResolution))
5731 if (image)
5732 j=image->units;
5733 if (j == UndefinedResolution)
5734 s=newSVpv("undefined units",0);
5735 else
5736 if (j == PixelsPerInchResolution)
5737 s=newSVpv("pixels / inch",0);
5738 else
5739 s=newSVpv("pixels / centimeter",0);
5740 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5741 continue;
5742 }
5743 if (LocaleCompare(attribute,"user-time") == 0)
5744 {
5745 if (image != (Image *) NULL)
5746 s=newSVnv(GetUserTime(&image->timer));
5747 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5748 continue;
5749 }
5750 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5751 attribute);
5752 break;
5753 }
5754 case 'V':
5755 case 'v':
5756 {
5757 if (LocaleCompare(attribute,"verbose") == 0)
5758 {
5759 if (info)
5760 s=newSViv((ssize_t) info->image_info->verbose);
5761 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5762 continue;
5763 }
5764 if (LocaleCompare(attribute,"version") == 0)
5765 {
5766 s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5767 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5768 continue;
5769 }
cristy4a3ce0a2013-08-03 20:06:59 +00005770 if (LocaleCompare(attribute,"virtual-pixel") == 0)
5771 {
5772 if (image == (Image *) NULL)
5773 break;
5774 j=(ssize_t) GetImageVirtualPixelMethod(image);
5775 s=newSViv(j);
5776 (void) sv_setpv(s,CommandOptionToMnemonic(
5777 MagickVirtualPixelOptions,j));
5778 SvIOK_on(s);
5779 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5780 continue;
5781 }
5782 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5783 attribute);
5784 break;
5785 }
5786 case 'W':
5787 case 'w':
5788 {
5789 if (LocaleCompare(attribute,"white-point") == 0)
5790 {
5791 if (image == (Image *) NULL)
5792 break;
Cristyb1710fe2017-02-11 13:51:48 -05005793 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005794 image->chromaticity.white_point.x,
5795 image->chromaticity.white_point.y);
5796 s=newSVpv(color,0);
5797 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5798 continue;
5799 }
5800 if (LocaleCompare(attribute,"width") == 0)
5801 {
5802 if (image != (Image *) NULL)
5803 s=newSViv((ssize_t) image->columns);
5804 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5805 continue;
5806 }
5807 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5808 attribute);
5809 break;
5810 }
5811 case 'X':
5812 case 'x':
5813 {
Cristyc1f9f9f2016-01-05 08:19:28 -05005814 if (LocaleCompare(attribute,"xmp") == 0)
5815 {
5816 if (image != (Image *) NULL)
5817 {
5818 const StringInfo
5819 *profile;
5820
5821 profile=GetImageProfile(image,"xmp");
5822 if (profile != (StringInfo *) NULL)
5823 s=newSVpv((const char *) GetStringInfoDatum(profile),
5824 GetStringInfoLength(profile));
5825 }
5826 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5827 continue;
5828 }
cristy4a3ce0a2013-08-03 20:06:59 +00005829 if (LocaleCompare(attribute,"x-resolution") == 0)
5830 {
5831 if (image != (Image *) NULL)
5832 s=newSVnv(image->resolution.x);
5833 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5834 continue;
5835 }
5836 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5837 attribute);
5838 break;
5839 }
5840 case 'Y':
5841 case 'y':
5842 {
5843 if (LocaleCompare(attribute,"y-resolution") == 0)
5844 {
5845 if (image != (Image *) NULL)
5846 s=newSVnv(image->resolution.y);
5847 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5848 continue;
5849 }
5850 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5851 attribute);
5852 break;
5853 }
5854 default:
5855 break;
5856 }
5857 if (image == (Image *) NULL)
5858 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5859 attribute)
5860 else
5861 {
5862 value=GetImageProperty(image,attribute,exception);
5863 if (value != (const char *) NULL)
5864 {
5865 s=newSVpv(value,0);
5866 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5867 }
5868 else
5869 if (*attribute != '%')
5870 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5871 attribute)
5872 else
5873 {
5874 char
5875 *meta;
5876
5877 meta=InterpretImageProperties(info ? info->image_info :
5878 (ImageInfo *) NULL,image,attribute,exception);
5879 s=newSVpv(meta,0);
5880 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5881 meta=(char *) RelinquishMagickMemory(meta);
5882 }
5883 }
5884 }
5885 exception=DestroyExceptionInfo(exception);
5886 SvREFCNT_dec(perl_exception); /* can't return warning messages */
5887 }
5888
5889#
5890###############################################################################
5891# #
5892# #
5893# #
5894# G e t A u t h e n t i c P i x e l s #
5895# #
5896# #
5897# #
5898###############################################################################
5899#
5900#
5901void *
5902GetAuthenticPixels(ref,...)
5903 Image::Magick ref = NO_INIT
5904 ALIAS:
5905 getauthenticpixels = 1
5906 GetImagePixels = 2
5907 getimagepixels = 3
5908 CODE:
5909 {
5910 char
5911 *attribute;
5912
5913 ExceptionInfo
5914 *exception;
5915
5916 Image
5917 *image;
5918
5919 RectangleInfo
5920 region;
5921
5922 ssize_t
5923 i;
5924
5925 struct PackageInfo
5926 *info;
5927
5928 SV
5929 *perl_exception,
5930 *reference;
5931
5932 void
5933 *blob = NULL;
5934
5935 PERL_UNUSED_VAR(ref);
5936 PERL_UNUSED_VAR(ix);
5937 exception=AcquireExceptionInfo();
5938 perl_exception=newSVpv("",0);
5939 if (sv_isobject(ST(0)) == 0)
5940 {
5941 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5942 PackageName);
5943 goto PerlException;
5944 }
5945 reference=SvRV(ST(0));
5946
5947 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5948 if (image == (Image *) NULL)
5949 {
5950 ThrowPerlException(exception,OptionError,"NoImagesDefined",
5951 PackageName);
5952 goto PerlException;
5953 }
5954
5955 region.x=0;
5956 region.y=0;
5957 region.width=image->columns;
5958 region.height=1;
5959 if (items == 1)
5960 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5961 for (i=2; i < items; i+=2)
5962 {
5963 attribute=(char *) SvPV(ST(i-1),na);
5964 switch (*attribute)
5965 {
5966 case 'g':
5967 case 'G':
5968 {
5969 if (LocaleCompare(attribute,"geometry") == 0)
5970 {
5971 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5972 break;
5973 }
5974 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5975 attribute);
5976 break;
5977 }
5978 case 'H':
5979 case 'h':
5980 {
5981 if (LocaleCompare(attribute,"height") == 0)
5982 {
5983 region.height=SvIV(ST(i));
5984 continue;
5985 }
5986 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5987 attribute);
5988 break;
5989 }
5990 case 'X':
5991 case 'x':
5992 {
5993 if (LocaleCompare(attribute,"x") == 0)
5994 {
5995 region.x=SvIV(ST(i));
5996 continue;
5997 }
5998 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5999 attribute);
6000 break;
6001 }
6002 case 'Y':
6003 case 'y':
6004 {
6005 if (LocaleCompare(attribute,"y") == 0)
6006 {
6007 region.y=SvIV(ST(i));
6008 continue;
6009 }
6010 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6011 attribute);
6012 break;
6013 }
6014 case 'W':
6015 case 'w':
6016 {
6017 if (LocaleCompare(attribute,"width") == 0)
6018 {
6019 region.width=SvIV(ST(i));
6020 continue;
6021 }
6022 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6023 attribute);
6024 break;
6025 }
6026 }
6027 }
6028 blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
6029 region.height,exception);
6030 if (blob != (void *) NULL)
6031 goto PerlEnd;
6032
6033 PerlException:
6034 InheritPerlException(exception,perl_exception);
6035 exception=DestroyExceptionInfo(exception);
6036 SvREFCNT_dec(perl_exception); /* throw away all errors */
6037
6038 PerlEnd:
6039 RETVAL = blob;
6040 }
6041 OUTPUT:
6042 RETVAL
6043
6044#
6045###############################################################################
6046# #
6047# #
6048# #
6049# G e t V i r t u a l P i x e l s #
6050# #
6051# #
6052# #
6053###############################################################################
6054#
6055#
6056void *
6057GetVirtualPixels(ref,...)
6058 Image::Magick ref = NO_INIT
6059 ALIAS:
6060 getvirtualpixels = 1
6061 AcquireImagePixels = 2
6062 acquireimagepixels = 3
6063 CODE:
6064 {
6065 char
6066 *attribute;
6067
6068 const void
6069 *blob = NULL;
6070
6071 ExceptionInfo
6072 *exception;
6073
6074 Image
6075 *image;
6076
6077 RectangleInfo
6078 region;
6079
6080 ssize_t
6081 i;
6082
6083 struct PackageInfo
6084 *info;
6085
6086 SV
6087 *perl_exception,
6088 *reference;
6089
6090 PERL_UNUSED_VAR(ref);
6091 PERL_UNUSED_VAR(ix);
6092 exception=AcquireExceptionInfo();
6093 perl_exception=newSVpv("",0);
6094 if (sv_isobject(ST(0)) == 0)
6095 {
6096 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6097 PackageName);
6098 goto PerlException;
6099 }
6100 reference=SvRV(ST(0));
6101
6102 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6103 if (image == (Image *) NULL)
6104 {
6105 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6106 PackageName);
6107 goto PerlException;
6108 }
6109
6110 region.x=0;
6111 region.y=0;
6112 region.width=image->columns;
6113 region.height=1;
6114 if (items == 1)
6115 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6116 for (i=2; i < items; i+=2)
6117 {
6118 attribute=(char *) SvPV(ST(i-1),na);
6119 switch (*attribute)
6120 {
6121 case 'g':
6122 case 'G':
6123 {
6124 if (LocaleCompare(attribute,"geometry") == 0)
6125 {
6126 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6127 break;
6128 }
6129 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6130 attribute);
6131 break;
6132 }
6133 case 'H':
6134 case 'h':
6135 {
6136 if (LocaleCompare(attribute,"height") == 0)
6137 {
6138 region.height=SvIV(ST(i));
6139 continue;
6140 }
6141 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6142 attribute);
6143 break;
6144 }
6145 case 'X':
6146 case 'x':
6147 {
6148 if (LocaleCompare(attribute,"x") == 0)
6149 {
6150 region.x=SvIV(ST(i));
6151 continue;
6152 }
6153 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6154 attribute);
6155 break;
6156 }
6157 case 'Y':
6158 case 'y':
6159 {
6160 if (LocaleCompare(attribute,"y") == 0)
6161 {
6162 region.y=SvIV(ST(i));
6163 continue;
6164 }
6165 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6166 attribute);
6167 break;
6168 }
6169 case 'W':
6170 case 'w':
6171 {
6172 if (LocaleCompare(attribute,"width") == 0)
6173 {
6174 region.width=SvIV(ST(i));
6175 continue;
6176 }
6177 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6178 attribute);
6179 break;
6180 }
6181 }
6182 }
6183 blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6184 region.height,exception);
6185 if (blob != (void *) NULL)
6186 goto PerlEnd;
6187
6188 PerlException:
6189 InheritPerlException(exception,perl_exception);
6190 exception=DestroyExceptionInfo(exception);
6191 SvREFCNT_dec(perl_exception); /* throw away all errors */
6192
6193 PerlEnd:
6194 RETVAL = (void *) blob;
6195 }
6196 OUTPUT:
6197 RETVAL
6198
6199#
6200###############################################################################
6201# #
6202# #
6203# #
6204# G e t A u t h e n t i c M e t a c o n t e n t #
6205# #
6206# #
6207# #
6208###############################################################################
6209#
6210#
6211void *
6212GetAuthenticMetacontent(ref,...)
6213 Image::Magick ref = NO_INIT
6214 ALIAS:
6215 getauthenticmetacontent = 1
6216 GetMetacontent = 2
6217 getmetacontent = 3
6218 CODE:
6219 {
6220 ExceptionInfo
6221 *exception;
6222
6223 Image
6224 *image;
6225
6226 struct PackageInfo
6227 *info;
6228
6229 SV
6230 *perl_exception,
6231 *reference;
6232
6233 void
6234 *blob = NULL;
6235
6236 PERL_UNUSED_VAR(ref);
6237 PERL_UNUSED_VAR(ix);
6238 exception=AcquireExceptionInfo();
6239 perl_exception=newSVpv("",0);
6240 if (sv_isobject(ST(0)) == 0)
6241 {
6242 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6243 PackageName);
6244 goto PerlException;
6245 }
6246 reference=SvRV(ST(0));
6247
6248 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6249 if (image == (Image *) NULL)
6250 {
6251 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6252 PackageName);
6253 goto PerlException;
6254 }
6255
6256 blob=(void *) GetAuthenticMetacontent(image);
6257 if (blob != (void *) NULL)
6258 goto PerlEnd;
6259
6260 PerlException:
6261 InheritPerlException(exception,perl_exception);
6262 exception=DestroyExceptionInfo(exception);
6263 SvREFCNT_dec(perl_exception); /* throw away all errors */
6264
6265 PerlEnd:
6266 RETVAL = blob;
6267 }
6268 OUTPUT:
6269 RETVAL
6270
6271#
6272###############################################################################
6273# #
6274# #
6275# #
6276# G e t V i r t u a l M e t a c o n t e n t #
6277# #
6278# #
6279# #
6280###############################################################################
6281#
6282#
6283void *
6284GetVirtualMetacontent(ref,...)
6285 Image::Magick ref = NO_INIT
6286 ALIAS:
6287 getvirtualmetacontent = 1
6288 CODE:
6289 {
6290 ExceptionInfo
6291 *exception;
6292
6293 Image
6294 *image;
6295
6296 struct PackageInfo
6297 *info;
6298
6299 SV
6300 *perl_exception,
6301 *reference;
6302
6303 void
6304 *blob = NULL;
6305
6306 PERL_UNUSED_VAR(ref);
6307 PERL_UNUSED_VAR(ix);
6308 exception=AcquireExceptionInfo();
6309 perl_exception=newSVpv("",0);
6310 if (sv_isobject(ST(0)) == 0)
6311 {
6312 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6313 PackageName);
6314 goto PerlException;
6315 }
6316 reference=SvRV(ST(0));
6317
6318 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6319 if (image == (Image *) NULL)
6320 {
6321 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6322 PackageName);
6323 goto PerlException;
6324 }
6325
6326 blob=(void *) GetVirtualMetacontent(image);
6327 if (blob != (void *) NULL)
6328 goto PerlEnd;
6329
6330 PerlException:
6331 InheritPerlException(exception,perl_exception);
6332 exception=DestroyExceptionInfo(exception);
6333 SvREFCNT_dec(perl_exception); /* throw away all errors */
6334
6335 PerlEnd:
6336 RETVAL = blob;
6337 }
6338 OUTPUT:
6339 RETVAL
6340
6341#
6342###############################################################################
6343# #
6344# #
6345# #
6346# H i s t o g r a m #
6347# #
6348# #
6349# #
6350###############################################################################
6351#
6352#
6353void
6354Histogram(ref,...)
6355 Image::Magick ref=NO_INIT
6356 ALIAS:
6357 HistogramImage = 1
6358 histogram = 2
6359 histogramimage = 3
6360 PPCODE:
6361 {
6362 AV
6363 *av;
6364
6365 char
cristy151b66d2015-04-15 10:50:31 +00006366 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00006367
6368 PixelInfo
6369 *histogram;
6370
6371 ExceptionInfo
6372 *exception;
6373
6374 Image
6375 *image;
6376
6377 register ssize_t
6378 i;
6379
6380 ssize_t
6381 count;
6382
6383 struct PackageInfo
6384 *info;
6385
6386 SV
6387 *perl_exception,
6388 *reference;
6389
6390 size_t
6391 number_colors;
6392
6393 PERL_UNUSED_VAR(ref);
6394 PERL_UNUSED_VAR(ix);
6395 exception=AcquireExceptionInfo();
6396 perl_exception=newSVpv("",0);
6397 av=NULL;
6398 if (sv_isobject(ST(0)) == 0)
6399 {
6400 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6401 PackageName);
6402 goto PerlException;
6403 }
6404 reference=SvRV(ST(0));
6405 av=newAV();
6406 SvREFCNT_dec(av);
6407 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6408 if (image == (Image *) NULL)
6409 {
6410 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6411 PackageName);
6412 goto PerlException;
6413 }
cristy4a3ce0a2013-08-03 20:06:59 +00006414 count=0;
6415 for ( ; image; image=image->next)
6416 {
6417 histogram=GetImageHistogram(image,&number_colors,exception);
6418 if (histogram == (PixelInfo *) NULL)
6419 continue;
6420 count+=(ssize_t) number_colors;
6421 EXTEND(sp,6*count);
6422 for (i=0; i < (ssize_t) number_colors; i++)
6423 {
cristy151b66d2015-04-15 10:50:31 +00006424 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006425 histogram[i].red);
6426 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006427 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006428 histogram[i].green);
6429 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006430 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006431 histogram[i].blue);
6432 PUSHs(sv_2mortal(newSVpv(message,0)));
6433 if (image->colorspace == CMYKColorspace)
6434 {
cristy151b66d2015-04-15 10:50:31 +00006435 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006436 histogram[i].black);
6437 PUSHs(sv_2mortal(newSVpv(message,0)));
6438 }
cristy151b66d2015-04-15 10:50:31 +00006439 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006440 histogram[i].alpha);
6441 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006442 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
cristy4a3ce0a2013-08-03 20:06:59 +00006443 histogram[i].count);
6444 PUSHs(sv_2mortal(newSVpv(message,0)));
6445 }
6446 histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6447 }
6448
6449 PerlException:
6450 InheritPerlException(exception,perl_exception);
6451 exception=DestroyExceptionInfo(exception);
6452 SvREFCNT_dec(perl_exception);
6453 }
6454
6455#
6456###############################################################################
6457# #
6458# #
6459# #
6460# G e t P i x e l #
6461# #
6462# #
6463# #
6464###############################################################################
6465#
6466#
6467void
6468GetPixel(ref,...)
6469 Image::Magick ref=NO_INIT
6470 ALIAS:
6471 getpixel = 1
6472 getPixel = 2
6473 PPCODE:
6474 {
6475 AV
6476 *av;
6477
6478 char
6479 *attribute;
6480
6481 ExceptionInfo
6482 *exception;
6483
6484 Image
6485 *image;
6486
6487 MagickBooleanType
6488 normalize;
6489
6490 RectangleInfo
6491 region;
6492
6493 register const Quantum
6494 *p;
6495
6496 register ssize_t
6497 i;
6498
6499 ssize_t
6500 option;
6501
6502 struct PackageInfo
6503 *info;
6504
6505 SV
6506 *perl_exception,
6507 *reference; /* reference is the SV* of ref=SvIV(reference) */
6508
6509 PERL_UNUSED_VAR(ref);
6510 PERL_UNUSED_VAR(ix);
6511 exception=AcquireExceptionInfo();
6512 perl_exception=newSVpv("",0);
6513 reference=SvRV(ST(0));
6514 av=(AV *) reference;
6515 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6516 exception);
6517 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6518 if (image == (Image *) NULL)
6519 {
6520 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6521 PackageName);
6522 goto PerlException;
6523 }
6524 normalize=MagickTrue;
6525 region.x=0;
6526 region.y=0;
6527 region.width=image->columns;
6528 region.height=1;
6529 if (items == 1)
6530 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6531 for (i=2; i < items; i+=2)
6532 {
6533 attribute=(char *) SvPV(ST(i-1),na);
6534 switch (*attribute)
6535 {
6536 case 'C':
6537 case 'c':
6538 {
6539 if (LocaleCompare(attribute,"channel") == 0)
6540 {
6541 ssize_t
6542 option;
6543
6544 option=ParseChannelOption(SvPV(ST(i),na));
6545 if (option < 0)
6546 {
6547 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6548 SvPV(ST(i),na));
6549 return;
6550 }
cristybcd59342015-06-07 14:07:19 +00006551 (void) SetPixelChannelMask(image,(ChannelType) option);
cristy4a3ce0a2013-08-03 20:06:59 +00006552 break;
6553 }
6554 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6555 attribute);
6556 break;
6557 }
6558 case 'g':
6559 case 'G':
6560 {
6561 if (LocaleCompare(attribute,"geometry") == 0)
6562 {
6563 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6564 break;
6565 }
6566 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6567 attribute);
6568 break;
6569 }
6570 case 'N':
6571 case 'n':
6572 {
6573 if (LocaleCompare(attribute,"normalize") == 0)
6574 {
6575 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6576 SvPV(ST(i),na));
6577 if (option < 0)
6578 {
6579 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6580 SvPV(ST(i),na));
6581 break;
6582 }
6583 normalize=option != 0 ? MagickTrue : MagickFalse;
6584 break;
6585 }
6586 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6587 attribute);
6588 break;
6589 }
6590 case 'x':
6591 case 'X':
6592 {
6593 if (LocaleCompare(attribute,"x") == 0)
6594 {
6595 region.x=SvIV(ST(i));
6596 break;
6597 }
6598 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6599 attribute);
6600 break;
6601 }
6602 case 'y':
6603 case 'Y':
6604 {
6605 if (LocaleCompare(attribute,"y") == 0)
6606 {
6607 region.y=SvIV(ST(i));
6608 break;
6609 }
6610 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6611 attribute);
6612 break;
6613 }
6614 default:
6615 {
6616 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6617 attribute);
6618 break;
6619 }
6620 }
6621 }
6622 p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6623 if (p == (const Quantum *) NULL)
6624 PUSHs(&sv_undef);
6625 else
6626 {
6627 double
6628 scale;
6629
6630 scale=1.0;
6631 if (normalize != MagickFalse)
6632 scale=1.0/QuantumRange;
6633 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6634 PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6635 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6636 PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6637 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6638 PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6639 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6640 (image->colorspace == CMYKColorspace))
6641 PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6642 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6643 PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6644 }
6645
6646 PerlException:
6647 InheritPerlException(exception,perl_exception);
6648 exception=DestroyExceptionInfo(exception);
6649 SvREFCNT_dec(perl_exception);
6650 }
6651
6652#
6653###############################################################################
6654# #
6655# #
6656# #
6657# G e t P i x e l s #
6658# #
6659# #
6660# #
6661###############################################################################
6662#
6663#
6664void
6665GetPixels(ref,...)
6666 Image::Magick ref=NO_INIT
6667 ALIAS:
6668 getpixels = 1
6669 getPixels = 2
6670 PPCODE:
6671 {
6672 AV
6673 *av;
6674
6675 char
6676 *attribute;
6677
6678 const char
6679 *map;
6680
6681 ExceptionInfo
6682 *exception;
6683
6684 Image
6685 *image;
6686
6687 MagickBooleanType
6688 normalize,
6689 status;
6690
6691 RectangleInfo
6692 region;
6693
6694 register ssize_t
6695 i;
6696
6697 ssize_t
6698 option;
6699
6700 struct PackageInfo
6701 *info;
6702
6703 SV
6704 *perl_exception,
6705 *reference; /* reference is the SV* of ref=SvIV(reference) */
6706
6707 PERL_UNUSED_VAR(ref);
6708 PERL_UNUSED_VAR(ix);
6709 exception=AcquireExceptionInfo();
6710 perl_exception=newSVpv("",0);
6711 reference=SvRV(ST(0));
6712 av=(AV *) reference;
6713 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6714 exception);
6715 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6716 if (image == (Image *) NULL)
6717 {
6718 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6719 PackageName);
6720 goto PerlException;
6721 }
6722 map="RGB";
cristy17f11b02014-12-20 19:37:04 +00006723 if (image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00006724 map="RGBA";
6725 if (image->colorspace == CMYKColorspace)
6726 {
6727 map="CMYK";
cristy17f11b02014-12-20 19:37:04 +00006728 if (image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00006729 map="CMYKA";
6730 }
6731 normalize=MagickFalse;
6732 region.x=0;
6733 region.y=0;
6734 region.width=image->columns;
6735 region.height=1;
6736 if (items == 1)
6737 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6738 for (i=2; i < items; i+=2)
6739 {
6740 attribute=(char *) SvPV(ST(i-1),na);
6741 switch (*attribute)
6742 {
6743 case 'g':
6744 case 'G':
6745 {
6746 if (LocaleCompare(attribute,"geometry") == 0)
6747 {
6748 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6749 break;
6750 }
6751 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6752 attribute);
6753 break;
6754 }
6755 case 'H':
6756 case 'h':
6757 {
6758 if (LocaleCompare(attribute,"height") == 0)
6759 {
6760 region.height=SvIV(ST(i));
6761 break;
6762 }
6763 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6764 attribute);
6765 break;
6766 }
6767 case 'M':
6768 case 'm':
6769 {
6770 if (LocaleCompare(attribute,"map") == 0)
6771 {
6772 map=SvPV(ST(i),na);
6773 break;
6774 }
6775 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6776 attribute);
6777 break;
6778 }
6779 case 'N':
6780 case 'n':
6781 {
6782 if (LocaleCompare(attribute,"normalize") == 0)
6783 {
6784 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6785 SvPV(ST(i),na));
6786 if (option < 0)
6787 {
6788 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6789 SvPV(ST(i),na));
6790 break;
6791 }
6792 normalize=option != 0 ? MagickTrue : MagickFalse;
6793 break;
6794 }
6795 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6796 attribute);
6797 break;
6798 }
6799 case 'W':
6800 case 'w':
6801 {
6802 if (LocaleCompare(attribute,"width") == 0)
6803 {
6804 region.width=SvIV(ST(i));
6805 break;
6806 }
6807 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6808 attribute);
6809 break;
6810 }
6811 case 'x':
6812 case 'X':
6813 {
6814 if (LocaleCompare(attribute,"x") == 0)
6815 {
6816 region.x=SvIV(ST(i));
6817 break;
6818 }
6819 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6820 attribute);
6821 break;
6822 }
6823 case 'y':
6824 case 'Y':
6825 {
6826 if (LocaleCompare(attribute,"y") == 0)
6827 {
6828 region.y=SvIV(ST(i));
6829 break;
6830 }
6831 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6832 attribute);
6833 break;
6834 }
6835 default:
6836 {
6837 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6838 attribute);
6839 break;
6840 }
6841 }
6842 }
6843 if (normalize != MagickFalse)
6844 {
6845 float
6846 *pixels;
6847
6848 pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6849 region.height*sizeof(*pixels));
6850 if (pixels == (float *) NULL)
6851 {
6852 ThrowPerlException(exception,ResourceLimitError,
6853 "MemoryAllocationFailed",PackageName);
6854 goto PerlException;
6855 }
6856 status=ExportImagePixels(image,region.x,region.y,region.width,
6857 region.height,map,FloatPixel,pixels,exception);
6858 if (status == MagickFalse)
6859 PUSHs(&sv_undef);
6860 else
6861 {
6862 EXTEND(sp,strlen(map)*region.width*region.height);
6863 for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6864 PUSHs(sv_2mortal(newSVnv(pixels[i])));
6865 }
6866 pixels=(float *) RelinquishMagickMemory(pixels);
6867 }
6868 else
6869 {
6870 Quantum
6871 *pixels;
6872
6873 pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6874 region.height*sizeof(*pixels));
6875 if (pixels == (Quantum *) NULL)
6876 {
6877 ThrowPerlException(exception,ResourceLimitError,
6878 "MemoryAllocationFailed",PackageName);
6879 goto PerlException;
6880 }
6881 status=ExportImagePixels(image,region.x,region.y,region.width,
6882 region.height,map,QuantumPixel,pixels,exception);
6883 if (status == MagickFalse)
6884 PUSHs(&sv_undef);
6885 else
6886 {
6887 EXTEND(sp,strlen(map)*region.width*region.height);
6888 for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6889 PUSHs(sv_2mortal(newSViv(pixels[i])));
6890 }
6891 pixels=(Quantum *) RelinquishMagickMemory(pixels);
6892 }
6893
6894 PerlException:
6895 InheritPerlException(exception,perl_exception);
6896 exception=DestroyExceptionInfo(exception);
6897 SvREFCNT_dec(perl_exception);
6898 }
6899
6900#
6901###############################################################################
6902# #
6903# #
6904# #
6905# I m a g e T o B l o b #
6906# #
6907# #
6908# #
6909###############################################################################
6910#
6911#
6912void
6913ImageToBlob(ref,...)
6914 Image::Magick ref=NO_INIT
6915 ALIAS:
6916 ImageToBlob = 1
6917 imagetoblob = 2
6918 toblob = 3
6919 blob = 4
6920 PPCODE:
6921 {
6922 char
cristy151b66d2015-04-15 10:50:31 +00006923 filename[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00006924
6925 ExceptionInfo
6926 *exception;
6927
6928 Image
6929 *image,
6930 *next;
6931
6932 register ssize_t
6933 i;
6934
6935 struct PackageInfo
6936 *info,
6937 *package_info;
6938
6939 size_t
6940 length;
6941
6942 ssize_t
6943 scene;
6944
6945 SV
6946 *perl_exception,
6947 *reference;
6948
6949 void
6950 *blob;
6951
6952 PERL_UNUSED_VAR(ref);
6953 PERL_UNUSED_VAR(ix);
6954 exception=AcquireExceptionInfo();
6955 perl_exception=newSVpv("",0);
6956 package_info=(struct PackageInfo *) NULL;
6957 if (sv_isobject(ST(0)) == 0)
6958 {
6959 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6960 PackageName);
6961 goto PerlException;
6962 }
6963 reference=SvRV(ST(0));
6964 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6965 if (image == (Image *) NULL)
6966 {
6967 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6968 PackageName);
6969 goto PerlException;
6970 }
6971 package_info=ClonePackageInfo(info,exception);
6972 for (i=2; i < items; i+=2)
6973 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6974 (void) CopyMagickString(filename,package_info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00006975 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00006976 scene=0;
6977 for (next=image; next; next=next->next)
6978 {
cristy151b66d2015-04-15 10:50:31 +00006979 (void) CopyMagickString(next->filename,filename,MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00006980 next->scene=scene++;
6981 }
6982 SetImageInfo(package_info->image_info,(unsigned int)
6983 GetImageListLength(image),exception);
6984 EXTEND(sp,(ssize_t) GetImageListLength(image));
6985 for ( ; image; image=image->next)
6986 {
6987 length=0;
6988 blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6989 if (blob != (char *) NULL)
6990 {
6991 PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6992 blob=(unsigned char *) RelinquishMagickMemory(blob);
6993 }
6994 if (package_info->image_info->adjoin)
6995 break;
6996 }
6997
6998 PerlException:
6999 if (package_info != (struct PackageInfo *) NULL)
7000 DestroyPackageInfo(package_info);
7001 InheritPerlException(exception,perl_exception);
7002 exception=DestroyExceptionInfo(exception);
7003 SvREFCNT_dec(perl_exception); /* throw away all errors */
7004 }
7005
7006#
7007###############################################################################
7008# #
7009# #
7010# #
7011# L a y e r s #
7012# #
7013# #
7014# #
7015###############################################################################
7016#
7017#
7018void
7019Layers(ref,...)
7020 Image::Magick ref=NO_INIT
7021 ALIAS:
7022 Layers = 1
7023 layers = 2
7024 OptimizeImageLayers = 3
7025 optimizelayers = 4
7026 optimizeimagelayers = 5
7027 PPCODE:
7028 {
7029 AV
7030 *av;
7031
7032 char
7033 *attribute;
7034
7035 CompositeOperator
7036 compose;
7037
7038 ExceptionInfo
7039 *exception;
7040
7041 HV
7042 *hv;
7043
7044 Image
7045 *image,
7046 *layers;
7047
7048 LayerMethod
7049 method;
7050
7051 register ssize_t
7052 i;
7053
7054 ssize_t
7055 option,
7056 sp;
7057
7058 struct PackageInfo
7059 *info;
7060
7061 SV
7062 *av_reference,
7063 *perl_exception,
7064 *reference,
7065 *rv,
7066 *sv;
7067
7068 PERL_UNUSED_VAR(ref);
7069 PERL_UNUSED_VAR(ix);
7070 exception=AcquireExceptionInfo();
7071 perl_exception=newSVpv("",0);
7072 sv=NULL;
7073 if (sv_isobject(ST(0)) == 0)
7074 {
7075 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7076 PackageName);
7077 goto PerlException;
7078 }
7079 reference=SvRV(ST(0));
7080 hv=SvSTASH(reference);
7081 av=newAV();
7082 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7083 SvREFCNT_dec(av);
7084 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7085 if (image == (Image *) NULL)
7086 {
7087 ThrowPerlException(exception,OptionError,"NoImagesDefined",
7088 PackageName);
7089 goto PerlException;
7090 }
7091 compose=image->compose;
7092 method=OptimizeLayer;
7093 for (i=2; i < items; i+=2)
7094 {
7095 attribute=(char *) SvPV(ST(i-1),na);
7096 switch (*attribute)
7097 {
7098 case 'C':
7099 case 'c':
7100 {
7101 if (LocaleCompare(attribute,"compose") == 0)
7102 {
7103 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7104 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7105 if (sp < 0)
7106 {
7107 ThrowPerlException(exception,OptionError,"UnrecognizedType",
7108 SvPV(ST(i),na));
7109 break;
7110 }
7111 compose=(CompositeOperator) sp;
7112 break;
7113 }
7114 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7115 attribute);
7116 break;
7117 }
7118 case 'M':
7119 case 'm':
7120 {
7121 if (LocaleCompare(attribute,"method") == 0)
7122 {
7123 option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7124 SvPV(ST(i),na));
7125 if (option < 0)
7126 {
7127 ThrowPerlException(exception,OptionError,"UnrecognizedType",
7128 SvPV(ST(i),na));
7129 break;
7130 }
7131 method=(LayerMethod) option;
7132 break;
7133 }
7134 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7135 attribute);
7136 break;
7137 }
7138 default:
7139 {
7140 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7141 attribute);
7142 break;
7143 }
7144 }
7145 }
7146 layers=(Image *) NULL;
7147 switch (method)
7148 {
7149 case CompareAnyLayer:
7150 case CompareClearLayer:
7151 case CompareOverlayLayer:
7152 default:
7153 {
7154 layers=CompareImagesLayers(image,method,exception);
7155 break;
7156 }
7157 case MergeLayer:
7158 case FlattenLayer:
7159 case MosaicLayer:
7160 {
7161 layers=MergeImageLayers(image,method,exception);
7162 break;
7163 }
7164 case DisposeLayer:
7165 {
7166 layers=DisposeImages(image,exception);
7167 break;
7168 }
7169 case OptimizeImageLayer:
7170 {
7171 layers=OptimizeImageLayers(image,exception);
7172 break;
7173 }
7174 case OptimizePlusLayer:
7175 {
7176 layers=OptimizePlusImageLayers(image,exception);
7177 break;
7178 }
7179 case OptimizeTransLayer:
7180 {
7181 OptimizeImageTransparency(image,exception);
7182 break;
7183 }
7184 case RemoveDupsLayer:
7185 {
7186 RemoveDuplicateLayers(&image,exception);
7187 break;
7188 }
7189 case RemoveZeroLayer:
7190 {
7191 RemoveZeroDelayLayers(&image,exception);
7192 break;
7193 }
7194 case OptimizeLayer:
7195 {
7196 QuantizeInfo
7197 *quantize_info;
7198
7199 /*
7200 General Purpose, GIF Animation Optimizer.
7201 */
7202 layers=CoalesceImages(image,exception);
7203 if (layers == (Image *) NULL)
7204 break;
7205 image=layers;
7206 layers=OptimizeImageLayers(image,exception);
7207 if (layers == (Image *) NULL)
7208 break;
7209 image=DestroyImageList(image);
7210 image=layers;
7211 layers=(Image *) NULL;
7212 OptimizeImageTransparency(image,exception);
7213 quantize_info=AcquireQuantizeInfo(info->image_info);
7214 (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7215 quantize_info=DestroyQuantizeInfo(quantize_info);
7216 break;
7217 }
7218 case CompositeLayer:
7219 {
7220 Image
7221 *source;
7222
7223 RectangleInfo
7224 geometry;
7225
7226 /*
7227 Split image sequence at the first 'NULL:' image.
7228 */
7229 source=image;
7230 while (source != (Image *) NULL)
7231 {
7232 source=GetNextImageInList(source);
7233 if ((source != (Image *) NULL) &&
7234 (LocaleCompare(source->magick,"NULL") == 0))
7235 break;
7236 }
7237 if (source != (Image *) NULL)
7238 {
7239 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7240 (GetNextImageInList(source) == (Image *) NULL))
7241 source=(Image *) NULL;
7242 else
7243 {
7244 /*
7245 Separate the two lists, junk the null: image.
7246 */
7247 source=SplitImageList(source->previous);
7248 DeleteImageFromList(&source);
7249 }
7250 }
7251 if (source == (Image *) NULL)
7252 {
7253 (void) ThrowMagickException(exception,GetMagickModule(),
7254 OptionError,"MissingNullSeparator","layers Composite");
7255 break;
7256 }
7257 /*
7258 Adjust offset with gravity and virtual canvas.
7259 */
7260 SetGeometry(image,&geometry);
7261 (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7262 geometry.width=source->page.width != 0 ? source->page.width :
7263 source->columns;
7264 geometry.height=source->page.height != 0 ? source->page.height :
7265 source->rows;
7266 GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7267 image->columns,image->page.height != 0 ? image->page.height :
7268 image->rows,image->gravity,&geometry);
7269 CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7270 source=DestroyImageList(source);
7271 break;
7272 }
7273 }
7274 if (layers != (Image *) NULL)
7275 image=layers;
cristy83a28a02013-08-03 20:25:48 +00007276 else
7277 image=CloneImage(image,0,0,MagickTrue,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007278 if (image == (Image *) NULL)
7279 goto PerlException;
7280 for ( ; image; image=image->next)
7281 {
7282 AddImageToRegistry(sv,image);
7283 rv=newRV(sv);
7284 av_push(av,sv_bless(rv,hv));
7285 SvREFCNT_dec(sv);
7286 }
7287 exception=DestroyExceptionInfo(exception);
7288 ST(0)=av_reference;
7289 SvREFCNT_dec(perl_exception);
7290 XSRETURN(1);
7291
7292 PerlException:
7293 InheritPerlException(exception,perl_exception);
7294 exception=DestroyExceptionInfo(exception);
7295 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7296 SvPOK_on(perl_exception);
7297 ST(0)=sv_2mortal(perl_exception);
7298 XSRETURN(1);
7299 }
7300
7301#
7302###############################################################################
7303# #
7304# #
7305# #
7306# M a g i c k T o M i m e #
7307# #
7308# #
7309# #
7310###############################################################################
7311#
7312#
7313SV *
7314MagickToMime(ref,name)
7315 Image::Magick ref=NO_INIT
7316 char *name
7317 ALIAS:
7318 magicktomime = 1
7319 CODE:
7320 {
7321 char
7322 *mime;
7323
7324 PERL_UNUSED_VAR(ref);
7325 PERL_UNUSED_VAR(ix);
7326 mime=MagickToMime(name);
7327 RETVAL=newSVpv(mime,0);
7328 mime=(char *) RelinquishMagickMemory(mime);
7329 }
7330 OUTPUT:
7331 RETVAL
7332
7333#
7334###############################################################################
7335# #
7336# #
7337# #
7338# M o g r i f y #
7339# #
7340# #
7341# #
7342###############################################################################
7343#
7344#
7345void
7346Mogrify(ref,...)
7347 Image::Magick ref=NO_INIT
7348 ALIAS:
7349 Comment = 1
7350 CommentImage = 2
7351 Label = 3
7352 LabelImage = 4
7353 AddNoise = 5
7354 AddNoiseImage = 6
7355 Colorize = 7
7356 ColorizeImage = 8
7357 Border = 9
7358 BorderImage = 10
7359 Blur = 11
7360 BlurImage = 12
7361 Chop = 13
7362 ChopImage = 14
7363 Crop = 15
7364 CropImage = 16
7365 Despeckle = 17
7366 DespeckleImage = 18
7367 Edge = 19
7368 EdgeImage = 20
7369 Emboss = 21
7370 EmbossImage = 22
7371 Enhance = 23
7372 EnhanceImage = 24
7373 Flip = 25
7374 FlipImage = 26
7375 Flop = 27
7376 FlopImage = 28
7377 Frame = 29
7378 FrameImage = 30
7379 Implode = 31
7380 ImplodeImage = 32
7381 Magnify = 33
7382 MagnifyImage = 34
7383 MedianFilter = 35
7384 MedianConvolveImage = 36
7385 Minify = 37
7386 MinifyImage = 38
7387 OilPaint = 39
7388 OilPaintImage = 40
7389 ReduceNoise = 41
7390 ReduceNoiseImage = 42
7391 Roll = 43
7392 RollImage = 44
7393 Rotate = 45
7394 RotateImage = 46
7395 Sample = 47
7396 SampleImage = 48
7397 Scale = 49
7398 ScaleImage = 50
7399 Shade = 51
7400 ShadeImage = 52
7401 Sharpen = 53
7402 SharpenImage = 54
7403 Shear = 55
7404 ShearImage = 56
7405 Spread = 57
7406 SpreadImage = 58
7407 Swirl = 59
7408 SwirlImage = 60
7409 Resize = 61
7410 ResizeImage = 62
7411 Zoom = 63
7412 ZoomImage = 64
7413 Annotate = 65
7414 AnnotateImage = 66
7415 ColorFloodfill = 67
7416 ColorFloodfillImage= 68
7417 Composite = 69
7418 CompositeImage = 70
7419 Contrast = 71
7420 ContrastImage = 72
7421 CycleColormap = 73
7422 CycleColormapImage = 74
7423 Draw = 75
7424 DrawImage = 76
7425 Equalize = 77
7426 EqualizeImage = 78
7427 Gamma = 79
7428 GammaImage = 80
7429 Map = 81
7430 MapImage = 82
7431 MatteFloodfill = 83
7432 MatteFloodfillImage= 84
7433 Modulate = 85
7434 ModulateImage = 86
7435 Negate = 87
7436 NegateImage = 88
7437 Normalize = 89
7438 NormalizeImage = 90
7439 NumberColors = 91
7440 NumberColorsImage = 92
7441 Opaque = 93
7442 OpaqueImage = 94
7443 Quantize = 95
7444 QuantizeImage = 96
7445 Raise = 97
7446 RaiseImage = 98
7447 Segment = 99
7448 SegmentImage = 100
7449 Signature = 101
7450 SignatureImage = 102
7451 Solarize = 103
7452 SolarizeImage = 104
7453 Sync = 105
7454 SyncImage = 106
7455 Texture = 107
7456 TextureImage = 108
7457 Evaluate = 109
7458 EvaluateImage = 110
7459 Transparent = 111
7460 TransparentImage = 112
7461 Threshold = 113
7462 ThresholdImage = 114
7463 Charcoal = 115
7464 CharcoalImage = 116
7465 Trim = 117
7466 TrimImage = 118
7467 Wave = 119
7468 WaveImage = 120
7469 Separate = 121
7470 SeparateImage = 122
7471 Stereo = 125
7472 StereoImage = 126
7473 Stegano = 127
7474 SteganoImage = 128
7475 Deconstruct = 129
7476 DeconstructImage = 130
7477 GaussianBlur = 131
7478 GaussianBlurImage = 132
7479 Convolve = 133
7480 ConvolveImage = 134
7481 Profile = 135
7482 ProfileImage = 136
7483 UnsharpMask = 137
7484 UnsharpMaskImage = 138
7485 MotionBlur = 139
7486 MotionBlurImage = 140
7487 OrderedDither = 141
7488 OrderedDitherImage = 142
7489 Shave = 143
7490 ShaveImage = 144
7491 Level = 145
7492 LevelImage = 146
7493 Clip = 147
7494 ClipImage = 148
7495 AffineTransform = 149
7496 AffineTransformImage = 150
7497 Difference = 151
7498 DifferenceImage = 152
7499 AdaptiveThreshold = 153
7500 AdaptiveThresholdImage = 154
7501 Resample = 155
7502 ResampleImage = 156
7503 Describe = 157
7504 DescribeImage = 158
7505 BlackThreshold = 159
7506 BlackThresholdImage= 160
7507 WhiteThreshold = 161
7508 WhiteThresholdImage= 162
cristy60c73c02014-03-25 12:09:58 +00007509 RotationalBlur = 163
7510 RotationalBlurImage= 164
cristy4a3ce0a2013-08-03 20:06:59 +00007511 Thumbnail = 165
7512 ThumbnailImage = 166
7513 Strip = 167
7514 StripImage = 168
7515 Tint = 169
7516 TintImage = 170
7517 Channel = 171
7518 ChannelImage = 172
7519 Splice = 173
7520 SpliceImage = 174
7521 Posterize = 175
7522 PosterizeImage = 176
7523 Shadow = 177
7524 ShadowImage = 178
7525 Identify = 179
7526 IdentifyImage = 180
7527 SepiaTone = 181
7528 SepiaToneImage = 182
7529 SigmoidalContrast = 183
7530 SigmoidalContrastImage = 184
7531 Extent = 185
7532 ExtentImage = 186
7533 Vignette = 187
7534 VignetteImage = 188
7535 ContrastStretch = 189
7536 ContrastStretchImage = 190
7537 Sans0 = 191
7538 Sans0Image = 192
7539 Sans1 = 193
7540 Sans1Image = 194
7541 AdaptiveSharpen = 195
7542 AdaptiveSharpenImage = 196
7543 Transpose = 197
7544 TransposeImage = 198
7545 Transverse = 199
7546 TransverseImage = 200
7547 AutoOrient = 201
7548 AutoOrientImage = 202
7549 AdaptiveBlur = 203
7550 AdaptiveBlurImage = 204
7551 Sketch = 205
7552 SketchImage = 206
7553 UniqueColors = 207
7554 UniqueColorsImage = 208
7555 AdaptiveResize = 209
7556 AdaptiveResizeImage= 210
7557 ClipMask = 211
7558 ClipMaskImage = 212
7559 LinearStretch = 213
7560 LinearStretchImage = 214
7561 ColorMatrix = 215
7562 ColorMatrixImage = 216
7563 Mask = 217
7564 MaskImage = 218
7565 Polaroid = 219
7566 PolaroidImage = 220
7567 FloodfillPaint = 221
7568 FloodfillPaintImage= 222
7569 Distort = 223
7570 DistortImage = 224
7571 Clut = 225
7572 ClutImage = 226
7573 LiquidRescale = 227
7574 LiquidRescaleImage = 228
7575 Encipher = 229
7576 EncipherImage = 230
7577 Decipher = 231
7578 DecipherImage = 232
7579 Deskew = 233
7580 DeskewImage = 234
7581 Remap = 235
7582 RemapImage = 236
7583 SparseColor = 237
7584 SparseColorImage = 238
7585 Function = 239
7586 FunctionImage = 240
7587 SelectiveBlur = 241
7588 SelectiveBlurImage = 242
7589 HaldClut = 243
7590 HaldClutImage = 244
7591 BlueShift = 245
7592 BlueShiftImage = 246
7593 ForwardFourierTransform = 247
7594 ForwardFourierTransformImage = 248
7595 InverseFourierTransform = 249
7596 InverseFourierTransformImage = 250
7597 ColorDecisionList = 251
7598 ColorDecisionListImage = 252
7599 AutoGamma = 253
7600 AutoGammaImage = 254
7601 AutoLevel = 255
7602 AutoLevelImage = 256
7603 LevelColors = 257
7604 LevelImageColors = 258
7605 Clamp = 259
7606 ClampImage = 260
7607 BrightnessContrast = 261
7608 BrightnessContrastImage = 262
7609 Morphology = 263
7610 MorphologyImage = 264
Cristy3ca633e2016-02-13 12:49:01 -05007611 Mode = 265
7612 ModeImage = 266
7613 Statistic = 267
7614 StatisticImage = 268
7615 Perceptible = 269
7616 PerceptibleImage = 270
7617 Poly = 271
7618 PolyImage = 272
7619 Grayscale = 273
7620 GrayscaleImage = 274
7621 CannyEdge = 275
7622 CannyEdgeImage = 276
7623 HoughLine = 277
7624 HoughLineImage = 278
7625 MeanShift = 279
7626 MeanShiftImage = 280
7627 Kuwahara = 281
7628 KuwaharaImage = 282
Cristy0f5df812017-07-04 18:30:05 -04007629 ConnectedComponents = 283
7630 ConnectedComponentsImage = 284
Cristy3ca633e2016-02-13 12:49:01 -05007631 CopyPixels = 285
7632 CopyImagePixels = 286
Cristy5488c982016-02-13 14:07:50 -05007633 Color = 287
7634 ColorImage = 288
Cristy2d830ed2016-02-21 10:54:16 -05007635 WaveletDenoise = 289
7636 WaveletDenoiseImage= 290
Cristy99a57162016-12-05 11:47:57 -05007637 Colorspace = 291
7638 ColorspaceImage = 292
Cristy53353872017-07-02 12:24:24 -04007639 AutoThreshold = 293
7640 AutoThresholdImage = 294
Cristy532b3382018-08-05 17:56:56 -04007641 RangeThreshold = 295
7642 RangeThresholdImage= 296
cristy4a3ce0a2013-08-03 20:06:59 +00007643 MogrifyRegion = 666
7644 PPCODE:
7645 {
7646 AffineMatrix
7647 affine,
7648 current;
7649
7650 char
7651 attribute_flag[MaxArguments],
cristy151b66d2015-04-15 10:50:31 +00007652 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00007653
7654 ChannelType
7655 channel,
7656 channel_mask;
7657
7658 CompositeOperator
7659 compose;
7660
7661 const char
7662 *attribute,
7663 *value;
7664
7665 double
7666 angle;
7667
7668 ExceptionInfo
7669 *exception;
7670
7671 GeometryInfo
7672 geometry_info;
7673
7674 Image
7675 *image,
Cristy7e567962018-02-03 12:42:20 -05007676 *next;
cristy4a3ce0a2013-08-03 20:06:59 +00007677
7678 MagickBooleanType
7679 status;
7680
7681 MagickStatusType
7682 flags;
7683
7684 PixelInfo
7685 fill_color;
7686
7687 RectangleInfo
7688 geometry,
7689 region_info;
7690
7691 register ssize_t
7692 i;
7693
7694 ssize_t
7695 base,
7696 j,
7697 number_images;
7698
7699 struct Methods
7700 *rp;
7701
7702 struct PackageInfo
7703 *info;
7704
7705 SV
7706 *perl_exception,
7707 **pv,
7708 *reference,
7709 **reference_vector;
7710
7711 struct ArgumentList
7712 argument_list[MaxArguments];
7713
7714 PERL_UNUSED_VAR(ref);
7715 PERL_UNUSED_VAR(ix);
7716 exception=AcquireExceptionInfo();
7717 perl_exception=newSVpv("",0);
7718 reference_vector=NULL;
cristy4a3ce0a2013-08-03 20:06:59 +00007719 number_images=0;
7720 base=2;
7721 if (sv_isobject(ST(0)) == 0)
7722 {
7723 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7724 PackageName);
7725 goto PerlException;
7726 }
7727 reference=SvRV(ST(0));
7728 region_info.width=0;
7729 region_info.height=0;
7730 region_info.x=0;
7731 region_info.y=0;
cristy4a3ce0a2013-08-03 20:06:59 +00007732 image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7733 if (ix && (ix != 666))
7734 {
7735 /*
7736 Called as Method(...)
7737 */
7738 ix=(ix+1)/2;
7739 rp=(&Methods[ix-1]);
7740 attribute=rp->name;
7741 }
7742 else
7743 {
7744 /*
7745 Called as Mogrify("Method",...)
7746 */
7747 attribute=(char *) SvPV(ST(1),na);
7748 if (ix)
7749 {
7750 flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7751 attribute=(char *) SvPV(ST(2),na);
7752 base++;
7753 }
7754 for (rp=Methods; ; rp++)
7755 {
7756 if (rp >= EndOf(Methods))
7757 {
7758 ThrowPerlException(exception,OptionError,
7759 "UnrecognizedPerlMagickMethod",attribute);
7760 goto PerlException;
7761 }
7762 if (strEQcase(attribute,rp->name))
7763 break;
7764 }
7765 ix=rp-Methods+1;
7766 base++;
7767 }
7768 if (image == (Image *) NULL)
7769 {
7770 ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7771 goto PerlException;
7772 }
7773 Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7774 Zero(&attribute_flag,NumberOf(attribute_flag),char);
7775 for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7776 {
7777 Arguments
7778 *pp,
7779 *qq;
7780
7781 ssize_t
7782 ssize_test;
7783
7784 struct ArgumentList
7785 *al;
7786
7787 SV
7788 *sv;
7789
7790 sv=NULL;
7791 ssize_test=0;
7792 pp=(Arguments *) NULL;
7793 qq=rp->arguments;
7794 if (i == items)
7795 {
7796 pp=rp->arguments,
7797 sv=ST(i-1);
7798 }
7799 else
7800 for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7801 {
7802 if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7803 break;
7804 if (strEQcase(attribute,qq->method) > ssize_test)
7805 {
7806 pp=qq;
7807 ssize_test=strEQcase(attribute,qq->method);
7808 }
7809 }
7810 if (pp == (Arguments *) NULL)
7811 {
7812 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7813 attribute);
7814 goto continue_outer_loop;
7815 }
7816 al=(&argument_list[pp-rp->arguments]);
7817 switch (pp->type)
7818 {
7819 case ArrayReference:
7820 {
7821 if (SvTYPE(sv) != SVt_RV)
7822 {
cristy151b66d2015-04-15 10:50:31 +00007823 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007824 "invalid %.60s value",pp->method);
7825 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7826 goto continue_outer_loop;
7827 }
7828 al->array_reference=SvRV(sv);
7829 break;
7830 }
7831 case RealReference:
7832 {
7833 al->real_reference=SvNV(sv);
7834 break;
7835 }
7836 case FileReference:
7837 {
7838 al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7839 break;
7840 }
7841 case ImageReference:
7842 {
7843 if (!sv_isobject(sv) ||
7844 !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7845 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7846 {
7847 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7848 PackageName);
7849 goto PerlException;
7850 }
7851 break;
7852 }
7853 case IntegerReference:
7854 {
7855 al->integer_reference=SvIV(sv);
7856 break;
7857 }
7858 case StringReference:
7859 {
7860 al->string_reference=(char *) SvPV(sv,al->length);
7861 if (sv_isobject(sv))
7862 al->image_reference=SetupList(aTHX_ SvRV(sv),
7863 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7864 break;
7865 }
7866 default:
7867 {
7868 /*
7869 Is a string; look up name.
7870 */
7871 if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7872 {
7873 al->string_reference=(char *) SvPV(sv,al->length);
7874 al->integer_reference=(-1);
7875 break;
7876 }
7877 al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7878 MagickFalse,SvPV(sv,na));
7879 if (pp->type == MagickChannelOptions)
7880 al->integer_reference=ParseChannelOption(SvPV(sv,na));
7881 if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7882 {
cristy151b66d2015-04-15 10:50:31 +00007883 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007884 "invalid %.60s value",pp->method);
7885 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7886 goto continue_outer_loop;
7887 }
7888 break;
7889 }
7890 }
7891 attribute_flag[pp-rp->arguments]++;
7892 continue_outer_loop: ;
7893 }
7894 (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7895 pv=reference_vector;
7896 SetGeometryInfo(&geometry_info);
7897 channel=DefaultChannels;
7898 for (next=image; next; next=next->next)
7899 {
7900 image=next;
7901 SetGeometry(image,&geometry);
7902 if ((region_info.width*region_info.height) != 0)
Cristy7e567962018-02-03 12:42:20 -05007903 (void) SetImageRegionMask(image,WritePixelMask,&region_info,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007904 switch (ix)
7905 {
7906 default:
7907 {
cristy151b66d2015-04-15 10:50:31 +00007908 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
cristy4a3ce0a2013-08-03 20:06:59 +00007909 ThrowPerlException(exception,OptionError,
7910 "UnrecognizedPerlMagickMethod",message);
7911 goto PerlException;
7912 }
7913 case 1: /* Comment */
7914 {
7915 if (attribute_flag[0] == 0)
7916 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007917 (void) SetImageProperty(image,"comment",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007918 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007919 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007920 break;
7921 }
7922 case 2: /* Label */
7923 {
7924 if (attribute_flag[0] == 0)
7925 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007926 (void) SetImageProperty(image,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007927 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007928 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007929 break;
7930 }
7931 case 3: /* AddNoise */
7932 {
7933 double
7934 attenuate;
7935
7936 if (attribute_flag[0] == 0)
7937 argument_list[0].integer_reference=UniformNoise;
7938 attenuate=1.0;
7939 if (attribute_flag[1] != 0)
7940 attenuate=argument_list[1].real_reference;
7941 if (attribute_flag[2] != 0)
7942 channel=(ChannelType) argument_list[2].integer_reference;
7943 channel_mask=SetImageChannelMask(image,channel);
7944 image=AddNoiseImage(image,(NoiseType)
7945 argument_list[0].integer_reference,attenuate,exception);
7946 if (image != (Image *) NULL)
7947 (void) SetImageChannelMask(image,channel_mask);
7948 break;
7949 }
7950 case 4: /* Colorize */
7951 {
7952 PixelInfo
7953 target;
7954
7955 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7956 0,0,&target,exception);
7957 if (attribute_flag[0] != 0)
7958 (void) QueryColorCompliance(argument_list[0].string_reference,
7959 AllCompliance,&target,exception);
7960 if (attribute_flag[1] == 0)
7961 argument_list[1].string_reference="100%";
7962 image=ColorizeImage(image,argument_list[1].string_reference,&target,
7963 exception);
7964 break;
7965 }
7966 case 5: /* Border */
7967 {
7968 CompositeOperator
7969 compose;
7970
7971 geometry.width=0;
7972 geometry.height=0;
7973 if (attribute_flag[0] != 0)
7974 flags=ParsePageGeometry(image,argument_list[0].string_reference,
7975 &geometry,exception);
7976 if (attribute_flag[1] != 0)
7977 geometry.width=argument_list[1].integer_reference;
7978 if (attribute_flag[2] != 0)
7979 geometry.height=argument_list[2].integer_reference;
7980 if (attribute_flag[3] != 0)
7981 QueryColorCompliance(argument_list[3].string_reference,
7982 AllCompliance,&image->border_color,exception);
7983 if (attribute_flag[4] != 0)
7984 QueryColorCompliance(argument_list[4].string_reference,
7985 AllCompliance,&image->border_color,exception);
7986 if (attribute_flag[5] != 0)
7987 QueryColorCompliance(argument_list[5].string_reference,
7988 AllCompliance,&image->border_color,exception);
7989 compose=image->compose;
7990 if (attribute_flag[6] != 0)
7991 compose=(CompositeOperator) argument_list[6].integer_reference;
7992 image=BorderImage(image,&geometry,compose,exception);
7993 break;
7994 }
7995 case 6: /* Blur */
7996 {
7997 if (attribute_flag[0] != 0)
7998 {
7999 flags=ParseGeometry(argument_list[0].string_reference,
8000 &geometry_info);
8001 if ((flags & SigmaValue) == 0)
8002 geometry_info.sigma=1.0;
8003 }
8004 if (attribute_flag[1] != 0)
8005 geometry_info.rho=argument_list[1].real_reference;
8006 if (attribute_flag[2] != 0)
8007 geometry_info.sigma=argument_list[2].real_reference;
8008 if (attribute_flag[3] != 0)
8009 channel=(ChannelType) argument_list[3].integer_reference;
8010 channel_mask=SetImageChannelMask(image,channel);
8011 image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
8012 exception);
8013 if (image != (Image *) NULL)
8014 (void) SetImageChannelMask(image,channel_mask);
8015 break;
8016 }
8017 case 7: /* Chop */
8018 {
cristy260bd762014-08-15 12:46:34 +00008019 if (attribute_flag[5] != 0)
8020 image->gravity=(GravityType) argument_list[5].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00008021 if (attribute_flag[0] != 0)
8022 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8023 &geometry,exception);
8024 if (attribute_flag[1] != 0)
8025 geometry.width=argument_list[1].integer_reference;
8026 if (attribute_flag[2] != 0)
8027 geometry.height=argument_list[2].integer_reference;
8028 if (attribute_flag[3] != 0)
8029 geometry.x=argument_list[3].integer_reference;
8030 if (attribute_flag[4] != 0)
8031 geometry.y=argument_list[4].integer_reference;
8032 image=ChopImage(image,&geometry,exception);
8033 break;
8034 }
8035 case 8: /* Crop */
8036 {
8037 if (attribute_flag[6] != 0)
8038 image->gravity=(GravityType) argument_list[6].integer_reference;
8039 if (attribute_flag[0] != 0)
8040 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8041 &geometry,exception);
8042 if (attribute_flag[1] != 0)
8043 geometry.width=argument_list[1].integer_reference;
8044 if (attribute_flag[2] != 0)
8045 geometry.height=argument_list[2].integer_reference;
8046 if (attribute_flag[3] != 0)
8047 geometry.x=argument_list[3].integer_reference;
8048 if (attribute_flag[4] != 0)
8049 geometry.y=argument_list[4].integer_reference;
8050 if (attribute_flag[5] != 0)
8051 image->fuzz=StringToDoubleInterval(
8052 argument_list[5].string_reference,(double) QuantumRange+1.0);
8053 image=CropImage(image,&geometry,exception);
8054 break;
8055 }
8056 case 9: /* Despeckle */
8057 {
8058 image=DespeckleImage(image,exception);
8059 break;
8060 }
8061 case 10: /* Edge */
8062 {
8063 if (attribute_flag[0] != 0)
8064 geometry_info.rho=argument_list[0].real_reference;
8065 image=EdgeImage(image,geometry_info.rho,exception);
8066 break;
8067 }
8068 case 11: /* Emboss */
8069 {
8070 if (attribute_flag[0] != 0)
8071 {
8072 flags=ParseGeometry(argument_list[0].string_reference,
8073 &geometry_info);
8074 if ((flags & SigmaValue) == 0)
8075 geometry_info.sigma=1.0;
8076 }
8077 if (attribute_flag[1] != 0)
8078 geometry_info.rho=argument_list[1].real_reference;
8079 if (attribute_flag[2] != 0)
8080 geometry_info.sigma=argument_list[2].real_reference;
8081 image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8082 exception);
8083 break;
8084 }
8085 case 12: /* Enhance */
8086 {
8087 image=EnhanceImage(image,exception);
8088 break;
8089 }
8090 case 13: /* Flip */
8091 {
8092 image=FlipImage(image,exception);
8093 break;
8094 }
8095 case 14: /* Flop */
8096 {
8097 image=FlopImage(image,exception);
8098 break;
8099 }
8100 case 15: /* Frame */
8101 {
8102 CompositeOperator
8103 compose;
8104
8105 FrameInfo
8106 frame_info;
8107
8108 if (attribute_flag[0] != 0)
8109 {
8110 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8111 &geometry,exception);
8112 frame_info.width=geometry.width;
8113 frame_info.height=geometry.height;
8114 frame_info.outer_bevel=geometry.x;
8115 frame_info.inner_bevel=geometry.y;
8116 }
8117 if (attribute_flag[1] != 0)
8118 frame_info.width=argument_list[1].integer_reference;
8119 if (attribute_flag[2] != 0)
8120 frame_info.height=argument_list[2].integer_reference;
8121 if (attribute_flag[3] != 0)
8122 frame_info.inner_bevel=argument_list[3].integer_reference;
8123 if (attribute_flag[4] != 0)
8124 frame_info.outer_bevel=argument_list[4].integer_reference;
8125 if (attribute_flag[5] != 0)
8126 QueryColorCompliance(argument_list[5].string_reference,
8127 AllCompliance,&fill_color,exception);
8128 if (attribute_flag[6] != 0)
8129 QueryColorCompliance(argument_list[6].string_reference,
8130 AllCompliance,&fill_color,exception);
8131 frame_info.x=(ssize_t) frame_info.width;
8132 frame_info.y=(ssize_t) frame_info.height;
8133 frame_info.width=image->columns+2*frame_info.x;
8134 frame_info.height=image->rows+2*frame_info.y;
8135 if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
Cristy8645e042016-02-03 16:35:29 -05008136 image->alpha_color=fill_color;
cristy4a3ce0a2013-08-03 20:06:59 +00008137 compose=image->compose;
8138 if (attribute_flag[7] != 0)
8139 compose=(CompositeOperator) argument_list[7].integer_reference;
8140 image=FrameImage(image,&frame_info,compose,exception);
8141 break;
8142 }
8143 case 16: /* Implode */
8144 {
8145 PixelInterpolateMethod
8146 method;
8147
8148 if (attribute_flag[0] == 0)
8149 argument_list[0].real_reference=0.5;
8150 method=UndefinedInterpolatePixel;
8151 if (attribute_flag[1] != 0)
8152 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8153 image=ImplodeImage(image,argument_list[0].real_reference,
8154 method,exception);
8155 break;
8156 }
8157 case 17: /* Magnify */
8158 {
8159 image=MagnifyImage(image,exception);
8160 break;
8161 }
8162 case 18: /* MedianFilter */
8163 {
8164 if (attribute_flag[0] != 0)
8165 {
8166 flags=ParseGeometry(argument_list[0].string_reference,
8167 &geometry_info);
8168 if ((flags & SigmaValue) == 0)
8169 geometry_info.sigma=geometry_info.rho;
8170 }
8171 if (attribute_flag[1] != 0)
8172 geometry_info.rho=argument_list[1].real_reference;
8173 if (attribute_flag[2] != 0)
8174 geometry_info.sigma=argument_list[2].real_reference;
8175 if (attribute_flag[3] != 0)
8176 channel=(ChannelType) argument_list[3].integer_reference;
8177 channel_mask=SetImageChannelMask(image,channel);
8178 image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8179 (size_t) geometry_info.sigma,exception);
8180 if (image != (Image *) NULL)
8181 (void) SetImageChannelMask(image,channel_mask);
8182 break;
8183 }
8184 case 19: /* Minify */
8185 {
8186 image=MinifyImage(image,exception);
8187 break;
8188 }
8189 case 20: /* OilPaint */
8190 {
8191 if (attribute_flag[0] == 0)
8192 argument_list[0].real_reference=0.0;
8193 if (attribute_flag[1] == 0)
8194 argument_list[1].real_reference=1.0;
8195 image=OilPaintImage(image,argument_list[0].real_reference,
8196 argument_list[1].real_reference,exception);
8197 break;
8198 }
8199 case 21: /* ReduceNoise */
8200 {
8201 if (attribute_flag[0] != 0)
8202 {
8203 flags=ParseGeometry(argument_list[0].string_reference,
8204 &geometry_info);
8205 if ((flags & SigmaValue) == 0)
8206 geometry_info.sigma=1.0;
8207 }
8208 if (attribute_flag[1] != 0)
8209 geometry_info.rho=argument_list[1].real_reference;
8210 if (attribute_flag[2] != 0)
8211 geometry_info.sigma=argument_list[2].real_reference;
8212 if (attribute_flag[3] != 0)
8213 channel=(ChannelType) argument_list[3].integer_reference;
8214 channel_mask=SetImageChannelMask(image,channel);
8215 image=StatisticImage(image,NonpeakStatistic,(size_t)
8216 geometry_info.rho,(size_t) geometry_info.sigma,exception);
8217 if (image != (Image *) NULL)
8218 (void) SetImageChannelMask(image,channel_mask);
8219 break;
8220 }
8221 case 22: /* Roll */
8222 {
8223 if (attribute_flag[0] != 0)
Cristyf94b0842017-07-14 07:05:02 -04008224 {
8225 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8226 &geometry,exception);
8227 if ((flags & PercentValue) != 0)
8228 {
8229 geometry.x*=(double) image->columns/100.0;
8230 geometry.y*=(double) image->rows/100.0;
8231 }
8232 }
cristy4a3ce0a2013-08-03 20:06:59 +00008233 if (attribute_flag[1] != 0)
8234 geometry.x=argument_list[1].integer_reference;
8235 if (attribute_flag[2] != 0)
8236 geometry.y=argument_list[2].integer_reference;
8237 image=RollImage(image,geometry.x,geometry.y,exception);
8238 break;
8239 }
8240 case 23: /* Rotate */
8241 {
8242 if (attribute_flag[0] == 0)
8243 argument_list[0].real_reference=90.0;
8244 if (attribute_flag[1] != 0)
8245 {
8246 QueryColorCompliance(argument_list[1].string_reference,
8247 AllCompliance,&image->background_color,exception);
cristy17f11b02014-12-20 19:37:04 +00008248 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8249 (image->alpha_trait == UndefinedPixelTrait))
cristy4a3ce0a2013-08-03 20:06:59 +00008250 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8251 }
8252 image=RotateImage(image,argument_list[0].real_reference,exception);
8253 break;
8254 }
8255 case 24: /* Sample */
8256 {
8257 if (attribute_flag[0] != 0)
8258 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8259 &geometry,exception);
8260 if (attribute_flag[1] != 0)
8261 geometry.width=argument_list[1].integer_reference;
8262 if (attribute_flag[2] != 0)
8263 geometry.height=argument_list[2].integer_reference;
8264 image=SampleImage(image,geometry.width,geometry.height,exception);
8265 break;
8266 }
8267 case 25: /* Scale */
8268 {
8269 if (attribute_flag[0] != 0)
8270 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8271 &geometry,exception);
8272 if (attribute_flag[1] != 0)
8273 geometry.width=argument_list[1].integer_reference;
8274 if (attribute_flag[2] != 0)
8275 geometry.height=argument_list[2].integer_reference;
8276 image=ScaleImage(image,geometry.width,geometry.height,exception);
8277 break;
8278 }
8279 case 26: /* Shade */
8280 {
8281 if (attribute_flag[0] != 0)
8282 {
8283 flags=ParseGeometry(argument_list[0].string_reference,
8284 &geometry_info);
8285 if ((flags & SigmaValue) == 0)
8286 geometry_info.sigma=0.0;
8287 }
8288 if (attribute_flag[1] != 0)
8289 geometry_info.rho=argument_list[1].real_reference;
8290 if (attribute_flag[2] != 0)
8291 geometry_info.sigma=argument_list[2].real_reference;
8292 image=ShadeImage(image,
8293 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8294 geometry_info.rho,geometry_info.sigma,exception);
8295 break;
8296 }
8297 case 27: /* Sharpen */
8298 {
8299 if (attribute_flag[0] != 0)
8300 {
8301 flags=ParseGeometry(argument_list[0].string_reference,
8302 &geometry_info);
8303 if ((flags & SigmaValue) == 0)
8304 geometry_info.sigma=1.0;
8305 }
8306 if (attribute_flag[1] != 0)
8307 geometry_info.rho=argument_list[1].real_reference;
8308 if (attribute_flag[2] != 0)
8309 geometry_info.sigma=argument_list[2].real_reference;
8310 if (attribute_flag[3] != 0)
8311 channel=(ChannelType) argument_list[3].integer_reference;
8312 channel_mask=SetImageChannelMask(image,channel);
8313 image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8314 exception);
8315 if (image != (Image *) NULL)
8316 (void) SetImageChannelMask(image,channel_mask);
8317 break;
8318 }
8319 case 28: /* Shear */
8320 {
8321 if (attribute_flag[0] != 0)
8322 {
8323 flags=ParseGeometry(argument_list[0].string_reference,
8324 &geometry_info);
8325 if ((flags & SigmaValue) == 0)
8326 geometry_info.sigma=geometry_info.rho;
8327 }
8328 if (attribute_flag[1] != 0)
8329 geometry_info.rho=argument_list[1].real_reference;
8330 if (attribute_flag[2] != 0)
8331 geometry_info.sigma=argument_list[2].real_reference;
8332 if (attribute_flag[3] != 0)
8333 QueryColorCompliance(argument_list[3].string_reference,
8334 AllCompliance,&image->background_color,exception);
8335 if (attribute_flag[4] != 0)
8336 QueryColorCompliance(argument_list[4].string_reference,
8337 AllCompliance,&image->background_color,exception);
8338 image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8339 exception);
8340 break;
8341 }
8342 case 29: /* Spread */
8343 {
Cristye3319c12015-08-24 07:11:48 -04008344 PixelInterpolateMethod
8345 method;
8346
cristy4a3ce0a2013-08-03 20:06:59 +00008347 if (attribute_flag[0] == 0)
8348 argument_list[0].real_reference=1.0;
Cristye3319c12015-08-24 07:11:48 -04008349 method=UndefinedInterpolatePixel;
8350 if (attribute_flag[1] != 0)
8351 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8352 image=SpreadImage(image,method,argument_list[0].real_reference,
8353 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008354 break;
8355 }
8356 case 30: /* Swirl */
8357 {
8358 PixelInterpolateMethod
8359 method;
8360
8361 if (attribute_flag[0] == 0)
8362 argument_list[0].real_reference=50.0;
8363 method=UndefinedInterpolatePixel;
8364 if (attribute_flag[1] != 0)
8365 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8366 image=SwirlImage(image,argument_list[0].real_reference,
8367 method,exception);
8368 break;
8369 }
8370 case 31: /* Resize */
8371 case 32: /* Zoom */
8372 {
8373 if (attribute_flag[0] != 0)
8374 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8375 &geometry,exception);
8376 if (attribute_flag[1] != 0)
8377 geometry.width=argument_list[1].integer_reference;
8378 if (attribute_flag[2] != 0)
8379 geometry.height=argument_list[2].integer_reference;
8380 if (attribute_flag[3] == 0)
8381 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8382 if (attribute_flag[4] != 0)
8383 SetImageArtifact(image,"filter:support",
8384 argument_list[4].string_reference);
8385 image=ResizeImage(image,geometry.width,geometry.height,
Cristy8645e042016-02-03 16:35:29 -05008386 (FilterType) argument_list[3].integer_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00008387 exception);
8388 break;
8389 }
8390 case 33: /* Annotate */
8391 {
8392 DrawInfo
8393 *draw_info;
8394
8395 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8396 (DrawInfo *) NULL);
8397 if (attribute_flag[0] != 0)
8398 {
8399 char
8400 *text;
8401
8402 text=InterpretImageProperties(info ? info->image_info :
8403 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8404 exception);
8405 (void) CloneString(&draw_info->text,text);
8406 text=DestroyString(text);
8407 }
8408 if (attribute_flag[1] != 0)
8409 (void) CloneString(&draw_info->font,
8410 argument_list[1].string_reference);
8411 if (attribute_flag[2] != 0)
8412 draw_info->pointsize=argument_list[2].real_reference;
8413 if (attribute_flag[3] != 0)
8414 (void) CloneString(&draw_info->density,
8415 argument_list[3].string_reference);
8416 if (attribute_flag[4] != 0)
8417 (void) QueryColorCompliance(argument_list[4].string_reference,
8418 AllCompliance,&draw_info->undercolor,exception);
8419 if (attribute_flag[5] != 0)
8420 {
8421 (void) QueryColorCompliance(argument_list[5].string_reference,
8422 AllCompliance,&draw_info->stroke,exception);
8423 if (argument_list[5].image_reference != (Image *) NULL)
8424 draw_info->stroke_pattern=CloneImage(
8425 argument_list[5].image_reference,0,0,MagickTrue,exception);
8426 }
8427 if (attribute_flag[6] != 0)
8428 {
8429 (void) QueryColorCompliance(argument_list[6].string_reference,
8430 AllCompliance,&draw_info->fill,exception);
8431 if (argument_list[6].image_reference != (Image *) NULL)
8432 draw_info->fill_pattern=CloneImage(
8433 argument_list[6].image_reference,0,0,MagickTrue,exception);
8434 }
8435 if (attribute_flag[7] != 0)
8436 {
8437 (void) CloneString(&draw_info->geometry,
8438 argument_list[7].string_reference);
8439 flags=ParsePageGeometry(image,argument_list[7].string_reference,
8440 &geometry,exception);
8441 if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8442 geometry_info.sigma=geometry_info.xi;
8443 }
8444 if (attribute_flag[8] != 0)
8445 (void) QueryColorCompliance(argument_list[8].string_reference,
8446 AllCompliance,&draw_info->fill,exception);
8447 if (attribute_flag[11] != 0)
8448 draw_info->gravity=(GravityType)
8449 argument_list[11].integer_reference;
8450 if (attribute_flag[25] != 0)
8451 {
8452 AV
8453 *av;
8454
8455 av=(AV *) argument_list[25].array_reference;
8456 if ((av_len(av) != 3) && (av_len(av) != 5))
8457 {
8458 ThrowPerlException(exception,OptionError,
8459 "affine matrix must have 4 or 6 elements",PackageName);
8460 goto PerlException;
8461 }
8462 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8463 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8464 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8465 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8466 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8467 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8468 {
8469 ThrowPerlException(exception,OptionError,
8470 "affine matrix is singular",PackageName);
8471 goto PerlException;
8472 }
8473 if (av_len(av) == 5)
8474 {
8475 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8476 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8477 }
8478 }
8479 for (j=12; j < 17; j++)
8480 {
8481 if (attribute_flag[j] == 0)
8482 continue;
8483 value=argument_list[j].string_reference;
8484 angle=argument_list[j].real_reference;
8485 current=draw_info->affine;
8486 GetAffineMatrix(&affine);
8487 switch (j)
8488 {
8489 case 12:
8490 {
8491 /*
8492 Translate.
8493 */
8494 flags=ParseGeometry(value,&geometry_info);
8495 affine.tx=geometry_info.xi;
8496 affine.ty=geometry_info.psi;
8497 if ((flags & PsiValue) == 0)
8498 affine.ty=affine.tx;
8499 break;
8500 }
8501 case 13:
8502 {
8503 /*
8504 Scale.
8505 */
8506 flags=ParseGeometry(value,&geometry_info);
8507 affine.sx=geometry_info.rho;
8508 affine.sy=geometry_info.sigma;
8509 if ((flags & SigmaValue) == 0)
8510 affine.sy=affine.sx;
8511 break;
8512 }
8513 case 14:
8514 {
8515 /*
8516 Rotate.
8517 */
8518 if (angle == 0.0)
8519 break;
8520 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8521 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8522 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8523 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8524 break;
8525 }
8526 case 15:
8527 {
8528 /*
8529 SkewX.
8530 */
8531 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8532 break;
8533 }
8534 case 16:
8535 {
8536 /*
8537 SkewY.
8538 */
8539 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8540 break;
8541 }
8542 }
8543 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8544 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8545 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8546 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8547 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8548 current.tx;
8549 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8550 current.ty;
8551 }
8552 if (attribute_flag[9] == 0)
8553 argument_list[9].real_reference=0.0;
8554 if (attribute_flag[10] == 0)
8555 argument_list[10].real_reference=0.0;
8556 if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8557 {
8558 char
cristy151b66d2015-04-15 10:50:31 +00008559 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008560
cristy151b66d2015-04-15 10:50:31 +00008561 (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
cristy4a3ce0a2013-08-03 20:06:59 +00008562 (double) argument_list[9].real_reference+draw_info->affine.tx,
8563 (double) argument_list[10].real_reference+draw_info->affine.ty);
8564 (void) CloneString(&draw_info->geometry,geometry);
8565 }
8566 if (attribute_flag[17] != 0)
8567 draw_info->stroke_width=argument_list[17].real_reference;
8568 if (attribute_flag[18] != 0)
8569 {
8570 draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8571 MagickTrue : MagickFalse;
8572 draw_info->stroke_antialias=draw_info->text_antialias;
8573 }
8574 if (attribute_flag[19] != 0)
8575 (void) CloneString(&draw_info->family,
8576 argument_list[19].string_reference);
8577 if (attribute_flag[20] != 0)
8578 draw_info->style=(StyleType) argument_list[20].integer_reference;
8579 if (attribute_flag[21] != 0)
8580 draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8581 if (attribute_flag[22] != 0)
8582 draw_info->weight=argument_list[22].integer_reference;
8583 if (attribute_flag[23] != 0)
8584 draw_info->align=(AlignType) argument_list[23].integer_reference;
8585 if (attribute_flag[24] != 0)
8586 (void) CloneString(&draw_info->encoding,
8587 argument_list[24].string_reference);
8588 if (attribute_flag[25] != 0)
8589 draw_info->fill_pattern=CloneImage(
8590 argument_list[25].image_reference,0,0,MagickTrue,exception);
8591 if (attribute_flag[26] != 0)
8592 draw_info->fill_pattern=CloneImage(
8593 argument_list[26].image_reference,0,0,MagickTrue,exception);
8594 if (attribute_flag[27] != 0)
8595 draw_info->stroke_pattern=CloneImage(
8596 argument_list[27].image_reference,0,0,MagickTrue,exception);
8597 if (attribute_flag[29] != 0)
8598 draw_info->kerning=argument_list[29].real_reference;
8599 if (attribute_flag[30] != 0)
8600 draw_info->interline_spacing=argument_list[30].real_reference;
8601 if (attribute_flag[31] != 0)
8602 draw_info->interword_spacing=argument_list[31].real_reference;
8603 if (attribute_flag[32] != 0)
8604 draw_info->direction=(DirectionType)
8605 argument_list[32].integer_reference;
8606 (void) AnnotateImage(image,draw_info,exception);
8607 draw_info=DestroyDrawInfo(draw_info);
8608 break;
8609 }
8610 case 34: /* ColorFloodfill */
8611 {
8612 DrawInfo
8613 *draw_info;
8614
8615 MagickBooleanType
8616 invert;
8617
8618 PixelInfo
8619 target;
8620
8621 draw_info=CloneDrawInfo(info ? info->image_info :
8622 (ImageInfo *) NULL,(DrawInfo *) NULL);
8623 if (attribute_flag[0] != 0)
8624 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8625 &geometry,exception);
8626 if (attribute_flag[1] != 0)
8627 geometry.x=argument_list[1].integer_reference;
8628 if (attribute_flag[2] != 0)
8629 geometry.y=argument_list[2].integer_reference;
8630 if (attribute_flag[3] != 0)
8631 (void) QueryColorCompliance(argument_list[3].string_reference,
8632 AllCompliance,&draw_info->fill,exception);
8633 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8634 geometry.x,geometry.y,&target,exception);
8635 invert=MagickFalse;
8636 if (attribute_flag[4] != 0)
8637 {
8638 QueryColorCompliance(argument_list[4].string_reference,
8639 AllCompliance,&target,exception);
8640 invert=MagickTrue;
8641 }
8642 if (attribute_flag[5] != 0)
8643 image->fuzz=StringToDoubleInterval(
8644 argument_list[5].string_reference,(double) QuantumRange+1.0);
8645 if (attribute_flag[6] != 0)
8646 invert=(MagickBooleanType) argument_list[6].integer_reference;
8647 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8648 geometry.y,invert,exception);
8649 draw_info=DestroyDrawInfo(draw_info);
8650 break;
8651 }
8652 case 35: /* Composite */
8653 {
8654 char
cristy151b66d2015-04-15 10:50:31 +00008655 composite_geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008656
8657 Image
8658 *composite_image,
8659 *rotate_image;
8660
8661 MagickBooleanType
8662 clip_to_self;
8663
8664 compose=OverCompositeOp;
8665 if (attribute_flag[0] != 0)
8666 composite_image=argument_list[0].image_reference;
8667 else
8668 {
8669 ThrowPerlException(exception,OptionError,
8670 "CompositeImageRequired",PackageName);
8671 goto PerlException;
8672 }
8673 /*
8674 Parameter Handling used for BOTH normal and tiled composition.
8675 */
8676 if (attribute_flag[1] != 0) /* compose */
8677 compose=(CompositeOperator) argument_list[1].integer_reference;
8678 if (attribute_flag[6] != 0) /* opacity */
8679 {
8680 if (compose != DissolveCompositeOp)
8681 (void) SetImageAlpha(composite_image,(Quantum)
8682 StringToDoubleInterval(argument_list[6].string_reference,
8683 (double) QuantumRange+1.0),exception);
8684 else
8685 {
8686 CacheView
8687 *composite_view;
8688
8689 double
8690 opacity;
8691
8692 MagickBooleanType
8693 sync;
8694
8695 register ssize_t
8696 x;
8697
8698 register Quantum
8699 *q;
8700
8701 ssize_t
8702 y;
8703
8704 /*
8705 Handle dissolve composite operator (patch by
8706 Kevin A. McGrail).
8707 */
8708 (void) CloneString(&image->geometry,
8709 argument_list[6].string_reference);
8710 opacity=(Quantum) StringToDoubleInterval(
8711 argument_list[6].string_reference,(double) QuantumRange+
8712 1.0);
cristy17f11b02014-12-20 19:37:04 +00008713 if (composite_image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00008714 (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8715 composite_view=AcquireAuthenticCacheView(composite_image,exception);
8716 for (y=0; y < (ssize_t) composite_image->rows ; y++)
8717 {
8718 q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8719 composite_image->columns,1,exception);
8720 for (x=0; x < (ssize_t) composite_image->columns; x++)
8721 {
8722 if (GetPixelAlpha(image,q) == OpaqueAlpha)
8723 SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8724 q);
8725 q+=GetPixelChannels(composite_image);
8726 }
8727 sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8728 if (sync == MagickFalse)
8729 break;
8730 }
8731 composite_view=DestroyCacheView(composite_view);
8732 }
8733 }
8734 if (attribute_flag[9] != 0) /* "color=>" */
8735 QueryColorCompliance(argument_list[9].string_reference,
8736 AllCompliance,&composite_image->background_color,exception);
8737 if (attribute_flag[12] != 0) /* "interpolate=>" */
8738 image->interpolate=(PixelInterpolateMethod)
8739 argument_list[12].integer_reference;
8740 if (attribute_flag[13] != 0) /* "args=>" */
8741 (void) SetImageArtifact(composite_image,"compose:args",
8742 argument_list[13].string_reference);
8743 if (attribute_flag[14] != 0) /* "blend=>" depreciated */
8744 (void) SetImageArtifact(composite_image,"compose:args",
8745 argument_list[14].string_reference);
Cristy72aed842018-07-08 18:25:50 -04008746 clip_to_self=MagickTrue;
8747 switch (compose)
8748 {
8749 case ClearCompositeOp:
8750 case SrcCompositeOp:
8751 case InCompositeOp:
8752 case SrcInCompositeOp:
8753 case OutCompositeOp:
8754 case SrcOutCompositeOp:
8755 case DstInCompositeOp:
8756 case DstAtopCompositeOp:
Cristy901f5212018-07-08 18:43:34 -04008757 case CopyAlphaCompositeOp:
Cristy72aed842018-07-08 18:25:50 -04008758 case ChangeMaskCompositeOp:
8759 case DissolveCompositeOp:
8760 case BlendCompositeOp:
8761 {
Cristy901f5212018-07-08 18:43:34 -04008762 clip_to_self=MagickFalse;
Cristy72aed842018-07-08 18:25:50 -04008763 break;
8764 }
8765 default:
8766 break;
8767 }
cristy4a3ce0a2013-08-03 20:06:59 +00008768 if (attribute_flag[15] != 0)
8769 clip_to_self=(MagickBooleanType)
8770 argument_list[15].integer_reference;
8771 /*
8772 Tiling Composition (with orthogonal rotate).
8773 */
8774 rotate_image=(Image *) NULL;
8775 if (attribute_flag[8] != 0) /* "rotate=>" */
8776 {
8777 /*
8778 Rotate image.
8779 */
8780 rotate_image=RotateImage(composite_image,
8781 argument_list[8].real_reference,exception);
8782 if (rotate_image == (Image *) NULL)
8783 break;
8784 }
8785 if ((attribute_flag[7] != 0) &&
8786 (argument_list[7].integer_reference != 0)) /* tile */
8787 {
8788 ssize_t
8789 x,
8790 y;
8791
8792 /*
8793 Tile the composite image.
8794 */
cristy4a3ce0a2013-08-03 20:06:59 +00008795 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8796 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8797 {
8798 if (attribute_flag[8] != 0) /* rotate */
8799 (void) CompositeImage(image,rotate_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008800 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008801 else
8802 (void) CompositeImage(image,composite_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008803 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008804 }
8805 if (attribute_flag[8] != 0) /* rotate */
8806 rotate_image=DestroyImage(rotate_image);
8807 break;
8808 }
8809 /*
8810 Parameter Handling used used ONLY for normal composition.
8811 */
8812 if (attribute_flag[5] != 0) /* gravity */
8813 image->gravity=(GravityType) argument_list[5].integer_reference;
8814 if (attribute_flag[2] != 0) /* geometry offset */
8815 {
8816 SetGeometry(image,&geometry);
8817 (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8818 &geometry);
8819 GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8820 &geometry);
8821 }
8822 if (attribute_flag[3] != 0) /* x offset */
8823 geometry.x=argument_list[3].integer_reference;
8824 if (attribute_flag[4] != 0) /* y offset */
8825 geometry.y=argument_list[4].integer_reference;
8826 if (attribute_flag[10] != 0) /* mask */
8827 {
8828 if ((image->compose == DisplaceCompositeOp) ||
8829 (image->compose == DistortCompositeOp))
8830 {
8831 /*
8832 Merge Y displacement into X displacement image.
8833 */
8834 composite_image=CloneImage(composite_image,0,0,MagickTrue,
8835 exception);
8836 (void) CompositeImage(composite_image,
8837 argument_list[10].image_reference,CopyGreenCompositeOp,
Cristy74e39292018-07-08 13:13:20 -04008838 clip_to_self,0,0,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008839 }
8840 else
8841 {
8842 Image
8843 *mask_image;
8844
8845 /*
8846 Set a blending mask for the composition.
8847 */
8848 mask_image=CloneImage(argument_list[10].image_reference,0,0,
8849 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +00008850 (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
cristyf3023752015-07-28 17:13:22 +00008851 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008852 mask_image=DestroyImage(mask_image);
8853 }
8854 }
8855 if (attribute_flag[11] != 0) /* channel */
8856 channel=(ChannelType) argument_list[11].integer_reference;
8857 /*
8858 Composite two images (normal composition).
8859 */
cristy151b66d2015-04-15 10:50:31 +00008860 (void) FormatLocaleString(composite_geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00008861 "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8862 (double) composite_image->rows,(double) geometry.x,(double)
8863 geometry.y);
8864 flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8865 exception);
8866 channel_mask=SetImageChannelMask(image,channel);
8867 if (attribute_flag[8] == 0) /* no rotate */
8868 CompositeImage(image,composite_image,compose,clip_to_self,
8869 geometry.x,geometry.y,exception);
8870 else
8871 {
8872 /*
8873 Position adjust rotated image then composite.
8874 */
8875 geometry.x-=(ssize_t) (rotate_image->columns-
8876 composite_image->columns)/2;
8877 geometry.y-=(ssize_t) (rotate_image->rows-
8878 composite_image->rows)/2;
8879 CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8880 geometry.y,exception);
8881 rotate_image=DestroyImage(rotate_image);
8882 }
8883 if (attribute_flag[10] != 0) /* mask */
8884 {
8885 if ((image->compose == DisplaceCompositeOp) ||
8886 (image->compose == DistortCompositeOp))
8887 composite_image=DestroyImage(composite_image);
8888 else
cristy1f7ffb72015-07-29 11:07:03 +00008889 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
cristyf3023752015-07-28 17:13:22 +00008890 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008891 }
8892 (void) SetImageChannelMask(image,channel_mask);
8893 break;
8894 }
8895 case 36: /* Contrast */
8896 {
8897 if (attribute_flag[0] == 0)
8898 argument_list[0].integer_reference=0;
8899 (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8900 MagickTrue : MagickFalse,exception);
8901 break;
8902 }
8903 case 37: /* CycleColormap */
8904 {
8905 if (attribute_flag[0] == 0)
8906 argument_list[0].integer_reference=6;
8907 (void) CycleColormapImage(image,argument_list[0].integer_reference,
8908 exception);
8909 break;
8910 }
8911 case 38: /* Draw */
8912 {
8913 DrawInfo
8914 *draw_info;
8915
8916 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8917 (DrawInfo *) NULL);
8918 (void) CloneString(&draw_info->primitive,"point");
8919 if (attribute_flag[0] != 0)
8920 {
8921 if (argument_list[0].integer_reference < 0)
8922 (void) CloneString(&draw_info->primitive,
8923 argument_list[0].string_reference);
8924 else
8925 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8926 MagickPrimitiveOptions,argument_list[0].integer_reference));
8927 }
8928 if (attribute_flag[1] != 0)
8929 {
8930 if (LocaleCompare(draw_info->primitive,"path") == 0)
8931 {
8932 (void) ConcatenateString(&draw_info->primitive," '");
8933 ConcatenateString(&draw_info->primitive,
8934 argument_list[1].string_reference);
8935 (void) ConcatenateString(&draw_info->primitive,"'");
8936 }
8937 else
8938 {
8939 (void) ConcatenateString(&draw_info->primitive," ");
8940 ConcatenateString(&draw_info->primitive,
8941 argument_list[1].string_reference);
8942 }
8943 }
8944 if (attribute_flag[2] != 0)
8945 {
8946 (void) ConcatenateString(&draw_info->primitive," ");
8947 (void) ConcatenateString(&draw_info->primitive,
8948 CommandOptionToMnemonic(MagickMethodOptions,
8949 argument_list[2].integer_reference));
8950 }
8951 if (attribute_flag[3] != 0)
8952 {
8953 (void) QueryColorCompliance(argument_list[3].string_reference,
8954 AllCompliance,&draw_info->stroke,exception);
8955 if (argument_list[3].image_reference != (Image *) NULL)
8956 draw_info->stroke_pattern=CloneImage(
8957 argument_list[3].image_reference,0,0,MagickTrue,exception);
8958 }
8959 if (attribute_flag[4] != 0)
8960 {
8961 (void) QueryColorCompliance(argument_list[4].string_reference,
8962 AllCompliance,&draw_info->fill,exception);
8963 if (argument_list[4].image_reference != (Image *) NULL)
8964 draw_info->fill_pattern=CloneImage(
8965 argument_list[4].image_reference,0,0,MagickTrue,exception);
8966 }
8967 if (attribute_flag[5] != 0)
8968 draw_info->stroke_width=argument_list[5].real_reference;
8969 if (attribute_flag[6] != 0)
8970 (void) CloneString(&draw_info->font,
8971 argument_list[6].string_reference);
8972 if (attribute_flag[7] != 0)
8973 (void) QueryColorCompliance(argument_list[7].string_reference,
8974 AllCompliance,&draw_info->border_color,exception);
8975 if (attribute_flag[8] != 0)
8976 draw_info->affine.tx=argument_list[8].real_reference;
8977 if (attribute_flag[9] != 0)
8978 draw_info->affine.ty=argument_list[9].real_reference;
8979 if (attribute_flag[20] != 0)
8980 {
8981 AV
8982 *av;
8983
8984 av=(AV *) argument_list[20].array_reference;
8985 if ((av_len(av) != 3) && (av_len(av) != 5))
8986 {
8987 ThrowPerlException(exception,OptionError,
8988 "affine matrix must have 4 or 6 elements",PackageName);
8989 goto PerlException;
8990 }
8991 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8992 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8993 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8994 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8995 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8996 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8997 {
8998 ThrowPerlException(exception,OptionError,
8999 "affine matrix is singular",PackageName);
9000 goto PerlException;
9001 }
9002 if (av_len(av) == 5)
9003 {
9004 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9005 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9006 }
9007 }
9008 for (j=10; j < 15; j++)
9009 {
9010 if (attribute_flag[j] == 0)
9011 continue;
9012 value=argument_list[j].string_reference;
9013 angle=argument_list[j].real_reference;
9014 current=draw_info->affine;
9015 GetAffineMatrix(&affine);
9016 switch (j)
9017 {
9018 case 10:
9019 {
9020 /*
9021 Translate.
9022 */
9023 flags=ParseGeometry(value,&geometry_info);
9024 affine.tx=geometry_info.xi;
9025 affine.ty=geometry_info.psi;
9026 if ((flags & PsiValue) == 0)
9027 affine.ty=affine.tx;
9028 break;
9029 }
9030 case 11:
9031 {
9032 /*
9033 Scale.
9034 */
9035 flags=ParseGeometry(value,&geometry_info);
9036 affine.sx=geometry_info.rho;
9037 affine.sy=geometry_info.sigma;
9038 if ((flags & SigmaValue) == 0)
9039 affine.sy=affine.sx;
9040 break;
9041 }
9042 case 12:
9043 {
9044 /*
9045 Rotate.
9046 */
9047 if (angle == 0.0)
9048 break;
9049 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9050 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9051 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9052 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9053 break;
9054 }
9055 case 13:
9056 {
9057 /*
9058 SkewX.
9059 */
9060 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9061 break;
9062 }
9063 case 14:
9064 {
9065 /*
9066 SkewY.
9067 */
9068 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9069 break;
9070 }
9071 }
9072 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9073 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9074 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9075 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9076 draw_info->affine.tx=
9077 current.sx*affine.tx+current.ry*affine.ty+current.tx;
9078 draw_info->affine.ty=
9079 current.rx*affine.tx+current.sy*affine.ty+current.ty;
9080 }
9081 if (attribute_flag[15] != 0)
9082 draw_info->fill_pattern=CloneImage(
9083 argument_list[15].image_reference,0,0,MagickTrue,exception);
9084 if (attribute_flag[16] != 0)
9085 draw_info->pointsize=argument_list[16].real_reference;
9086 if (attribute_flag[17] != 0)
9087 {
9088 draw_info->stroke_antialias=argument_list[17].integer_reference != 0
9089 ? MagickTrue : MagickFalse;
9090 draw_info->text_antialias=draw_info->stroke_antialias;
9091 }
9092 if (attribute_flag[18] != 0)
9093 (void) CloneString(&draw_info->density,
9094 argument_list[18].string_reference);
9095 if (attribute_flag[19] != 0)
9096 draw_info->stroke_width=argument_list[19].real_reference;
9097 if (attribute_flag[21] != 0)
9098 draw_info->dash_offset=argument_list[21].real_reference;
9099 if (attribute_flag[22] != 0)
9100 {
9101 AV
9102 *av;
9103
9104 av=(AV *) argument_list[22].array_reference;
9105 draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9106 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9107 if (draw_info->dash_pattern != (double *) NULL)
9108 {
9109 for (i=0; i <= av_len(av); i++)
9110 draw_info->dash_pattern[i]=(double)
9111 SvNV(*(av_fetch(av,i,0)));
9112 draw_info->dash_pattern[i]=0.0;
9113 }
9114 }
9115 if (attribute_flag[23] != 0)
9116 image->interpolate=(PixelInterpolateMethod)
9117 argument_list[23].integer_reference;
9118 if ((attribute_flag[24] != 0) &&
9119 (draw_info->fill_pattern != (Image *) NULL))
9120 flags=ParsePageGeometry(draw_info->fill_pattern,
9121 argument_list[24].string_reference,
9122 &draw_info->fill_pattern->tile_offset,exception);
9123 if (attribute_flag[25] != 0)
9124 {
9125 (void) ConcatenateString(&draw_info->primitive," '");
9126 (void) ConcatenateString(&draw_info->primitive,
9127 argument_list[25].string_reference);
9128 (void) ConcatenateString(&draw_info->primitive,"'");
9129 }
9130 if (attribute_flag[26] != 0)
9131 draw_info->fill_pattern=CloneImage(
9132 argument_list[26].image_reference,0,0,MagickTrue,exception);
9133 if (attribute_flag[27] != 0)
9134 draw_info->stroke_pattern=CloneImage(
9135 argument_list[27].image_reference,0,0,MagickTrue,exception);
9136 if (attribute_flag[28] != 0)
9137 (void) CloneString(&draw_info->primitive,
9138 argument_list[28].string_reference);
9139 if (attribute_flag[29] != 0)
9140 draw_info->kerning=argument_list[29].real_reference;
9141 if (attribute_flag[30] != 0)
9142 draw_info->interline_spacing=argument_list[30].real_reference;
9143 if (attribute_flag[31] != 0)
9144 draw_info->interword_spacing=argument_list[31].real_reference;
9145 if (attribute_flag[32] != 0)
9146 draw_info->direction=(DirectionType)
9147 argument_list[32].integer_reference;
9148 DrawImage(image,draw_info,exception);
9149 draw_info=DestroyDrawInfo(draw_info);
9150 break;
9151 }
9152 case 39: /* Equalize */
9153 {
9154 if (attribute_flag[0] != 0)
9155 channel=(ChannelType) argument_list[0].integer_reference;
9156 channel_mask=SetImageChannelMask(image,channel);
9157 EqualizeImage(image,exception);
9158 (void) SetImageChannelMask(image,channel_mask);
9159 break;
9160 }
9161 case 40: /* Gamma */
9162 {
9163 if (attribute_flag[1] != 0)
9164 channel=(ChannelType) argument_list[1].integer_reference;
9165 if (attribute_flag[2] == 0)
9166 argument_list[2].real_reference=1.0;
9167 if (attribute_flag[3] == 0)
9168 argument_list[3].real_reference=1.0;
9169 if (attribute_flag[4] == 0)
9170 argument_list[4].real_reference=1.0;
9171 if (attribute_flag[0] == 0)
9172 {
cristy151b66d2015-04-15 10:50:31 +00009173 (void) FormatLocaleString(message,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -05009174 "%.20g,%.20g,%.20g",(double) argument_list[2].real_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009175 (double) argument_list[3].real_reference,
9176 (double) argument_list[4].real_reference);
9177 argument_list[0].string_reference=message;
9178 }
9179 (void) GammaImage(image,StringToDouble(
9180 argument_list[0].string_reference,(char **) NULL),exception);
9181 break;
9182 }
9183 case 41: /* Map */
9184 {
9185 QuantizeInfo
9186 *quantize_info;
9187
9188 if (attribute_flag[0] == 0)
9189 {
9190 ThrowPerlException(exception,OptionError,"MapImageRequired",
9191 PackageName);
9192 goto PerlException;
9193 }
9194 quantize_info=AcquireQuantizeInfo(info->image_info);
9195 if (attribute_flag[1] != 0)
9196 quantize_info->dither_method=(DitherMethod)
9197 argument_list[1].integer_reference;
9198 (void) RemapImages(quantize_info,image,
9199 argument_list[0].image_reference,exception);
9200 quantize_info=DestroyQuantizeInfo(quantize_info);
9201 break;
9202 }
9203 case 42: /* MatteFloodfill */
9204 {
9205 DrawInfo
9206 *draw_info;
9207
9208 MagickBooleanType
9209 invert;
9210
9211 PixelInfo
9212 target;
9213
9214 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9215 (DrawInfo *) NULL);
9216 if (attribute_flag[0] != 0)
9217 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9218 &geometry,exception);
9219 if (attribute_flag[1] != 0)
9220 geometry.x=argument_list[1].integer_reference;
9221 if (attribute_flag[2] != 0)
9222 geometry.y=argument_list[2].integer_reference;
cristy17f11b02014-12-20 19:37:04 +00009223 if (image->alpha_trait == UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00009224 (void) SetImageAlpha(image,OpaqueAlpha,exception);
9225 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9226 geometry.x,geometry.y,&target,exception);
9227 if (attribute_flag[4] != 0)
9228 QueryColorCompliance(argument_list[4].string_reference,
9229 AllCompliance,&target,exception);
9230 if (attribute_flag[3] != 0)
9231 target.alpha=StringToDoubleInterval(
9232 argument_list[3].string_reference,(double) (double) QuantumRange+
9233 1.0);
9234 if (attribute_flag[5] != 0)
9235 image->fuzz=StringToDoubleInterval(
9236 argument_list[5].string_reference,(double) QuantumRange+1.0);
9237 invert=MagickFalse;
9238 if (attribute_flag[6] != 0)
9239 invert=(MagickBooleanType) argument_list[6].integer_reference;
9240 channel_mask=SetImageChannelMask(image,AlphaChannel);
9241 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9242 geometry.y,invert,exception);
9243 (void) SetImageChannelMask(image,channel_mask);
9244 draw_info=DestroyDrawInfo(draw_info);
9245 break;
9246 }
9247 case 43: /* Modulate */
9248 {
9249 char
cristy151b66d2015-04-15 10:50:31 +00009250 modulate[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00009251
9252 geometry_info.rho=100.0;
9253 geometry_info.sigma=100.0;
9254 geometry_info.xi=100.0;
9255 if (attribute_flag[0] != 0)
9256 (void)ParseGeometry(argument_list[0].string_reference,
9257 &geometry_info);
9258 if (attribute_flag[1] != 0)
9259 geometry_info.xi=argument_list[1].real_reference;
9260 if (attribute_flag[2] != 0)
9261 geometry_info.sigma=argument_list[2].real_reference;
9262 if (attribute_flag[3] != 0)
9263 {
9264 geometry_info.sigma=argument_list[3].real_reference;
9265 SetImageArtifact(image,"modulate:colorspace","HWB");
9266 }
9267 if (attribute_flag[4] != 0)
9268 {
9269 geometry_info.rho=argument_list[4].real_reference;
9270 SetImageArtifact(image,"modulate:colorspace","HSB");
9271 }
9272 if (attribute_flag[5] != 0)
9273 {
9274 geometry_info.sigma=argument_list[5].real_reference;
9275 SetImageArtifact(image,"modulate:colorspace","HSL");
9276 }
9277 if (attribute_flag[6] != 0)
9278 {
9279 geometry_info.rho=argument_list[6].real_reference;
9280 SetImageArtifact(image,"modulate:colorspace","HWB");
9281 }
Cristy935a4052017-03-31 17:45:37 -04009282 (void) FormatLocaleString(modulate,MagickPathExtent,"%.20g,%.20g,%.20g",
9283 geometry_info.rho,geometry_info.sigma,geometry_info.xi);
cristy4a3ce0a2013-08-03 20:06:59 +00009284 (void) ModulateImage(image,modulate,exception);
9285 break;
9286 }
9287 case 44: /* Negate */
9288 {
9289 if (attribute_flag[0] == 0)
9290 argument_list[0].integer_reference=0;
9291 if (attribute_flag[1] != 0)
9292 channel=(ChannelType) argument_list[1].integer_reference;
9293 channel_mask=SetImageChannelMask(image,channel);
9294 (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9295 MagickTrue : MagickFalse,exception);
9296 (void) SetImageChannelMask(image,channel_mask);
9297 break;
9298 }
9299 case 45: /* Normalize */
9300 {
9301 if (attribute_flag[0] != 0)
9302 channel=(ChannelType) argument_list[0].integer_reference;
9303 channel_mask=SetImageChannelMask(image,channel);
9304 NormalizeImage(image,exception);
9305 (void) SetImageChannelMask(image,channel_mask);
9306 break;
9307 }
9308 case 46: /* NumberColors */
9309 break;
9310 case 47: /* Opaque */
9311 {
9312 MagickBooleanType
9313 invert;
9314
9315 PixelInfo
9316 fill_color,
9317 target;
9318
9319 (void) QueryColorCompliance("none",AllCompliance,&target,
9320 exception);
9321 (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9322 exception);
9323 if (attribute_flag[0] != 0)
9324 (void) QueryColorCompliance(argument_list[0].string_reference,
9325 AllCompliance,&target,exception);
9326 if (attribute_flag[1] != 0)
9327 (void) QueryColorCompliance(argument_list[1].string_reference,
9328 AllCompliance,&fill_color,exception);
9329 if (attribute_flag[2] != 0)
9330 image->fuzz=StringToDoubleInterval(
9331 argument_list[2].string_reference,(double) QuantumRange+1.0);
9332 if (attribute_flag[3] != 0)
9333 channel=(ChannelType) argument_list[3].integer_reference;
9334 invert=MagickFalse;
9335 if (attribute_flag[4] != 0)
9336 invert=(MagickBooleanType) argument_list[4].integer_reference;
9337 channel_mask=SetImageChannelMask(image,channel);
9338 (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9339 (void) SetImageChannelMask(image,channel_mask);
9340 break;
9341 }
9342 case 48: /* Quantize */
9343 {
9344 QuantizeInfo
9345 *quantize_info;
9346
9347 quantize_info=AcquireQuantizeInfo(info->image_info);
9348 if (attribute_flag[0] != 0)
9349 quantize_info->number_colors=(size_t)
9350 argument_list[0].integer_reference;
9351 if (attribute_flag[1] != 0)
9352 quantize_info->tree_depth=(size_t)
9353 argument_list[1].integer_reference;
9354 if (attribute_flag[2] != 0)
9355 quantize_info->colorspace=(ColorspaceType)
9356 argument_list[2].integer_reference;
9357 if (attribute_flag[3] != 0)
cristy785c9342014-03-19 22:06:39 +00009358 quantize_info->dither_method=(DitherMethod)
9359 argument_list[3].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00009360 if (attribute_flag[4] != 0)
cristy71716d52014-03-19 10:11:11 +00009361 quantize_info->measure_error=
9362 argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
cristy4a3ce0a2013-08-03 20:06:59 +00009363 if (attribute_flag[6] != 0)
cristyd472dd82014-03-19 22:04:36 +00009364 (void) QueryColorCompliance(argument_list[6].string_reference,
cristyf7563392014-03-25 13:54:04 +00009365 AllCompliance,&image->transparent_color,exception);
cristy71716d52014-03-19 10:11:11 +00009366 if (attribute_flag[7] != 0)
cristy4a3ce0a2013-08-03 20:06:59 +00009367 quantize_info->dither_method=(DitherMethod)
cristy71716d52014-03-19 10:11:11 +00009368 argument_list[7].integer_reference;
9369 if (attribute_flag[5] && argument_list[5].integer_reference)
cristyf7563392014-03-25 13:54:04 +00009370 (void) QuantizeImages(quantize_info,image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009371 else
cristyf7563392014-03-25 13:54:04 +00009372 if ((image->storage_class == DirectClass) ||
9373 (image->colors > quantize_info->number_colors) ||
9374 (quantize_info->colorspace == GRAYColorspace))
9375 (void) QuantizeImage(quantize_info,image,exception);
9376 else
9377 CompressImageColormap(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009378 quantize_info=DestroyQuantizeInfo(quantize_info);
9379 break;
9380 }
9381 case 49: /* Raise */
9382 {
9383 if (attribute_flag[0] != 0)
9384 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9385 &geometry,exception);
9386 if (attribute_flag[1] != 0)
9387 geometry.width=argument_list[1].integer_reference;
9388 if (attribute_flag[2] != 0)
9389 geometry.height=argument_list[2].integer_reference;
9390 if (attribute_flag[3] == 0)
9391 argument_list[3].integer_reference=1;
9392 (void) RaiseImage(image,&geometry,
9393 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9394 exception);
9395 break;
9396 }
9397 case 50: /* Segment */
9398 {
9399 ColorspaceType
9400 colorspace;
9401
9402 double
9403 cluster_threshold,
9404 smoothing_threshold;
9405
9406 MagickBooleanType
9407 verbose;
9408
9409 cluster_threshold=1.0;
9410 smoothing_threshold=1.5;
9411 colorspace=sRGBColorspace;
9412 verbose=MagickFalse;
9413 if (attribute_flag[0] != 0)
9414 {
9415 flags=ParseGeometry(argument_list[0].string_reference,
9416 &geometry_info);
9417 cluster_threshold=geometry_info.rho;
9418 if (flags & SigmaValue)
9419 smoothing_threshold=geometry_info.sigma;
9420 }
9421 if (attribute_flag[1] != 0)
9422 cluster_threshold=argument_list[1].real_reference;
9423 if (attribute_flag[2] != 0)
9424 smoothing_threshold=argument_list[2].real_reference;
9425 if (attribute_flag[3] != 0)
9426 colorspace=(ColorspaceType) argument_list[3].integer_reference;
9427 if (attribute_flag[4] != 0)
9428 verbose=argument_list[4].integer_reference != 0 ?
9429 MagickTrue : MagickFalse;
9430 (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9431 smoothing_threshold,exception);
9432 break;
9433 }
9434 case 51: /* Signature */
9435 {
9436 (void) SignatureImage(image,exception);
9437 break;
9438 }
9439 case 52: /* Solarize */
9440 {
9441 geometry_info.rho=QuantumRange/2.0;
9442 if (attribute_flag[0] != 0)
9443 flags=ParseGeometry(argument_list[0].string_reference,
9444 &geometry_info);
9445 if (attribute_flag[1] != 0)
9446 geometry_info.rho=StringToDoubleInterval(
9447 argument_list[1].string_reference,(double) QuantumRange+1.0);
9448 (void) SolarizeImage(image,geometry_info.rho,exception);
9449 break;
9450 }
9451 case 53: /* Sync */
9452 {
9453 (void) SyncImage(image,exception);
9454 break;
9455 }
9456 case 54: /* Texture */
9457 {
9458 if (attribute_flag[0] == 0)
9459 break;
9460 TextureImage(image,argument_list[0].image_reference,exception);
9461 break;
9462 }
9463 case 55: /* Evalute */
9464 {
9465 MagickEvaluateOperator
9466 op;
9467
9468 op=SetEvaluateOperator;
9469 if (attribute_flag[0] == MagickFalse)
9470 argument_list[0].real_reference=0.0;
9471 if (attribute_flag[1] != MagickFalse)
9472 op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9473 if (attribute_flag[2] != MagickFalse)
9474 channel=(ChannelType) argument_list[2].integer_reference;
9475 channel_mask=SetImageChannelMask(image,channel);
9476 (void) EvaluateImage(image,op,argument_list[0].real_reference,
9477 exception);
9478 (void) SetImageChannelMask(image,channel_mask);
9479 break;
9480 }
9481 case 56: /* Transparent */
9482 {
9483 double
9484 opacity;
9485
9486 MagickBooleanType
9487 invert;
9488
9489 PixelInfo
9490 target;
9491
9492 (void) QueryColorCompliance("none",AllCompliance,&target,
9493 exception);
9494 if (attribute_flag[0] != 0)
9495 (void) QueryColorCompliance(argument_list[0].string_reference,
9496 AllCompliance,&target,exception);
9497 opacity=TransparentAlpha;
9498 if (attribute_flag[1] != 0)
9499 opacity=StringToDoubleInterval(argument_list[1].string_reference,
9500 (double) QuantumRange+1.0);
9501 if (attribute_flag[2] != 0)
9502 image->fuzz=StringToDoubleInterval(
9503 argument_list[2].string_reference,(double) QuantumRange+1.0);
9504 if (attribute_flag[3] == 0)
9505 argument_list[3].integer_reference=0;
9506 invert=MagickFalse;
9507 if (attribute_flag[3] != 0)
9508 invert=(MagickBooleanType) argument_list[3].integer_reference;
9509 (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9510 invert,exception);
9511 break;
9512 }
9513 case 57: /* Threshold */
9514 {
9515 double
9516 threshold;
9517
9518 if (attribute_flag[0] == 0)
9519 argument_list[0].string_reference="50%";
9520 if (attribute_flag[1] != 0)
9521 channel=(ChannelType) argument_list[1].integer_reference;
9522 threshold=StringToDoubleInterval(argument_list[0].string_reference,
9523 (double) QuantumRange+1.0);
9524 channel_mask=SetImageChannelMask(image,channel);
9525 (void) BilevelImage(image,threshold,exception);
9526 (void) SetImageChannelMask(image,channel_mask);
9527 break;
9528 }
9529 case 58: /* Charcoal */
9530 {
9531 if (attribute_flag[0] != 0)
9532 {
9533 flags=ParseGeometry(argument_list[0].string_reference,
9534 &geometry_info);
9535 if ((flags & SigmaValue) == 0)
9536 geometry_info.sigma=1.0;
9537 }
9538 if (attribute_flag[1] != 0)
9539 geometry_info.rho=argument_list[1].real_reference;
9540 if (attribute_flag[2] != 0)
9541 geometry_info.sigma=argument_list[2].real_reference;
9542 image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9543 exception);
9544 break;
9545 }
9546 case 59: /* Trim */
9547 {
9548 if (attribute_flag[0] != 0)
9549 image->fuzz=StringToDoubleInterval(
9550 argument_list[0].string_reference,(double) QuantumRange+1.0);
9551 image=TrimImage(image,exception);
9552 break;
9553 }
9554 case 60: /* Wave */
9555 {
9556 PixelInterpolateMethod
9557 method;
9558
9559 if (attribute_flag[0] != 0)
9560 {
9561 flags=ParseGeometry(argument_list[0].string_reference,
9562 &geometry_info);
9563 if ((flags & SigmaValue) == 0)
9564 geometry_info.sigma=1.0;
9565 }
9566 if (attribute_flag[1] != 0)
9567 geometry_info.rho=argument_list[1].real_reference;
9568 if (attribute_flag[2] != 0)
9569 geometry_info.sigma=argument_list[2].real_reference;
9570 method=UndefinedInterpolatePixel;
9571 if (attribute_flag[3] != 0)
9572 method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9573 image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9574 method,exception);
9575 break;
9576 }
9577 case 61: /* Separate */
9578 {
9579 if (attribute_flag[0] != 0)
9580 channel=(ChannelType) argument_list[0].integer_reference;
9581 image=SeparateImage(image,channel,exception);
9582 break;
9583 }
9584 case 63: /* Stereo */
9585 {
9586 if (attribute_flag[0] == 0)
9587 {
9588 ThrowPerlException(exception,OptionError,"StereoImageRequired",
9589 PackageName);
9590 goto PerlException;
9591 }
9592 if (attribute_flag[1] != 0)
9593 geometry.x=argument_list[1].integer_reference;
9594 if (attribute_flag[2] != 0)
9595 geometry.y=argument_list[2].integer_reference;
9596 image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9597 geometry.x,geometry.y,exception);
9598 break;
9599 }
9600 case 64: /* Stegano */
9601 {
9602 if (attribute_flag[0] == 0)
9603 {
9604 ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9605 PackageName);
9606 goto PerlException;
9607 }
9608 if (attribute_flag[1] == 0)
9609 argument_list[1].integer_reference=0;
9610 image->offset=argument_list[1].integer_reference;
9611 image=SteganoImage(image,argument_list[0].image_reference,exception);
9612 break;
9613 }
9614 case 65: /* Deconstruct */
9615 {
9616 image=CompareImagesLayers(image,CompareAnyLayer,exception);
9617 break;
9618 }
9619 case 66: /* GaussianBlur */
9620 {
9621 if (attribute_flag[0] != 0)
9622 {
9623 flags=ParseGeometry(argument_list[0].string_reference,
9624 &geometry_info);
9625 if ((flags & SigmaValue) == 0)
9626 geometry_info.sigma=1.0;
9627 }
9628 if (attribute_flag[1] != 0)
9629 geometry_info.rho=argument_list[1].real_reference;
9630 if (attribute_flag[2] != 0)
9631 geometry_info.sigma=argument_list[2].real_reference;
9632 if (attribute_flag[3] != 0)
9633 channel=(ChannelType) argument_list[3].integer_reference;
9634 channel_mask=SetImageChannelMask(image,channel);
9635 image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9636 exception);
9637 if (image != (Image *) NULL)
9638 (void) SetImageChannelMask(image,channel_mask);
9639 break;
9640 }
9641 case 67: /* Convolve */
9642 {
9643 KernelInfo
9644 *kernel;
9645
9646 kernel=(KernelInfo *) NULL;
9647 if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9648 break;
9649 if (attribute_flag[0] != 0)
9650 {
9651 AV
9652 *av;
9653
9654 size_t
9655 order;
9656
cristy2c57b742014-10-31 00:40:34 +00009657 kernel=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009658 if (kernel == (KernelInfo *) NULL)
9659 break;
9660 av=(AV *) argument_list[0].array_reference;
9661 order=(size_t) sqrt(av_len(av)+1);
9662 kernel->width=order;
9663 kernel->height=order;
9664 kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9665 order*sizeof(*kernel->values));
9666 if (kernel->values == (MagickRealType *) NULL)
9667 {
9668 kernel=DestroyKernelInfo(kernel);
9669 ThrowPerlException(exception,ResourceLimitFatalError,
9670 "MemoryAllocationFailed",PackageName);
9671 goto PerlException;
9672 }
9673 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9674 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9675 for ( ; j < (ssize_t) (order*order); j++)
9676 kernel->values[j]=0.0;
9677 }
9678 if (attribute_flag[1] != 0)
9679 channel=(ChannelType) argument_list[1].integer_reference;
9680 if (attribute_flag[2] != 0)
Cristyc4ff6bd2017-07-05 21:00:11 -04009681 SetImageArtifact(image,"convolve:bias",
cristy4a3ce0a2013-08-03 20:06:59 +00009682 argument_list[2].string_reference);
9683 if (attribute_flag[3] != 0)
9684 {
cristy2c57b742014-10-31 00:40:34 +00009685 kernel=AcquireKernelInfo(argument_list[3].string_reference,
9686 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009687 if (kernel == (KernelInfo *) NULL)
9688 break;
9689 }
9690 channel_mask=SetImageChannelMask(image,channel);
9691 image=ConvolveImage(image,kernel,exception);
9692 if (image != (Image *) NULL)
9693 (void) SetImageChannelMask(image,channel_mask);
9694 kernel=DestroyKernelInfo(kernel);
9695 break;
9696 }
9697 case 68: /* Profile */
9698 {
9699 const char
9700 *name;
9701
9702 Image
9703 *profile_image;
9704
9705 ImageInfo
9706 *profile_info;
9707
9708 StringInfo
9709 *profile;
9710
9711 name="*";
9712 if (attribute_flag[0] != 0)
9713 name=argument_list[0].string_reference;
9714 if (attribute_flag[2] != 0)
9715 image->rendering_intent=(RenderingIntent)
9716 argument_list[2].integer_reference;
9717 if (attribute_flag[3] != 0)
9718 image->black_point_compensation=
9719 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9720 if (attribute_flag[1] != 0)
9721 {
9722 if (argument_list[1].length == 0)
9723 {
9724 /*
9725 Remove a profile from the image.
9726 */
9727 (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9728 exception);
9729 break;
9730 }
9731 /*
9732 Associate user supplied profile with the image.
9733 */
9734 profile=AcquireStringInfo(argument_list[1].length);
9735 SetStringInfoDatum(profile,(const unsigned char *)
9736 argument_list[1].string_reference);
9737 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9738 (size_t) GetStringInfoLength(profile),exception);
9739 profile=DestroyStringInfo(profile);
9740 break;
9741 }
9742 /*
9743 Associate a profile with the image.
9744 */
9745 profile_info=CloneImageInfo(info ? info->image_info :
9746 (ImageInfo *) NULL);
9747 profile_image=ReadImages(profile_info,name,exception);
9748 if (profile_image == (Image *) NULL)
9749 break;
9750 ResetImageProfileIterator(profile_image);
9751 name=GetNextImageProfile(profile_image);
9752 while (name != (const char *) NULL)
9753 {
9754 const StringInfo
9755 *profile;
9756
9757 profile=GetImageProfile(profile_image,name);
9758 if (profile != (const StringInfo *) NULL)
9759 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9760 (size_t) GetStringInfoLength(profile),exception);
9761 name=GetNextImageProfile(profile_image);
9762 }
9763 profile_image=DestroyImage(profile_image);
9764 profile_info=DestroyImageInfo(profile_info);
9765 break;
9766 }
9767 case 69: /* UnsharpMask */
9768 {
9769 if (attribute_flag[0] != 0)
9770 {
9771 flags=ParseGeometry(argument_list[0].string_reference,
9772 &geometry_info);
9773 if ((flags & SigmaValue) == 0)
9774 geometry_info.sigma=1.0;
9775 if ((flags & XiValue) == 0)
9776 geometry_info.xi=1.0;
9777 if ((flags & PsiValue) == 0)
9778 geometry_info.psi=0.5;
9779 }
9780 if (attribute_flag[1] != 0)
9781 geometry_info.rho=argument_list[1].real_reference;
9782 if (attribute_flag[2] != 0)
9783 geometry_info.sigma=argument_list[2].real_reference;
9784 if (attribute_flag[3] != 0)
9785 geometry_info.xi=argument_list[3].real_reference;
9786 if (attribute_flag[4] != 0)
9787 geometry_info.psi=argument_list[4].real_reference;
9788 if (attribute_flag[5] != 0)
9789 channel=(ChannelType) argument_list[5].integer_reference;
9790 channel_mask=SetImageChannelMask(image,channel);
9791 image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9792 geometry_info.xi,geometry_info.psi,exception);
9793 if (image != (Image *) NULL)
9794 (void) SetImageChannelMask(image,channel_mask);
9795 break;
9796 }
9797 case 70: /* MotionBlur */
9798 {
9799 if (attribute_flag[0] != 0)
9800 {
9801 flags=ParseGeometry(argument_list[0].string_reference,
9802 &geometry_info);
9803 if ((flags & SigmaValue) == 0)
9804 geometry_info.sigma=1.0;
9805 if ((flags & XiValue) == 0)
9806 geometry_info.xi=1.0;
9807 }
9808 if (attribute_flag[1] != 0)
9809 geometry_info.rho=argument_list[1].real_reference;
9810 if (attribute_flag[2] != 0)
9811 geometry_info.sigma=argument_list[2].real_reference;
9812 if (attribute_flag[3] != 0)
9813 geometry_info.xi=argument_list[3].real_reference;
9814 if (attribute_flag[4] != 0)
9815 channel=(ChannelType) argument_list[4].integer_reference;
9816 channel_mask=SetImageChannelMask(image,channel);
9817 image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9818 geometry_info.xi,exception);
9819 if (image != (Image *) NULL)
9820 (void) SetImageChannelMask(image,channel_mask);
9821 break;
9822 }
9823 case 71: /* OrderedDither */
9824 {
9825 if (attribute_flag[0] == 0)
9826 argument_list[0].string_reference="o8x8";
9827 if (attribute_flag[1] != 0)
9828 channel=(ChannelType) argument_list[1].integer_reference;
9829 channel_mask=SetImageChannelMask(image,channel);
Cristy6b93c072016-02-04 07:45:48 -05009830 (void) OrderedDitherImage(image,argument_list[0].string_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009831 exception);
9832 (void) SetImageChannelMask(image,channel_mask);
9833 break;
9834 }
9835 case 72: /* Shave */
9836 {
9837 if (attribute_flag[0] != 0)
9838 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9839 &geometry,exception);
9840 if (attribute_flag[1] != 0)
9841 geometry.width=argument_list[1].integer_reference;
9842 if (attribute_flag[2] != 0)
9843 geometry.height=argument_list[2].integer_reference;
9844 image=ShaveImage(image,&geometry,exception);
9845 break;
9846 }
9847 case 73: /* Level */
9848 {
9849 double
9850 black_point,
9851 gamma,
9852 white_point;
9853
9854 black_point=0.0;
9855 white_point=(double) image->columns*image->rows;
9856 gamma=1.0;
9857 if (attribute_flag[0] != 0)
9858 {
9859 flags=ParseGeometry(argument_list[0].string_reference,
9860 &geometry_info);
9861 black_point=geometry_info.rho;
9862 if ((flags & SigmaValue) != 0)
9863 white_point=geometry_info.sigma;
9864 if ((flags & XiValue) != 0)
9865 gamma=geometry_info.xi;
9866 if ((flags & PercentValue) != 0)
9867 {
9868 black_point*=(double) (QuantumRange/100.0);
9869 white_point*=(double) (QuantumRange/100.0);
9870 }
9871 if ((flags & SigmaValue) == 0)
9872 white_point=(double) QuantumRange-black_point;
9873 }
9874 if (attribute_flag[1] != 0)
9875 black_point=argument_list[1].real_reference;
9876 if (attribute_flag[2] != 0)
9877 white_point=argument_list[2].real_reference;
9878 if (attribute_flag[3] != 0)
9879 gamma=argument_list[3].real_reference;
9880 if (attribute_flag[4] != 0)
9881 channel=(ChannelType) argument_list[4].integer_reference;
9882 if (attribute_flag[5] != 0)
9883 {
9884 argument_list[0].real_reference=argument_list[5].real_reference;
9885 attribute_flag[0]=attribute_flag[5];
9886 }
9887 channel_mask=SetImageChannelMask(image,channel);
9888 (void) LevelImage(image,black_point,white_point,gamma,exception);
9889 (void) SetImageChannelMask(image,channel_mask);
9890 break;
9891 }
9892 case 74: /* Clip */
9893 {
9894 if (attribute_flag[0] == 0)
9895 argument_list[0].string_reference="#1";
9896 if (attribute_flag[1] == 0)
9897 argument_list[1].integer_reference=MagickTrue;
9898 (void) ClipImagePath(image,argument_list[0].string_reference,
9899 argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9900 exception);
9901 break;
9902 }
9903 case 75: /* AffineTransform */
9904 {
9905 DrawInfo
9906 *draw_info;
9907
9908 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9909 (DrawInfo *) NULL);
9910 if (attribute_flag[0] != 0)
9911 {
9912 AV
9913 *av;
9914
9915 av=(AV *) argument_list[0].array_reference;
9916 if ((av_len(av) != 3) && (av_len(av) != 5))
9917 {
9918 ThrowPerlException(exception,OptionError,
9919 "affine matrix must have 4 or 6 elements",PackageName);
9920 goto PerlException;
9921 }
9922 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9923 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9924 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9925 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9926 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9927 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9928 {
9929 ThrowPerlException(exception,OptionError,
9930 "affine matrix is singular",PackageName);
9931 goto PerlException;
9932 }
9933 if (av_len(av) == 5)
9934 {
9935 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9936 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9937 }
9938 }
9939 for (j=1; j < 6; j++)
9940 {
9941 if (attribute_flag[j] == 0)
9942 continue;
9943 value=argument_list[j].string_reference;
9944 angle=argument_list[j].real_reference;
9945 current=draw_info->affine;
9946 GetAffineMatrix(&affine);
9947 switch (j)
9948 {
9949 case 1:
9950 {
9951 /*
9952 Translate.
9953 */
9954 flags=ParseGeometry(value,&geometry_info);
9955 affine.tx=geometry_info.xi;
9956 affine.ty=geometry_info.psi;
9957 if ((flags & PsiValue) == 0)
9958 affine.ty=affine.tx;
9959 break;
9960 }
9961 case 2:
9962 {
9963 /*
9964 Scale.
9965 */
9966 flags=ParseGeometry(value,&geometry_info);
9967 affine.sx=geometry_info.rho;
9968 affine.sy=geometry_info.sigma;
9969 if ((flags & SigmaValue) == 0)
9970 affine.sy=affine.sx;
9971 break;
9972 }
9973 case 3:
9974 {
9975 /*
9976 Rotate.
9977 */
9978 if (angle == 0.0)
9979 break;
9980 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9981 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9982 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9983 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9984 break;
9985 }
9986 case 4:
9987 {
9988 /*
9989 SkewX.
9990 */
9991 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9992 break;
9993 }
9994 case 5:
9995 {
9996 /*
9997 SkewY.
9998 */
9999 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
10000 break;
10001 }
10002 }
10003 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
10004 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
10005 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
10006 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
10007 draw_info->affine.tx=
10008 current.sx*affine.tx+current.ry*affine.ty+current.tx;
10009 draw_info->affine.ty=
10010 current.rx*affine.tx+current.sy*affine.ty+current.ty;
10011 }
10012 if (attribute_flag[6] != 0)
10013 image->interpolate=(PixelInterpolateMethod)
10014 argument_list[6].integer_reference;
10015 if (attribute_flag[7] != 0)
10016 QueryColorCompliance(argument_list[7].string_reference,
10017 AllCompliance,&image->background_color,exception);
10018 image=AffineTransformImage(image,&draw_info->affine,exception);
10019 draw_info=DestroyDrawInfo(draw_info);
10020 break;
10021 }
10022 case 76: /* Difference */
10023 {
10024 if (attribute_flag[0] == 0)
10025 {
10026 ThrowPerlException(exception,OptionError,
10027 "ReferenceImageRequired",PackageName);
10028 goto PerlException;
10029 }
10030 if (attribute_flag[1] != 0)
10031 image->fuzz=StringToDoubleInterval(
10032 argument_list[1].string_reference,(double) QuantumRange+1.0);
Cristyf2479812015-12-12 12:17:43 -050010033 (void) SetImageColorMetric(image,argument_list[0].image_reference,
cristy4a3ce0a2013-08-03 20:06:59 +000010034 exception);
10035 break;
10036 }
10037 case 77: /* AdaptiveThreshold */
10038 {
10039 if (attribute_flag[0] != 0)
10040 {
10041 flags=ParseGeometry(argument_list[0].string_reference,
10042 &geometry_info);
10043 if ((flags & PercentValue) != 0)
10044 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10045 }
10046 if (attribute_flag[1] != 0)
10047 geometry_info.rho=argument_list[1].integer_reference;
10048 if (attribute_flag[2] != 0)
10049 geometry_info.sigma=argument_list[2].integer_reference;
10050 if (attribute_flag[3] != 0)
10051 geometry_info.xi=argument_list[3].integer_reference;;
10052 image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
10053 (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
10054 break;
10055 }
10056 case 78: /* Resample */
10057 {
10058 size_t
10059 height,
10060 width;
10061
10062 if (attribute_flag[0] != 0)
10063 {
10064 flags=ParseGeometry(argument_list[0].string_reference,
10065 &geometry_info);
10066 if ((flags & SigmaValue) == 0)
10067 geometry_info.sigma=geometry_info.rho;
10068 }
10069 if (attribute_flag[1] != 0)
10070 geometry_info.rho=argument_list[1].real_reference;
10071 if (attribute_flag[2] != 0)
10072 geometry_info.sigma=argument_list[2].real_reference;
10073 if (attribute_flag[3] == 0)
10074 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10075 if (attribute_flag[4] == 0)
10076 SetImageArtifact(image,"filter:support",
10077 argument_list[4].string_reference);
10078 width=(size_t) (geometry_info.rho*image->columns/
10079 (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10080 height=(size_t) (geometry_info.sigma*image->rows/
10081 (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
Cristy8645e042016-02-03 16:35:29 -050010082 image=ResizeImage(image,width,height,(FilterType)
cristy4a3ce0a2013-08-03 20:06:59 +000010083 argument_list[3].integer_reference,exception);
10084 if (image != (Image *) NULL)
10085 {
10086 image->resolution.x=geometry_info.rho;
10087 image->resolution.y=geometry_info.sigma;
10088 }
10089 break;
10090 }
10091 case 79: /* Describe */
10092 {
10093 if (attribute_flag[0] == 0)
10094 argument_list[0].file_reference=(FILE *) NULL;
10095 if (attribute_flag[1] != 0)
10096 (void) SetImageArtifact(image,"identify:features",
10097 argument_list[1].string_reference);
10098 (void) IdentifyImage(image,argument_list[0].file_reference,
10099 MagickTrue,exception);
10100 break;
10101 }
10102 case 80: /* BlackThreshold */
10103 {
10104 if (attribute_flag[0] == 0)
10105 argument_list[0].string_reference="50%";
10106 if (attribute_flag[2] != 0)
10107 channel=(ChannelType) argument_list[2].integer_reference;
10108 channel_mask=SetImageChannelMask(image,channel);
10109 BlackThresholdImage(image,argument_list[0].string_reference,
10110 exception);
10111 (void) SetImageChannelMask(image,channel_mask);
10112 break;
10113 }
10114 case 81: /* WhiteThreshold */
10115 {
10116 if (attribute_flag[0] == 0)
10117 argument_list[0].string_reference="50%";
10118 if (attribute_flag[2] != 0)
10119 channel=(ChannelType) argument_list[2].integer_reference;
10120 channel_mask=SetImageChannelMask(image,channel);
10121 WhiteThresholdImage(image,argument_list[0].string_reference,
10122 exception);
10123 (void) SetImageChannelMask(image,channel_mask);
10124 break;
10125 }
cristy60c73c02014-03-25 12:09:58 +000010126 case 82: /* RotationalBlur */
cristy4a3ce0a2013-08-03 20:06:59 +000010127 {
10128 if (attribute_flag[0] != 0)
10129 {
10130 flags=ParseGeometry(argument_list[0].string_reference,
10131 &geometry_info);
10132 }
10133 if (attribute_flag[1] != 0)
10134 geometry_info.rho=argument_list[1].real_reference;
10135 if (attribute_flag[2] != 0)
10136 channel=(ChannelType) argument_list[2].integer_reference;
10137 channel_mask=SetImageChannelMask(image,channel);
cristy49d4d222014-03-16 00:37:58 +000010138 image=RotationalBlurImage(image,geometry_info.rho,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010139 if (image != (Image *) NULL)
10140 (void) SetImageChannelMask(image,channel_mask);
10141 break;
10142 }
10143 case 83: /* Thumbnail */
10144 {
10145 if (attribute_flag[0] != 0)
10146 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10147 &geometry,exception);
10148 if (attribute_flag[1] != 0)
10149 geometry.width=argument_list[1].integer_reference;
10150 if (attribute_flag[2] != 0)
10151 geometry.height=argument_list[2].integer_reference;
10152 image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10153 break;
10154 }
10155 case 84: /* Strip */
10156 {
10157 (void) StripImage(image,exception);
10158 break;
10159 }
10160 case 85: /* Tint */
10161 {
10162 PixelInfo
10163 tint;
10164
10165 GetPixelInfo(image,&tint);
10166 if (attribute_flag[0] != 0)
10167 (void) QueryColorCompliance(argument_list[0].string_reference,
10168 AllCompliance,&tint,exception);
10169 if (attribute_flag[1] == 0)
10170 argument_list[1].string_reference="100";
10171 image=TintImage(image,argument_list[1].string_reference,&tint,
10172 exception);
10173 break;
10174 }
10175 case 86: /* Channel */
10176 {
10177 if (attribute_flag[0] != 0)
10178 channel=(ChannelType) argument_list[0].integer_reference;
10179 image=SeparateImage(image,channel,exception);
10180 break;
10181 }
10182 case 87: /* Splice */
10183 {
cristy260bd762014-08-15 12:46:34 +000010184 if (attribute_flag[7] != 0)
10185 image->gravity=(GravityType) argument_list[7].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010186 if (attribute_flag[0] != 0)
10187 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10188 &geometry,exception);
10189 if (attribute_flag[1] != 0)
10190 geometry.width=argument_list[1].integer_reference;
10191 if (attribute_flag[2] != 0)
10192 geometry.height=argument_list[2].integer_reference;
10193 if (attribute_flag[3] != 0)
10194 geometry.x=argument_list[3].integer_reference;
10195 if (attribute_flag[4] != 0)
10196 geometry.y=argument_list[4].integer_reference;
10197 if (attribute_flag[5] != 0)
10198 image->fuzz=StringToDoubleInterval(
10199 argument_list[5].string_reference,(double) QuantumRange+1.0);
10200 if (attribute_flag[6] != 0)
10201 (void) QueryColorCompliance(argument_list[6].string_reference,
10202 AllCompliance,&image->background_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010203 image=SpliceImage(image,&geometry,exception);
10204 break;
10205 }
10206 case 88: /* Posterize */
10207 {
10208 if (attribute_flag[0] == 0)
10209 argument_list[0].integer_reference=3;
10210 if (attribute_flag[1] == 0)
10211 argument_list[1].integer_reference=0;
10212 (void) PosterizeImage(image,argument_list[0].integer_reference,
10213 argument_list[1].integer_reference ? RiemersmaDitherMethod :
10214 NoDitherMethod,exception);
10215 break;
10216 }
10217 case 89: /* Shadow */
10218 {
10219 if (attribute_flag[0] != 0)
10220 {
10221 flags=ParseGeometry(argument_list[0].string_reference,
10222 &geometry_info);
10223 if ((flags & SigmaValue) == 0)
10224 geometry_info.sigma=1.0;
10225 if ((flags & XiValue) == 0)
10226 geometry_info.xi=4.0;
10227 if ((flags & PsiValue) == 0)
10228 geometry_info.psi=4.0;
10229 }
10230 if (attribute_flag[1] != 0)
10231 geometry_info.rho=argument_list[1].real_reference;
10232 if (attribute_flag[2] != 0)
10233 geometry_info.sigma=argument_list[2].real_reference;
10234 if (attribute_flag[3] != 0)
10235 geometry_info.xi=argument_list[3].integer_reference;
10236 if (attribute_flag[4] != 0)
10237 geometry_info.psi=argument_list[4].integer_reference;
10238 image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10239 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10240 ceil(geometry_info.psi-0.5),exception);
10241 break;
10242 }
10243 case 90: /* Identify */
10244 {
10245 if (attribute_flag[0] == 0)
10246 argument_list[0].file_reference=(FILE *) NULL;
10247 if (attribute_flag[1] != 0)
10248 (void) SetImageArtifact(image,"identify:features",
10249 argument_list[1].string_reference);
10250 if ((attribute_flag[2] != 0) &&
10251 (argument_list[2].integer_reference != 0))
10252 (void) SetImageArtifact(image,"identify:unique","true");
10253 (void) IdentifyImage(image,argument_list[0].file_reference,
10254 MagickTrue,exception);
10255 break;
10256 }
10257 case 91: /* SepiaTone */
10258 {
10259 if (attribute_flag[0] == 0)
10260 argument_list[0].real_reference=80.0*QuantumRange/100.0;
10261 image=SepiaToneImage(image,argument_list[0].real_reference,
10262 exception);
10263 break;
10264 }
10265 case 92: /* SigmoidalContrast */
10266 {
10267 MagickBooleanType
10268 sharpen;
10269
10270 if (attribute_flag[0] != 0)
10271 {
10272 flags=ParseGeometry(argument_list[0].string_reference,
10273 &geometry_info);
10274 if ((flags & SigmaValue) == 0)
10275 geometry_info.sigma=QuantumRange/2.0;
10276 if ((flags & PercentValue) != 0)
10277 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10278 }
10279 if (attribute_flag[1] != 0)
10280 geometry_info.rho=argument_list[1].real_reference;
10281 if (attribute_flag[2] != 0)
10282 geometry_info.sigma=argument_list[2].real_reference;
10283 if (attribute_flag[3] != 0)
10284 channel=(ChannelType) argument_list[3].integer_reference;
10285 sharpen=MagickTrue;
10286 if (attribute_flag[4] != 0)
10287 sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10288 MagickFalse;
10289 channel_mask=SetImageChannelMask(image,channel);
10290 (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10291 geometry_info.sigma,exception);
10292 (void) SetImageChannelMask(image,channel_mask);
10293 break;
10294 }
10295 case 93: /* Extent */
10296 {
10297 if (attribute_flag[7] != 0)
10298 image->gravity=(GravityType) argument_list[7].integer_reference;
10299 if (attribute_flag[0] != 0)
10300 {
10301 int
10302 flags;
10303
10304 flags=ParseGravityGeometry(image,
10305 argument_list[0].string_reference,&geometry,exception);
10306 (void) flags;
10307 if (geometry.width == 0)
10308 geometry.width=image->columns;
10309 if (geometry.height == 0)
10310 geometry.height=image->rows;
10311 }
10312 if (attribute_flag[1] != 0)
10313 geometry.width=argument_list[1].integer_reference;
10314 if (attribute_flag[2] != 0)
10315 geometry.height=argument_list[2].integer_reference;
10316 if (attribute_flag[3] != 0)
10317 geometry.x=argument_list[3].integer_reference;
10318 if (attribute_flag[4] != 0)
10319 geometry.y=argument_list[4].integer_reference;
10320 if (attribute_flag[5] != 0)
10321 image->fuzz=StringToDoubleInterval(
10322 argument_list[5].string_reference,(double) QuantumRange+1.0);
10323 if (attribute_flag[6] != 0)
10324 (void) QueryColorCompliance(argument_list[6].string_reference,
10325 AllCompliance,&image->background_color,exception);
10326 image=ExtentImage(image,&geometry,exception);
10327 break;
10328 }
10329 case 94: /* Vignette */
10330 {
10331 if (attribute_flag[0] != 0)
10332 {
10333 flags=ParseGeometry(argument_list[0].string_reference,
10334 &geometry_info);
10335 if ((flags & SigmaValue) == 0)
10336 geometry_info.sigma=1.0;
10337 if ((flags & XiValue) == 0)
10338 geometry_info.xi=0.1*image->columns;
10339 if ((flags & PsiValue) == 0)
10340 geometry_info.psi=0.1*image->rows;
10341 }
10342 if (attribute_flag[1] != 0)
10343 geometry_info.rho=argument_list[1].real_reference;
10344 if (attribute_flag[2] != 0)
10345 geometry_info.sigma=argument_list[2].real_reference;
10346 if (attribute_flag[3] != 0)
10347 geometry_info.xi=argument_list[3].integer_reference;
10348 if (attribute_flag[4] != 0)
10349 geometry_info.psi=argument_list[4].integer_reference;
10350 if (attribute_flag[5] != 0)
10351 (void) QueryColorCompliance(argument_list[5].string_reference,
10352 AllCompliance,&image->background_color,exception);
10353 image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10354 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10355 ceil(geometry_info.psi-0.5),exception);
10356 break;
10357 }
10358 case 95: /* ContrastStretch */
10359 {
10360 double
10361 black_point,
10362 white_point;
10363
10364 black_point=0.0;
10365 white_point=(double) image->columns*image->rows;
10366 if (attribute_flag[0] != 0)
10367 {
10368 flags=ParseGeometry(argument_list[0].string_reference,
10369 &geometry_info);
10370 black_point=geometry_info.rho;
10371 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10372 black_point;
10373 if ((flags & PercentValue) != 0)
10374 {
10375 black_point*=(double) image->columns*image->rows/100.0;
10376 white_point*=(double) image->columns*image->rows/100.0;
10377 }
10378 white_point=(double) image->columns*image->rows-
10379 white_point;
10380 }
10381 if (attribute_flag[1] != 0)
10382 black_point=argument_list[1].real_reference;
10383 if (attribute_flag[2] != 0)
10384 white_point=argument_list[2].real_reference;
10385 if (attribute_flag[4] != 0)
10386 channel=(ChannelType) argument_list[4].integer_reference;
10387 channel_mask=SetImageChannelMask(image,channel);
10388 (void) ContrastStretchImage(image,black_point,white_point,exception);
10389 (void) SetImageChannelMask(image,channel_mask);
10390 break;
10391 }
10392 case 96: /* Sans0 */
10393 {
10394 break;
10395 }
10396 case 97: /* Sans1 */
10397 {
10398 break;
10399 }
10400 case 98: /* AdaptiveSharpen */
10401 {
10402 if (attribute_flag[0] != 0)
10403 {
10404 flags=ParseGeometry(argument_list[0].string_reference,
10405 &geometry_info);
10406 if ((flags & SigmaValue) == 0)
10407 geometry_info.sigma=1.0;
10408 if ((flags & XiValue) == 0)
10409 geometry_info.xi=0.0;
10410 }
10411 if (attribute_flag[1] != 0)
10412 geometry_info.rho=argument_list[1].real_reference;
10413 if (attribute_flag[2] != 0)
10414 geometry_info.sigma=argument_list[2].real_reference;
10415 if (attribute_flag[3] != 0)
10416 geometry_info.xi=argument_list[3].real_reference;
10417 if (attribute_flag[4] != 0)
10418 channel=(ChannelType) argument_list[4].integer_reference;
10419 channel_mask=SetImageChannelMask(image,channel);
10420 image=AdaptiveSharpenImage(image,geometry_info.rho,
10421 geometry_info.sigma,exception);
10422 if (image != (Image *) NULL)
10423 (void) SetImageChannelMask(image,channel_mask);
10424 break;
10425 }
10426 case 99: /* Transpose */
10427 {
10428 image=TransposeImage(image,exception);
10429 break;
10430 }
10431 case 100: /* Tranverse */
10432 {
10433 image=TransverseImage(image,exception);
10434 break;
10435 }
10436 case 101: /* AutoOrient */
10437 {
10438 image=AutoOrientImage(image,image->orientation,exception);
10439 break;
10440 }
10441 case 102: /* AdaptiveBlur */
10442 {
10443 if (attribute_flag[0] != 0)
10444 {
10445 flags=ParseGeometry(argument_list[0].string_reference,
10446 &geometry_info);
10447 if ((flags & SigmaValue) == 0)
10448 geometry_info.sigma=1.0;
10449 if ((flags & XiValue) == 0)
10450 geometry_info.xi=0.0;
10451 }
10452 if (attribute_flag[1] != 0)
10453 geometry_info.rho=argument_list[1].real_reference;
10454 if (attribute_flag[2] != 0)
10455 geometry_info.sigma=argument_list[2].real_reference;
10456 if (attribute_flag[3] != 0)
10457 channel=(ChannelType) argument_list[3].integer_reference;
10458 channel_mask=SetImageChannelMask(image,channel);
10459 image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10460 exception);
10461 if (image != (Image *) NULL)
10462 (void) SetImageChannelMask(image,channel_mask);
10463 break;
10464 }
10465 case 103: /* Sketch */
10466 {
10467 if (attribute_flag[0] != 0)
10468 {
10469 flags=ParseGeometry(argument_list[0].string_reference,
10470 &geometry_info);
10471 if ((flags & SigmaValue) == 0)
10472 geometry_info.sigma=1.0;
10473 if ((flags & XiValue) == 0)
10474 geometry_info.xi=1.0;
10475 }
10476 if (attribute_flag[1] != 0)
10477 geometry_info.rho=argument_list[1].real_reference;
10478 if (attribute_flag[2] != 0)
10479 geometry_info.sigma=argument_list[2].real_reference;
10480 if (attribute_flag[3] != 0)
10481 geometry_info.xi=argument_list[3].real_reference;
10482 image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10483 geometry_info.xi,exception);
10484 break;
10485 }
10486 case 104: /* UniqueColors */
10487 {
10488 image=UniqueImageColors(image,exception);
10489 break;
10490 }
10491 case 105: /* AdaptiveResize */
10492 {
10493 if (attribute_flag[0] != 0)
10494 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10495 &geometry,exception);
10496 if (attribute_flag[1] != 0)
10497 geometry.width=argument_list[1].integer_reference;
10498 if (attribute_flag[2] != 0)
10499 geometry.height=argument_list[2].integer_reference;
10500 if (attribute_flag[3] != 0)
Cristy8645e042016-02-03 16:35:29 -050010501 image->filter=(FilterType) argument_list[4].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010502 if (attribute_flag[4] != 0)
10503 SetImageArtifact(image,"filter:support",
10504 argument_list[4].string_reference);
10505 image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10506 exception);
10507 break;
10508 }
10509 case 106: /* ClipMask */
10510 {
10511 Image
10512 *mask_image;
10513
10514 if (attribute_flag[0] == 0)
10515 {
10516 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10517 PackageName);
10518 goto PerlException;
10519 }
10520 mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10521 exception);
cristy1f7ffb72015-07-29 11:07:03 +000010522 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010523 mask_image=DestroyImage(mask_image);
10524 break;
10525 }
10526 case 107: /* LinearStretch */
10527 {
10528 double
10529 black_point,
10530 white_point;
10531
10532 black_point=0.0;
10533 white_point=(double) image->columns*image->rows;
10534 if (attribute_flag[0] != 0)
10535 {
10536 flags=ParseGeometry(argument_list[0].string_reference,
10537 &geometry_info);
10538 if ((flags & SigmaValue) != 0)
10539 white_point=geometry_info.sigma;
10540 if ((flags & PercentValue) != 0)
10541 {
10542 black_point*=(double) image->columns*image->rows/100.0;
10543 white_point*=(double) image->columns*image->rows/100.0;
10544 }
10545 if ((flags & SigmaValue) == 0)
10546 white_point=(double) image->columns*image->rows-black_point;
10547 }
10548 if (attribute_flag[1] != 0)
10549 black_point=argument_list[1].real_reference;
10550 if (attribute_flag[2] != 0)
10551 white_point=argument_list[2].real_reference;
10552 (void) LinearStretchImage(image,black_point,white_point,exception);
10553 break;
10554 }
10555 case 108: /* ColorMatrix */
10556 {
10557 AV
10558 *av;
10559
10560 double
10561 *color_matrix;
10562
10563 KernelInfo
10564 *kernel_info;
10565
10566 size_t
10567 order;
10568
10569 if (attribute_flag[0] == 0)
10570 break;
10571 av=(AV *) argument_list[0].array_reference;
10572 order=(size_t) sqrt(av_len(av)+1);
10573 color_matrix=(double *) AcquireQuantumMemory(order,order*
10574 sizeof(*color_matrix));
10575 if (color_matrix == (double *) NULL)
10576 {
10577 ThrowPerlException(exception,ResourceLimitFatalError,
10578 "MemoryAllocationFailed",PackageName);
10579 goto PerlException;
10580 }
10581 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10582 color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10583 for ( ; j < (ssize_t) (order*order); j++)
10584 color_matrix[j]=0.0;
cristy2c57b742014-10-31 00:40:34 +000010585 kernel_info=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010586 if (kernel_info == (KernelInfo *) NULL)
10587 break;
10588 kernel_info->width=order;
10589 kernel_info->height=order;
10590 kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10591 order*sizeof(*kernel_info->values));
10592 if (kernel_info->values != (MagickRealType *) NULL)
10593 {
10594 for (i=0; i < (ssize_t) (order*order); i++)
10595 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10596 image=ColorMatrixImage(image,kernel_info,exception);
10597 }
10598 kernel_info=DestroyKernelInfo(kernel_info);
10599 color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10600 break;
10601 }
10602 case 109: /* Mask */
10603 {
10604 Image
10605 *mask_image;
10606
10607 if (attribute_flag[0] == 0)
10608 {
10609 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10610 PackageName);
10611 goto PerlException;
10612 }
10613 mask_image=CloneImage(argument_list[0].image_reference,0,0,
10614 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +000010615 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010616 mask_image=DestroyImage(mask_image);
10617 break;
10618 }
10619 case 110: /* Polaroid */
10620 {
10621 char
10622 *caption;
10623
10624 DrawInfo
10625 *draw_info;
10626
10627 double
10628 angle;
10629
10630 PixelInterpolateMethod
10631 method;
10632
10633 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10634 (DrawInfo *) NULL);
10635 caption=(char *) NULL;
10636 if (attribute_flag[0] != 0)
10637 caption=InterpretImageProperties(info ? info->image_info :
10638 (ImageInfo *) NULL,image,argument_list[0].string_reference,
10639 exception);
10640 angle=0.0;
10641 if (attribute_flag[1] != 0)
10642 angle=argument_list[1].real_reference;
10643 if (attribute_flag[2] != 0)
10644 (void) CloneString(&draw_info->font,
10645 argument_list[2].string_reference);
10646 if (attribute_flag[3] != 0)
10647 (void) QueryColorCompliance(argument_list[3].string_reference,
10648 AllCompliance,&draw_info->stroke,exception);
10649 if (attribute_flag[4] != 0)
10650 (void) QueryColorCompliance(argument_list[4].string_reference,
10651 AllCompliance,&draw_info->fill,exception);
10652 if (attribute_flag[5] != 0)
10653 draw_info->stroke_width=argument_list[5].real_reference;
10654 if (attribute_flag[6] != 0)
10655 draw_info->pointsize=argument_list[6].real_reference;
10656 if (attribute_flag[7] != 0)
10657 draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10658 if (attribute_flag[8] != 0)
10659 (void) QueryColorCompliance(argument_list[8].string_reference,
10660 AllCompliance,&image->background_color,exception);
10661 method=UndefinedInterpolatePixel;
10662 if (attribute_flag[9] != 0)
10663 method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10664 image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10665 draw_info=DestroyDrawInfo(draw_info);
10666 if (caption != (char *) NULL)
10667 caption=DestroyString(caption);
10668 break;
10669 }
10670 case 111: /* FloodfillPaint */
10671 {
10672 DrawInfo
10673 *draw_info;
10674
10675 MagickBooleanType
10676 invert;
10677
10678 PixelInfo
10679 target;
10680
10681 draw_info=CloneDrawInfo(info ? info->image_info :
10682 (ImageInfo *) NULL,(DrawInfo *) NULL);
10683 if (attribute_flag[0] != 0)
10684 flags=ParsePageGeometry(image,argument_list[0].string_reference,
10685 &geometry,exception);
10686 if (attribute_flag[1] != 0)
10687 geometry.x=argument_list[1].integer_reference;
10688 if (attribute_flag[2] != 0)
10689 geometry.y=argument_list[2].integer_reference;
10690 if (attribute_flag[3] != 0)
10691 (void) QueryColorCompliance(argument_list[3].string_reference,
10692 AllCompliance,&draw_info->fill,exception);
10693 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10694 geometry.x,geometry.y,&target,exception);
10695 if (attribute_flag[4] != 0)
10696 QueryColorCompliance(argument_list[4].string_reference,
10697 AllCompliance,&target,exception);
10698 if (attribute_flag[5] != 0)
10699 image->fuzz=StringToDoubleInterval(
10700 argument_list[5].string_reference,(double) QuantumRange+1.0);
10701 if (attribute_flag[6] != 0)
10702 channel=(ChannelType) argument_list[6].integer_reference;
10703 invert=MagickFalse;
10704 if (attribute_flag[7] != 0)
10705 invert=(MagickBooleanType) argument_list[7].integer_reference;
10706 channel_mask=SetImageChannelMask(image,channel);
10707 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10708 geometry.y,invert,exception);
10709 (void) SetImageChannelMask(image,channel_mask);
10710 draw_info=DestroyDrawInfo(draw_info);
10711 break;
10712 }
10713 case 112: /* Distort */
10714 {
10715 AV
10716 *av;
10717
10718 double
10719 *coordinates;
10720
Cristy8645e042016-02-03 16:35:29 -050010721 DistortMethod
cristy4a3ce0a2013-08-03 20:06:59 +000010722 method;
10723
10724 size_t
10725 number_coordinates;
10726
10727 VirtualPixelMethod
10728 virtual_pixel;
10729
10730 if (attribute_flag[0] == 0)
10731 break;
10732 method=UndefinedDistortion;
10733 if (attribute_flag[1] != 0)
Cristy8645e042016-02-03 16:35:29 -050010734 method=(DistortMethod) argument_list[1].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010735 av=(AV *) argument_list[0].array_reference;
10736 number_coordinates=(size_t) av_len(av)+1;
10737 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10738 sizeof(*coordinates));
10739 if (coordinates == (double *) NULL)
10740 {
10741 ThrowPerlException(exception,ResourceLimitFatalError,
10742 "MemoryAllocationFailed",PackageName);
10743 goto PerlException;
10744 }
10745 for (j=0; j < (ssize_t) number_coordinates; j++)
10746 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10747 virtual_pixel=UndefinedVirtualPixelMethod;
10748 if (attribute_flag[2] != 0)
10749 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10750 argument_list[2].integer_reference,exception);
10751 image=DistortImage(image,method,number_coordinates,coordinates,
10752 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10753 exception);
10754 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10755 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10756 exception);
10757 coordinates=(double *) RelinquishMagickMemory(coordinates);
10758 break;
10759 }
10760 case 113: /* Clut */
10761 {
10762 PixelInterpolateMethod
10763 method;
10764
10765 if (attribute_flag[0] == 0)
10766 {
10767 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10768 PackageName);
10769 goto PerlException;
10770 }
10771 method=UndefinedInterpolatePixel;
10772 if (attribute_flag[1] != 0)
10773 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10774 if (attribute_flag[2] != 0)
10775 channel=(ChannelType) argument_list[2].integer_reference;
10776 channel_mask=SetImageChannelMask(image,channel);
10777 (void) ClutImage(image,argument_list[0].image_reference,method,
10778 exception);
10779 (void) SetImageChannelMask(image,channel_mask);
10780 break;
10781 }
10782 case 114: /* LiquidRescale */
10783 {
10784 if (attribute_flag[0] != 0)
10785 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10786 &geometry,exception);
10787 if (attribute_flag[1] != 0)
10788 geometry.width=argument_list[1].integer_reference;
10789 if (attribute_flag[2] != 0)
10790 geometry.height=argument_list[2].integer_reference;
10791 if (attribute_flag[3] == 0)
10792 argument_list[3].real_reference=1.0;
10793 if (attribute_flag[4] == 0)
10794 argument_list[4].real_reference=0.0;
10795 image=LiquidRescaleImage(image,geometry.width,geometry.height,
10796 argument_list[3].real_reference,argument_list[4].real_reference,
10797 exception);
10798 break;
10799 }
10800 case 115: /* EncipherImage */
10801 {
10802 (void) EncipherImage(image,argument_list[0].string_reference,
10803 exception);
10804 break;
10805 }
10806 case 116: /* DecipherImage */
10807 {
10808 (void) DecipherImage(image,argument_list[0].string_reference,
10809 exception);
10810 break;
10811 }
10812 case 117: /* Deskew */
10813 {
10814 geometry_info.rho=QuantumRange/2.0;
10815 if (attribute_flag[0] != 0)
10816 flags=ParseGeometry(argument_list[0].string_reference,
10817 &geometry_info);
10818 if (attribute_flag[1] != 0)
10819 geometry_info.rho=StringToDoubleInterval(
10820 argument_list[1].string_reference,(double) QuantumRange+1.0);
10821 image=DeskewImage(image,geometry_info.rho,exception);
10822 break;
10823 }
10824 case 118: /* Remap */
10825 {
10826 QuantizeInfo
10827 *quantize_info;
10828
10829 if (attribute_flag[0] == 0)
10830 {
10831 ThrowPerlException(exception,OptionError,"RemapImageRequired",
10832 PackageName);
10833 goto PerlException;
10834 }
10835 quantize_info=AcquireQuantizeInfo(info->image_info);
10836 if (attribute_flag[1] != 0)
10837 quantize_info->dither_method=(DitherMethod)
10838 argument_list[1].integer_reference;
10839 (void) RemapImages(quantize_info,image,
10840 argument_list[0].image_reference,exception);
10841 quantize_info=DestroyQuantizeInfo(quantize_info);
10842 break;
10843 }
10844 case 119: /* SparseColor */
10845 {
10846 AV
10847 *av;
10848
10849 double
10850 *coordinates;
10851
10852 SparseColorMethod
10853 method;
10854
10855 size_t
10856 number_coordinates;
10857
10858 VirtualPixelMethod
10859 virtual_pixel;
10860
10861 if (attribute_flag[0] == 0)
10862 break;
10863 method=UndefinedColorInterpolate;
10864 if (attribute_flag[1] != 0)
10865 method=(SparseColorMethod) argument_list[1].integer_reference;
10866 av=(AV *) argument_list[0].array_reference;
10867 number_coordinates=(size_t) av_len(av)+1;
10868 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10869 sizeof(*coordinates));
10870 if (coordinates == (double *) NULL)
10871 {
10872 ThrowPerlException(exception,ResourceLimitFatalError,
10873 "MemoryAllocationFailed",PackageName);
10874 goto PerlException;
10875 }
10876 for (j=0; j < (ssize_t) number_coordinates; j++)
10877 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10878 virtual_pixel=UndefinedVirtualPixelMethod;
10879 if (attribute_flag[2] != 0)
10880 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10881 argument_list[2].integer_reference,exception);
10882 if (attribute_flag[3] != 0)
10883 channel=(ChannelType) argument_list[3].integer_reference;
10884 channel_mask=SetImageChannelMask(image,channel);
10885 image=SparseColorImage(image,method,number_coordinates,coordinates,
10886 exception);
10887 if (image != (Image *) NULL)
10888 (void) SetImageChannelMask(image,channel_mask);
10889 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10890 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10891 exception);
10892 coordinates=(double *) RelinquishMagickMemory(coordinates);
10893 break;
10894 }
10895 case 120: /* Function */
10896 {
10897 AV
10898 *av;
10899
10900 double
10901 *parameters;
10902
10903 MagickFunction
10904 function;
10905
10906 size_t
10907 number_parameters;
10908
10909 VirtualPixelMethod
10910 virtual_pixel;
10911
10912 if (attribute_flag[0] == 0)
10913 break;
10914 function=UndefinedFunction;
10915 if (attribute_flag[1] != 0)
10916 function=(MagickFunction) argument_list[1].integer_reference;
10917 av=(AV *) argument_list[0].array_reference;
10918 number_parameters=(size_t) av_len(av)+1;
10919 parameters=(double *) AcquireQuantumMemory(number_parameters,
10920 sizeof(*parameters));
10921 if (parameters == (double *) NULL)
10922 {
10923 ThrowPerlException(exception,ResourceLimitFatalError,
10924 "MemoryAllocationFailed",PackageName);
10925 goto PerlException;
10926 }
10927 for (j=0; j < (ssize_t) number_parameters; j++)
10928 parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10929 virtual_pixel=UndefinedVirtualPixelMethod;
10930 if (attribute_flag[2] != 0)
10931 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10932 argument_list[2].integer_reference,exception);
10933 (void) FunctionImage(image,function,number_parameters,parameters,
10934 exception);
10935 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10936 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10937 exception);
10938 parameters=(double *) RelinquishMagickMemory(parameters);
10939 break;
10940 }
10941 case 121: /* SelectiveBlur */
10942 {
10943 if (attribute_flag[0] != 0)
10944 {
10945 flags=ParseGeometry(argument_list[0].string_reference,
10946 &geometry_info);
10947 if ((flags & SigmaValue) == 0)
10948 geometry_info.sigma=1.0;
10949 if ((flags & PercentValue) != 0)
10950 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10951 }
10952 if (attribute_flag[1] != 0)
10953 geometry_info.rho=argument_list[1].real_reference;
10954 if (attribute_flag[2] != 0)
10955 geometry_info.sigma=argument_list[2].real_reference;
10956 if (attribute_flag[3] != 0)
10957 geometry_info.xi=argument_list[3].integer_reference;;
10958 if (attribute_flag[5] != 0)
10959 channel=(ChannelType) argument_list[5].integer_reference;
10960 channel_mask=SetImageChannelMask(image,channel);
10961 image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10962 geometry_info.xi,exception);
10963 if (image != (Image *) NULL)
10964 (void) SetImageChannelMask(image,channel_mask);
10965 break;
10966 }
10967 case 122: /* HaldClut */
10968 {
10969 if (attribute_flag[0] == 0)
10970 {
10971 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10972 PackageName);
10973 goto PerlException;
10974 }
10975 if (attribute_flag[1] != 0)
10976 channel=(ChannelType) argument_list[1].integer_reference;
10977 channel_mask=SetImageChannelMask(image,channel);
10978 (void) HaldClutImage(image,argument_list[0].image_reference,
10979 exception);
10980 (void) SetImageChannelMask(image,channel_mask);
10981 break;
10982 }
10983 case 123: /* BlueShift */
10984 {
10985 if (attribute_flag[0] != 0)
10986 (void) ParseGeometry(argument_list[0].string_reference,
10987 &geometry_info);
10988 image=BlueShiftImage(image,geometry_info.rho,exception);
10989 break;
10990 }
10991 case 124: /* ForwardFourierTransformImage */
10992 {
10993 image=ForwardFourierTransformImage(image,
10994 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10995 exception);
10996 break;
10997 }
10998 case 125: /* InverseFourierTransformImage */
10999 {
11000 image=InverseFourierTransformImage(image,image->next,
11001 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11002 exception);
11003 break;
11004 }
11005 case 126: /* ColorDecisionList */
11006 {
11007 if (attribute_flag[0] == 0)
11008 argument_list[0].string_reference=(char *) NULL;
11009 (void) ColorDecisionListImage(image,
11010 argument_list[0].string_reference,exception);
11011 break;
11012 }
11013 case 127: /* AutoGamma */
11014 {
11015 if (attribute_flag[0] != 0)
11016 channel=(ChannelType) argument_list[0].integer_reference;
11017 channel_mask=SetImageChannelMask(image,channel);
11018 (void) AutoGammaImage(image,exception);
11019 (void) SetImageChannelMask(image,channel_mask);
11020 break;
11021 }
11022 case 128: /* AutoLevel */
11023 {
11024 if (attribute_flag[0] != 0)
11025 channel=(ChannelType) argument_list[0].integer_reference;
11026 channel_mask=SetImageChannelMask(image,channel);
11027 (void) AutoLevelImage(image,exception);
11028 (void) SetImageChannelMask(image,channel_mask);
11029 break;
11030 }
11031 case 129: /* LevelColors */
11032 {
11033 PixelInfo
11034 black_point,
11035 white_point;
11036
11037 (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
11038 exception);
11039 (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
11040 exception);
11041 if (attribute_flag[1] != 0)
11042 (void) QueryColorCompliance(
11043 argument_list[1].string_reference,AllCompliance,&black_point,
11044 exception);
11045 if (attribute_flag[2] != 0)
11046 (void) QueryColorCompliance(
11047 argument_list[2].string_reference,AllCompliance,&white_point,
11048 exception);
11049 if (attribute_flag[3] != 0)
11050 channel=(ChannelType) argument_list[3].integer_reference;
11051 channel_mask=SetImageChannelMask(image,channel);
11052 (void) LevelImageColors(image,&black_point,&white_point,
11053 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11054 exception);
11055 (void) SetImageChannelMask(image,channel_mask);
11056 break;
11057 }
11058 case 130: /* Clamp */
11059 {
11060 if (attribute_flag[0] != 0)
11061 channel=(ChannelType) argument_list[0].integer_reference;
11062 channel_mask=SetImageChannelMask(image,channel);
11063 (void) ClampImage(image,exception);
11064 (void) SetImageChannelMask(image,channel_mask);
11065 break;
11066 }
11067 case 131: /* BrightnessContrast */
11068 {
11069 double
11070 brightness,
11071 contrast;
11072
11073 brightness=0.0;
11074 contrast=0.0;
11075 if (attribute_flag[0] != 0)
11076 {
11077 flags=ParseGeometry(argument_list[0].string_reference,
11078 &geometry_info);
11079 brightness=geometry_info.rho;
11080 if ((flags & SigmaValue) == 0)
11081 contrast=geometry_info.sigma;
11082 }
11083 if (attribute_flag[1] != 0)
11084 brightness=argument_list[1].real_reference;
11085 if (attribute_flag[2] != 0)
11086 contrast=argument_list[2].real_reference;
11087 if (attribute_flag[4] != 0)
11088 channel=(ChannelType) argument_list[4].integer_reference;
11089 channel_mask=SetImageChannelMask(image,channel);
11090 (void) BrightnessContrastImage(image,brightness,contrast,exception);
11091 (void) SetImageChannelMask(image,channel_mask);
11092 break;
11093 }
11094 case 132: /* Morphology */
11095 {
11096 KernelInfo
11097 *kernel;
11098
11099 MorphologyMethod
11100 method;
11101
11102 ssize_t
11103 iterations;
11104
11105 if (attribute_flag[0] == 0)
11106 break;
cristy2c57b742014-10-31 00:40:34 +000011107 kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011108 if (kernel == (KernelInfo *) NULL)
11109 break;
11110 if (attribute_flag[1] != 0)
11111 channel=(ChannelType) argument_list[1].integer_reference;
11112 method=UndefinedMorphology;
11113 if (attribute_flag[2] != 0)
11114 method=argument_list[2].integer_reference;
11115 iterations=1;
11116 if (attribute_flag[3] != 0)
11117 iterations=argument_list[3].integer_reference;
11118 channel_mask=SetImageChannelMask(image,channel);
11119 image=MorphologyImage(image,method,iterations,kernel,exception);
11120 if (image != (Image *) NULL)
11121 (void) SetImageChannelMask(image,channel_mask);
11122 kernel=DestroyKernelInfo(kernel);
11123 break;
11124 }
11125 case 133: /* Mode */
11126 {
11127 if (attribute_flag[0] != 0)
11128 {
11129 flags=ParseGeometry(argument_list[0].string_reference,
11130 &geometry_info);
11131 if ((flags & SigmaValue) == 0)
11132 geometry_info.sigma=1.0;
11133 }
11134 if (attribute_flag[1] != 0)
11135 geometry_info.rho=argument_list[1].real_reference;
11136 if (attribute_flag[2] != 0)
11137 geometry_info.sigma=argument_list[2].real_reference;
11138 if (attribute_flag[3] != 0)
11139 channel=(ChannelType) argument_list[3].integer_reference;
11140 channel_mask=SetImageChannelMask(image,channel);
11141 image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11142 (size_t) geometry_info.sigma,exception);
11143 if (image != (Image *) NULL)
11144 (void) SetImageChannelMask(image,channel_mask);
11145 break;
11146 }
11147 case 134: /* Statistic */
11148 {
11149 StatisticType
11150 statistic;
11151
11152 statistic=UndefinedStatistic;
11153 if (attribute_flag[0] != 0)
11154 {
11155 flags=ParseGeometry(argument_list[0].string_reference,
11156 &geometry_info);
11157 if ((flags & SigmaValue) == 0)
11158 geometry_info.sigma=1.0;
11159 }
11160 if (attribute_flag[1] != 0)
11161 geometry_info.rho=argument_list[1].real_reference;
11162 if (attribute_flag[2] != 0)
11163 geometry_info.sigma=argument_list[2].real_reference;
11164 if (attribute_flag[3] != 0)
11165 channel=(ChannelType) argument_list[3].integer_reference;
11166 if (attribute_flag[4] != 0)
11167 statistic=(StatisticType) argument_list[4].integer_reference;
11168 channel_mask=SetImageChannelMask(image,channel);
11169 image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11170 (size_t) geometry_info.sigma,exception);
11171 if (image != (Image *) NULL)
11172 (void) SetImageChannelMask(image,channel_mask);
11173 break;
11174 }
11175 case 135: /* Perceptible */
11176 {
11177 double
11178 epsilon;
11179
11180 epsilon=MagickEpsilon;
11181 if (attribute_flag[0] != 0)
11182 epsilon=argument_list[0].real_reference;
11183 if (attribute_flag[1] != 0)
11184 channel=(ChannelType) argument_list[1].integer_reference;
11185 channel_mask=SetImageChannelMask(image,channel);
11186 (void) PerceptibleImage(image,epsilon,exception);
11187 (void) SetImageChannelMask(image,channel_mask);
11188 break;
11189 }
11190 case 136: /* Poly */
11191 {
11192 AV
11193 *av;
11194
11195 double
11196 *terms;
11197
11198 size_t
11199 number_terms;
11200
11201 if (attribute_flag[0] == 0)
11202 break;
11203 if (attribute_flag[1] != 0)
11204 channel=(ChannelType) argument_list[1].integer_reference;
11205 av=(AV *) argument_list[0].array_reference;
11206 number_terms=(size_t) av_len(av);
11207 terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11208 if (terms == (double *) NULL)
11209 {
11210 ThrowPerlException(exception,ResourceLimitFatalError,
11211 "MemoryAllocationFailed",PackageName);
11212 goto PerlException;
11213 }
11214 for (j=0; j < av_len(av); j++)
11215 terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11216 image=PolynomialImage(image,number_terms >> 1,terms,exception);
11217 terms=(double *) RelinquishMagickMemory(terms);
11218 break;
11219 }
11220 case 137: /* Grayscale */
11221 {
11222 PixelIntensityMethod
11223 method;
11224
11225 method=UndefinedPixelIntensityMethod;
11226 if (attribute_flag[0] != 0)
11227 method=(PixelIntensityMethod) argument_list[0].integer_reference;
11228 (void) GrayscaleImage(image,method,exception);
11229 break;
11230 }
cristy4ceadb82014-03-29 15:30:43 +000011231 case 138: /* Canny */
11232 {
11233 if (attribute_flag[0] != 0)
11234 {
11235 flags=ParseGeometry(argument_list[0].string_reference,
11236 &geometry_info);
11237 if ((flags & SigmaValue) == 0)
11238 geometry_info.sigma=1.0;
11239 if ((flags & XiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011240 geometry_info.xi=0.10;
cristy4ceadb82014-03-29 15:30:43 +000011241 if ((flags & PsiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011242 geometry_info.psi=0.30;
cristy41814f22014-04-09 20:53:11 +000011243 if ((flags & PercentValue) != 0)
11244 {
11245 geometry_info.xi/=100.0;
11246 geometry_info.psi/=100.0;
11247 }
cristy4ceadb82014-03-29 15:30:43 +000011248 }
11249 if (attribute_flag[1] != 0)
11250 geometry_info.rho=argument_list[1].real_reference;
11251 if (attribute_flag[2] != 0)
11252 geometry_info.sigma=argument_list[2].real_reference;
11253 if (attribute_flag[3] != 0)
11254 geometry_info.xi=argument_list[3].real_reference;
11255 if (attribute_flag[4] != 0)
11256 geometry_info.psi=argument_list[4].real_reference;
11257 if (attribute_flag[5] != 0)
11258 channel=(ChannelType) argument_list[5].integer_reference;
11259 channel_mask=SetImageChannelMask(image,channel);
11260 image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11261 geometry_info.xi,geometry_info.psi,exception);
11262 if (image != (Image *) NULL)
11263 (void) SetImageChannelMask(image,channel_mask);
11264 break;
11265 }
cristy2fc10e52014-04-26 14:13:53 +000011266 case 139: /* HoughLine */
cristy4e215022014-04-19 18:02:35 +000011267 {
11268 if (attribute_flag[0] != 0)
11269 {
11270 flags=ParseGeometry(argument_list[0].string_reference,
11271 &geometry_info);
11272 if ((flags & SigmaValue) == 0)
11273 geometry_info.sigma=geometry_info.rho;
cristy20f90422014-04-27 13:34:21 +000011274 if ((flags & XiValue) == 0)
11275 geometry_info.xi=40;
cristy4e215022014-04-19 18:02:35 +000011276 }
11277 if (attribute_flag[1] != 0)
11278 geometry_info.rho=(double) argument_list[1].integer_reference;
11279 if (attribute_flag[2] != 0)
11280 geometry_info.sigma=(double) argument_list[2].integer_reference;
11281 if (attribute_flag[3] != 0)
11282 geometry_info.xi=(double) argument_list[3].integer_reference;
cristy2fc10e52014-04-26 14:13:53 +000011283 image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11284 geometry_info.sigma,(size_t) geometry_info.xi,exception);
11285 break;
11286 }
11287 case 140: /* MeanShift */
11288 {
11289 if (attribute_flag[0] != 0)
11290 {
11291 flags=ParseGeometry(argument_list[0].string_reference,
11292 &geometry_info);
11293 if ((flags & SigmaValue) == 0)
11294 geometry_info.sigma=geometry_info.rho;
cristy2fc10e52014-04-26 14:13:53 +000011295 if ((flags & XiValue) == 0)
cristy1309fc32014-04-26 18:48:37 +000011296 geometry_info.xi=0.10*QuantumRange;
11297 if ((flags & PercentValue) != 0)
11298 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
cristy2fc10e52014-04-26 14:13:53 +000011299 }
11300 if (attribute_flag[1] != 0)
11301 geometry_info.rho=(double) argument_list[1].integer_reference;
11302 if (attribute_flag[2] != 0)
11303 geometry_info.sigma=(double) argument_list[2].integer_reference;
11304 if (attribute_flag[3] != 0)
11305 geometry_info.xi=(double) argument_list[3].integer_reference;
11306 image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
cristy1309fc32014-04-26 18:48:37 +000011307 geometry_info.sigma,geometry_info.xi,exception);
cristy4e215022014-04-19 18:02:35 +000011308 break;
11309 }
cristy3b207f82014-09-27 14:21:20 +000011310 case 141: /* Kuwahara */
11311 {
11312 if (attribute_flag[0] != 0)
11313 {
11314 flags=ParseGeometry(argument_list[0].string_reference,
11315 &geometry_info);
11316 if ((flags & SigmaValue) == 0)
cristy3a9903c2014-10-04 01:14:20 +000011317 geometry_info.sigma=geometry_info.rho-0.5;
cristy3b207f82014-09-27 14:21:20 +000011318 }
11319 if (attribute_flag[1] != 0)
11320 geometry_info.rho=argument_list[1].real_reference;
11321 if (attribute_flag[2] != 0)
11322 geometry_info.sigma=argument_list[2].real_reference;
11323 if (attribute_flag[3] != 0)
11324 channel=(ChannelType) argument_list[3].integer_reference;
11325 channel_mask=SetImageChannelMask(image,channel);
11326 image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11327 exception);
11328 if (image != (Image *) NULL)
11329 (void) SetImageChannelMask(image,channel_mask);
11330 break;
11331 }
Cristy0f5df812017-07-04 18:30:05 -040011332 case 142: /* ConnectedComponents */
cristy6e0b3bc2014-10-19 17:51:42 +000011333 {
11334 size_t
11335 connectivity;
11336
11337 connectivity=4;
11338 if (attribute_flag[0] != 0)
11339 connectivity=argument_list[0].integer_reference;
Cristy2ca0e9a2016-01-01 08:36:14 -050011340 image=ConnectedComponentsImage(image,connectivity,
Cristy4f83be82015-12-31 08:40:53 -050011341 (CCObjectInfo **) NULL,exception);
cristy6e0b3bc2014-10-19 17:51:42 +000011342 break;
11343 }
cristy0b94b392015-06-22 18:56:37 +000011344 case 143: /* Copy */
11345 {
11346 Image
11347 *source_image;
11348
11349 OffsetInfo
11350 offset;
11351
cristy2ffdb092015-06-25 14:31:20 +000011352 RectangleInfo
11353 offset_geometry;
11354
cristyf3a724a2015-06-25 13:02:53 +000011355 source_image=image;
cristy0b94b392015-06-22 18:56:37 +000011356 if (attribute_flag[0] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011357 source_image=argument_list[0].image_reference;
cristy2ffdb092015-06-25 14:31:20 +000011358 SetGeometry(source_image,&geometry);
cristy0b94b392015-06-22 18:56:37 +000011359 if (attribute_flag[1] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011360 flags=ParseGravityGeometry(source_image,
11361 argument_list[1].string_reference,&geometry,exception);
cristy0b94b392015-06-22 18:56:37 +000011362 if (attribute_flag[2] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011363 geometry.width=argument_list[2].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011364 if (attribute_flag[3] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011365 geometry.height=argument_list[3].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011366 if (attribute_flag[4] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011367 geometry.x=argument_list[4].integer_reference;
11368 if (attribute_flag[5] != 0)
11369 geometry.y=argument_list[5].integer_reference;
11370 if (attribute_flag[6] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011371 image->gravity=(GravityType) argument_list[6].integer_reference;
dirk169d1642015-06-27 19:51:08 +000011372 SetGeometry(image,&offset_geometry);
cristyf3a724a2015-06-25 13:02:53 +000011373 if (attribute_flag[7] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011374 flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11375 &offset_geometry,exception);
11376 offset.x=offset_geometry.x;
11377 offset.y=offset_geometry.y;
cristyf3a724a2015-06-25 13:02:53 +000011378 if (attribute_flag[8] != 0)
11379 offset.x=argument_list[8].integer_reference;
11380 if (attribute_flag[9] != 0)
11381 offset.y=argument_list[9].integer_reference;
cristycd6d5182015-06-23 17:22:15 +000011382 (void) CopyImagePixels(image,source_image,&geometry,&offset,
11383 exception);
cristy0b94b392015-06-22 18:56:37 +000011384 break;
11385 }
Cristy5488c982016-02-13 14:07:50 -050011386 case 144: /* Color */
11387 {
11388 PixelInfo
11389 color;
11390
Cristyf20e3562016-02-14 09:08:15 -050011391 (void) QueryColorCompliance("none",AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011392 if (attribute_flag[0] != 0)
Cristyf20e3562016-02-14 09:08:15 -050011393 (void) QueryColorCompliance(argument_list[0].string_reference,
11394 AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011395 (void) SetImageColor(image,&color,exception);
11396 break;
11397 }
Cristy2d830ed2016-02-21 10:54:16 -050011398 case 145: /* WaveletDenoise */
11399 {
Cristyc1759412016-02-27 12:17:58 -050011400 if (attribute_flag[0] != 0)
Cristyee21f7f2016-02-27 15:56:49 -050011401 {
11402 flags=ParseGeometry(argument_list[0].string_reference,
11403 &geometry_info);
11404 if ((flags & PercentValue) != 0)
Cristy23446632016-02-29 09:36:34 -050011405 {
11406 geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11407 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11408 }
Cristyee21f7f2016-02-27 15:56:49 -050011409 if ((flags & SigmaValue) == 0)
11410 geometry_info.sigma=0.0;
11411 }
Cristyc1759412016-02-27 12:17:58 -050011412 if (attribute_flag[1] != 0)
11413 geometry_info.rho=argument_list[1].real_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011414 if (attribute_flag[2] != 0)
Cristyc1759412016-02-27 12:17:58 -050011415 geometry_info.sigma=argument_list[2].real_reference;
11416 if (attribute_flag[3] != 0)
11417 channel=(ChannelType) argument_list[3].integer_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011418 channel_mask=SetImageChannelMask(image,channel);
Cristyc1759412016-02-27 12:17:58 -050011419 image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11420 exception);
Cristy2d830ed2016-02-21 10:54:16 -050011421 if (image != (Image *) NULL)
11422 (void) SetImageChannelMask(image,channel_mask);
11423 break;
11424 }
Cristy99a57162016-12-05 11:47:57 -050011425 case 146: /* Colorspace */
11426 {
11427 ColorspaceType
11428 colorspace;
11429
11430 colorspace=sRGBColorspace;
11431 if (attribute_flag[0] != 0)
11432 colorspace=(ColorspaceType) argument_list[0].integer_reference;
11433 (void) TransformImageColorspace(image,colorspace,exception);
11434 break;
11435 }
Cristy53353872017-07-02 12:24:24 -040011436 case 147: /* AutoThreshold */
11437 {
11438 AutoThresholdMethod
11439 method;
11440
11441 method=UndefinedThresholdMethod;
11442 if (attribute_flag[0] != 0)
Cristyb63e7752017-07-02 13:22:01 -040011443 method=(AutoThresholdMethod) argument_list[0].integer_reference;
Cristy53353872017-07-02 12:24:24 -040011444 (void) AutoThresholdImage(image,method,exception);
11445 break;
11446 }
Cristy532b3382018-08-05 17:56:56 -040011447 case 148: /* RangeThreshold */
11448 {
11449 if (attribute_flag[0] != 0)
11450 {
11451 flags=ParseGeometry(argument_list[0].string_reference,
11452 &geometry_info);
11453 if ((flags & SigmaValue) == 0)
11454 geometry_info.sigma=geometry_info.rho;
11455 if ((flags & XiValue) == 0)
11456 geometry_info.xi=geometry_info.sigma;
11457 if ((flags & PsiValue) == 0)
11458 geometry_info.psi=geometry_info.xi;
11459 }
11460 if (attribute_flag[1] != 0)
11461 geometry_info.rho=argument_list[1].real_reference;
11462 if (attribute_flag[2] != 0)
11463 geometry_info.sigma=argument_list[2].real_reference;
11464 if (attribute_flag[3] != 0)
11465 geometry_info.xi=argument_list[3].real_reference;
11466 if (attribute_flag[4] != 0)
11467 geometry_info.psi=argument_list[4].real_reference;
11468 if (attribute_flag[5] != 0)
11469 channel=(ChannelType) argument_list[5].integer_reference;
11470 channel_mask=SetImageChannelMask(image,channel);
11471 image=RangeThresholdImage(image,geometry_info.rho,geometry_info.sigma,
11472 geometry_info.xi,geometry_info.psi,exception);
11473 if (image != (Image *) NULL)
11474 (void) SetImageChannelMask(image,channel_mask);
11475 break;
11476 }
cristy4a3ce0a2013-08-03 20:06:59 +000011477 }
11478 if (next != (Image *) NULL)
11479 (void) CatchImageException(next);
Cristy7e567962018-02-03 12:42:20 -050011480 if ((region_info.width*region_info.height) != 0)
11481 (void) SetImageRegionMask(image,WritePixelMask,
11482 (const RectangleInfo *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011483 if (image != (Image *) NULL)
11484 {
11485 number_images++;
11486 if (next && (next != image))
11487 {
11488 image->next=next->next;
11489 if (image->next != (Image *) NULL)
11490 image->next->previous=image;
11491 DeleteImageFromRegistry(*pv,next);
11492 }
11493 sv_setiv(*pv,PTR2IV(image));
11494 next=image;
11495 }
11496 if (*pv)
11497 pv++;
11498 }
11499
11500 PerlException:
11501 if (reference_vector)
11502 reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11503 InheritPerlException(exception,perl_exception);
11504 exception=DestroyExceptionInfo(exception);
11505 sv_setiv(perl_exception,(IV) number_images);
11506 SvPOK_on(perl_exception);
11507 ST(0)=sv_2mortal(perl_exception);
11508 XSRETURN(1);
11509 }
11510
11511#
11512###############################################################################
11513# #
11514# #
11515# #
11516# M o n t a g e #
11517# #
11518# #
11519# #
11520###############################################################################
11521#
11522#
11523void
11524Montage(ref,...)
11525 Image::Magick ref=NO_INIT
11526 ALIAS:
11527 MontageImage = 1
11528 montage = 2
11529 montageimage = 3
11530 PPCODE:
11531 {
11532 AV
11533 *av;
11534
11535 char
11536 *attribute;
11537
11538 ExceptionInfo
11539 *exception;
11540
11541 HV
11542 *hv;
11543
11544 Image
11545 *image,
11546 *next;
11547
11548 PixelInfo
11549 transparent_color;
11550
11551 MontageInfo
11552 *montage_info;
11553
11554 register ssize_t
11555 i;
11556
11557 ssize_t
11558 sp;
11559
11560 struct PackageInfo
11561 *info;
11562
11563 SV
11564 *av_reference,
11565 *perl_exception,
11566 *reference,
11567 *rv,
11568 *sv;
11569
11570 PERL_UNUSED_VAR(ref);
11571 PERL_UNUSED_VAR(ix);
11572 exception=AcquireExceptionInfo();
11573 perl_exception=newSVpv("",0);
11574 sv=NULL;
11575 attribute=NULL;
11576 if (sv_isobject(ST(0)) == 0)
11577 {
11578 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11579 PackageName);
11580 goto PerlException;
11581 }
11582 reference=SvRV(ST(0));
11583 hv=SvSTASH(reference);
11584 av=newAV();
11585 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11586 SvREFCNT_dec(av);
11587 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11588 if (image == (Image *) NULL)
11589 {
11590 ThrowPerlException(exception,OptionError,"NoImagesDefined",
11591 PackageName);
11592 goto PerlException;
11593 }
11594 /*
11595 Get options.
11596 */
11597 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11598 montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11599 (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11600 exception);
11601 for (i=2; i < items; i+=2)
11602 {
11603 attribute=(char *) SvPV(ST(i-1),na);
11604 switch (*attribute)
11605 {
11606 case 'B':
11607 case 'b':
11608 {
11609 if (LocaleCompare(attribute,"background") == 0)
11610 {
11611 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11612 &montage_info->background_color,exception);
11613 for (next=image; next; next=next->next)
11614 next->background_color=montage_info->background_color;
11615 break;
11616 }
11617 if (LocaleCompare(attribute,"border") == 0)
11618 {
11619 montage_info->border_width=SvIV(ST(i));
11620 break;
11621 }
11622 if (LocaleCompare(attribute,"bordercolor") == 0)
11623 {
11624 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11625 &montage_info->border_color,exception);
11626 for (next=image; next; next=next->next)
11627 next->border_color=montage_info->border_color;
11628 break;
11629 }
11630 if (LocaleCompare(attribute,"borderwidth") == 0)
11631 {
11632 montage_info->border_width=SvIV(ST(i));
11633 break;
11634 }
11635 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11636 attribute);
11637 break;
11638 }
11639 case 'C':
11640 case 'c':
11641 {
11642 if (LocaleCompare(attribute,"compose") == 0)
11643 {
11644 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11645 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11646 if (sp < 0)
11647 {
11648 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11649 SvPV(ST(i),na));
11650 break;
11651 }
11652 for (next=image; next; next=next->next)
11653 next->compose=(CompositeOperator) sp;
11654 break;
11655 }
11656 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11657 attribute);
11658 break;
11659 }
11660 case 'F':
11661 case 'f':
11662 {
11663 if (LocaleCompare(attribute,"fill") == 0)
11664 {
11665 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11666 &montage_info->fill,exception);
11667 break;
11668 }
11669 if (LocaleCompare(attribute,"font") == 0)
11670 {
11671 (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11672 break;
11673 }
11674 if (LocaleCompare(attribute,"frame") == 0)
11675 {
11676 char
11677 *p;
11678
11679 p=SvPV(ST(i),na);
11680 if (IsGeometry(p) == MagickFalse)
11681 {
11682 ThrowPerlException(exception,OptionError,"MissingGeometry",
11683 p);
11684 break;
11685 }
11686 (void) CloneString(&montage_info->frame,p);
11687 if (*p == '\0')
11688 montage_info->frame=(char *) NULL;
11689 break;
11690 }
11691 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11692 attribute);
11693 break;
11694 }
11695 case 'G':
11696 case 'g':
11697 {
11698 if (LocaleCompare(attribute,"geometry") == 0)
11699 {
11700 char
11701 *p;
11702
11703 p=SvPV(ST(i),na);
11704 if (IsGeometry(p) == MagickFalse)
11705 {
11706 ThrowPerlException(exception,OptionError,"MissingGeometry",
11707 p);
11708 break;
11709 }
11710 (void) CloneString(&montage_info->geometry,p);
11711 if (*p == '\0')
11712 montage_info->geometry=(char *) NULL;
11713 break;
11714 }
11715 if (LocaleCompare(attribute,"gravity") == 0)
11716 {
11717 ssize_t
11718 in;
11719
11720 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11721 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11722 if (in < 0)
11723 {
11724 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11725 SvPV(ST(i),na));
11726 return;
11727 }
11728 montage_info->gravity=(GravityType) in;
11729 for (next=image; next; next=next->next)
11730 next->gravity=(GravityType) in;
11731 break;
11732 }
11733 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11734 attribute);
11735 break;
11736 }
11737 case 'L':
11738 case 'l':
11739 {
11740 if (LocaleCompare(attribute,"label") == 0)
11741 {
11742 for (next=image; next; next=next->next)
Cristy935a4052017-03-31 17:45:37 -040011743 (void) SetImageProperty(next,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +000011744 info ? info->image_info : (ImageInfo *) NULL,next,
Cristy935a4052017-03-31 17:45:37 -040011745 SvPV(ST(i),na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011746 break;
11747 }
11748 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11749 attribute);
11750 break;
11751 }
11752 case 'M':
11753 case 'm':
11754 {
11755 if (LocaleCompare(attribute,"mattecolor") == 0)
11756 {
11757 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
Cristy8645e042016-02-03 16:35:29 -050011758 &montage_info->alpha_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011759 for (next=image; next; next=next->next)
Cristy8645e042016-02-03 16:35:29 -050011760 next->alpha_color=montage_info->alpha_color;
cristy4a3ce0a2013-08-03 20:06:59 +000011761 break;
11762 }
11763 if (LocaleCompare(attribute,"mode") == 0)
11764 {
11765 ssize_t
11766 in;
11767
11768 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11769 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11770 switch (in)
11771 {
11772 default:
11773 {
11774 ThrowPerlException(exception,OptionError,
11775 "UnrecognizedModeType",SvPV(ST(i),na));
11776 break;
11777 }
11778 case FrameMode:
11779 {
11780 (void) CloneString(&montage_info->frame,"15x15+3+3");
11781 montage_info->shadow=MagickTrue;
11782 break;
11783 }
11784 case UnframeMode:
11785 {
11786 montage_info->frame=(char *) NULL;
11787 montage_info->shadow=MagickFalse;
11788 montage_info->border_width=0;
11789 break;
11790 }
11791 case ConcatenateMode:
11792 {
11793 montage_info->frame=(char *) NULL;
11794 montage_info->shadow=MagickFalse;
11795 (void) CloneString(&montage_info->geometry,"+0+0");
11796 montage_info->border_width=0;
11797 }
11798 }
11799 break;
11800 }
11801 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11802 attribute);
11803 break;
11804 }
11805 case 'P':
11806 case 'p':
11807 {
11808 if (LocaleCompare(attribute,"pointsize") == 0)
11809 {
11810 montage_info->pointsize=SvIV(ST(i));
11811 break;
11812 }
11813 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11814 attribute);
11815 break;
11816 }
11817 case 'S':
11818 case 's':
11819 {
11820 if (LocaleCompare(attribute,"shadow") == 0)
11821 {
11822 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11823 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11824 if (sp < 0)
11825 {
11826 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11827 SvPV(ST(i),na));
11828 break;
11829 }
11830 montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11831 break;
11832 }
11833 if (LocaleCompare(attribute,"stroke") == 0)
11834 {
11835 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11836 &montage_info->stroke,exception);
11837 break;
11838 }
11839 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11840 attribute);
11841 break;
11842 }
11843 case 'T':
11844 case 't':
11845 {
11846 if (LocaleCompare(attribute,"texture") == 0)
11847 {
11848 (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11849 break;
11850 }
11851 if (LocaleCompare(attribute,"tile") == 0)
11852 {
11853 char *p=SvPV(ST(i),na);
11854 if (IsGeometry(p) == MagickFalse)
11855 {
11856 ThrowPerlException(exception,OptionError,"MissingGeometry",
11857 p);
11858 break;
11859 }
11860 (void) CloneString(&montage_info->tile,p);
11861 if (*p == '\0')
11862 montage_info->tile=(char *) NULL;
11863 break;
11864 }
11865 if (LocaleCompare(attribute,"title") == 0)
11866 {
11867 (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11868 break;
11869 }
11870 if (LocaleCompare(attribute,"transparent") == 0)
11871 {
11872 PixelInfo
11873 transparent_color;
11874
11875 QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11876 &transparent_color,exception);
11877 for (next=image; next; next=next->next)
11878 (void) TransparentPaintImage(next,&transparent_color,
11879 TransparentAlpha,MagickFalse,exception);
11880 break;
11881 }
11882 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11883 attribute);
11884 break;
11885 }
11886 default:
11887 {
11888 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11889 attribute);
11890 break;
11891 }
11892 }
11893 }
11894 image=MontageImageList(info->image_info,montage_info,image,exception);
11895 montage_info=DestroyMontageInfo(montage_info);
11896 if (image == (Image *) NULL)
11897 goto PerlException;
11898 if (transparent_color.alpha != TransparentAlpha)
11899 for (next=image; next; next=next->next)
11900 (void) TransparentPaintImage(next,&transparent_color,
11901 TransparentAlpha,MagickFalse,exception);
11902 for ( ; image; image=image->next)
11903 {
11904 AddImageToRegistry(sv,image);
11905 rv=newRV(sv);
11906 av_push(av,sv_bless(rv,hv));
11907 SvREFCNT_dec(sv);
11908 }
11909 exception=DestroyExceptionInfo(exception);
11910 ST(0)=av_reference;
11911 SvREFCNT_dec(perl_exception);
11912 XSRETURN(1);
11913
11914 PerlException:
11915 InheritPerlException(exception,perl_exception);
11916 exception=DestroyExceptionInfo(exception);
11917 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11918 SvPOK_on(perl_exception);
11919 ST(0)=sv_2mortal(perl_exception);
11920 XSRETURN(1);
11921 }
11922
11923#
11924###############################################################################
11925# #
11926# #
11927# #
11928# M o r p h #
11929# #
11930# #
11931# #
11932###############################################################################
11933#
11934#
11935void
11936Morph(ref,...)
11937 Image::Magick ref=NO_INIT
11938 ALIAS:
11939 MorphImage = 1
11940 morph = 2
11941 morphimage = 3
11942 PPCODE:
11943 {
11944 AV
11945 *av;
11946
11947 char
11948 *attribute;
11949
11950 ExceptionInfo
11951 *exception;
11952
11953 HV
11954 *hv;
11955
11956 Image
11957 *image;
11958
11959 register ssize_t
11960 i;
11961
11962 ssize_t
11963 number_frames;
11964
11965 struct PackageInfo
11966 *info;
11967
11968 SV
11969 *av_reference,
11970 *perl_exception,
11971 *reference,
11972 *rv,
11973 *sv;
11974
11975 PERL_UNUSED_VAR(ref);
11976 PERL_UNUSED_VAR(ix);
11977 exception=AcquireExceptionInfo();
11978 perl_exception=newSVpv("",0);
11979 sv=NULL;
11980 av=NULL;
11981 attribute=NULL;
11982 if (sv_isobject(ST(0)) == 0)
11983 {
11984 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11985 PackageName);
11986 goto PerlException;
11987 }
11988 reference=SvRV(ST(0));
11989 hv=SvSTASH(reference);
11990 av=newAV();
11991 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11992 SvREFCNT_dec(av);
11993 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11994 if (image == (Image *) NULL)
11995 {
11996 ThrowPerlException(exception,OptionError,"NoImagesDefined",
11997 PackageName);
11998 goto PerlException;
11999 }
12000 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12001 /*
12002 Get attribute.
12003 */
12004 number_frames=30;
12005 for (i=2; i < items; i+=2)
12006 {
12007 attribute=(char *) SvPV(ST(i-1),na);
12008 switch (*attribute)
12009 {
12010 case 'F':
12011 case 'f':
12012 {
12013 if (LocaleCompare(attribute,"frames") == 0)
12014 {
12015 number_frames=SvIV(ST(i));
12016 break;
12017 }
12018 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12019 attribute);
12020 break;
12021 }
12022 default:
12023 {
12024 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12025 attribute);
12026 break;
12027 }
12028 }
12029 }
12030 image=MorphImages(image,number_frames,exception);
12031 if (image == (Image *) NULL)
12032 goto PerlException;
12033 for ( ; image; image=image->next)
12034 {
12035 AddImageToRegistry(sv,image);
12036 rv=newRV(sv);
12037 av_push(av,sv_bless(rv,hv));
12038 SvREFCNT_dec(sv);
12039 }
12040 exception=DestroyExceptionInfo(exception);
12041 ST(0)=av_reference;
12042 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12043 XSRETURN(1);
12044
12045 PerlException:
12046 InheritPerlException(exception,perl_exception);
12047 exception=DestroyExceptionInfo(exception);
12048 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12049 SvPOK_on(perl_exception);
12050 ST(0)=sv_2mortal(perl_exception);
12051 XSRETURN(1);
12052 }
12053
12054#
12055###############################################################################
12056# #
12057# #
12058# #
12059# M o s a i c #
12060# #
12061# #
12062# #
12063###############################################################################
12064#
12065#
12066void
12067Mosaic(ref)
12068 Image::Magick ref=NO_INIT
12069 ALIAS:
12070 MosaicImage = 1
12071 mosaic = 2
12072 mosaicimage = 3
12073 PPCODE:
12074 {
12075 AV
12076 *av;
12077
12078 ExceptionInfo
12079 *exception;
12080
12081 HV
12082 *hv;
12083
12084 Image
12085 *image;
12086
12087 struct PackageInfo
12088 *info;
12089
12090 SV
12091 *perl_exception,
12092 *reference,
12093 *rv,
12094 *sv;
12095
12096 PERL_UNUSED_VAR(ref);
12097 PERL_UNUSED_VAR(ix);
12098 exception=AcquireExceptionInfo();
12099 perl_exception=newSVpv("",0);
12100 sv=NULL;
12101 if (sv_isobject(ST(0)) == 0)
12102 {
12103 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12104 PackageName);
12105 goto PerlException;
12106 }
12107 reference=SvRV(ST(0));
12108 hv=SvSTASH(reference);
12109 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12110 if (image == (Image *) NULL)
12111 {
12112 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12113 PackageName);
12114 goto PerlException;
12115 }
12116 image=MergeImageLayers(image,MosaicLayer,exception);
12117 /*
12118 Create blessed Perl array for the returned image.
12119 */
12120 av=newAV();
12121 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12122 SvREFCNT_dec(av);
12123 AddImageToRegistry(sv,image);
12124 rv=newRV(sv);
12125 av_push(av,sv_bless(rv,hv));
12126 SvREFCNT_dec(sv);
cristy4a3ce0a2013-08-03 20:06:59 +000012127 (void) CopyMagickString(info->image_info->filename,image->filename,
cristy151b66d2015-04-15 10:50:31 +000012128 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012129 SetImageInfo(info->image_info,0,exception);
12130 exception=DestroyExceptionInfo(exception);
12131 SvREFCNT_dec(perl_exception);
12132 XSRETURN(1);
12133
12134 PerlException:
12135 InheritPerlException(exception,perl_exception);
12136 exception=DestroyExceptionInfo(exception);
12137 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12138 SvPOK_on(perl_exception); /* return messages in string context */
12139 ST(0)=sv_2mortal(perl_exception);
12140 XSRETURN(1);
12141 }
12142
12143#
12144###############################################################################
12145# #
12146# #
12147# #
12148# P i n g #
12149# #
12150# #
12151# #
12152###############################################################################
12153#
12154#
12155void
12156Ping(ref,...)
12157 Image::Magick ref=NO_INIT
12158 ALIAS:
12159 PingImage = 1
12160 ping = 2
12161 pingimage = 3
12162 PPCODE:
12163 {
12164 AV
12165 *av;
12166
12167 char
12168 **keep,
12169 **list;
12170
12171 ExceptionInfo
12172 *exception;
12173
12174 Image
12175 *image,
12176 *next;
12177
12178 int
12179 n;
12180
12181 MagickBooleanType
12182 status;
12183
12184 register char
12185 **p;
12186
12187 register ssize_t
12188 i;
12189
12190 ssize_t
12191 ac;
12192
12193 STRLEN
12194 *length;
12195
12196 struct PackageInfo
12197 *info,
12198 *package_info;
12199
12200 SV
12201 *perl_exception,
12202 *reference;
12203
12204 size_t
12205 count;
12206
12207 PERL_UNUSED_VAR(ref);
12208 PERL_UNUSED_VAR(ix);
12209 exception=AcquireExceptionInfo();
12210 perl_exception=newSVpv("",0);
12211 package_info=(struct PackageInfo *) NULL;
12212 ac=(items < 2) ? 1 : items-1;
12213 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12214 keep=list;
12215 length=(STRLEN *) NULL;
12216 if (list == (char **) NULL)
12217 {
12218 ThrowPerlException(exception,ResourceLimitError,
12219 "MemoryAllocationFailed",PackageName);
12220 goto PerlException;
12221 }
12222 keep=list;
12223 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12224 if (length == (STRLEN *) NULL)
12225 {
12226 ThrowPerlException(exception,ResourceLimitError,
12227 "MemoryAllocationFailed",PackageName);
12228 goto PerlException;
12229 }
12230 if (sv_isobject(ST(0)) == 0)
12231 {
12232 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12233 PackageName);
12234 goto PerlException;
12235 }
12236 reference=SvRV(ST(0));
12237 if (SvTYPE(reference) != SVt_PVAV)
12238 {
12239 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12240 PackageName);
12241 goto PerlException;
12242 }
12243 av=(AV *) reference;
12244 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12245 exception);
12246 package_info=ClonePackageInfo(info,exception);
12247 n=1;
12248 if (items <= 1)
12249 *list=(char *) (*package_info->image_info->filename ?
12250 package_info->image_info->filename : "XC:black");
12251 else
12252 for (n=0, i=0; i < ac; i++)
12253 {
12254 list[n]=(char *) SvPV(ST(i+1),length[n]);
12255 if ((items >= 3) && strEQcase(list[n],"blob"))
12256 {
12257 void
12258 *blob;
12259
12260 i++;
12261 blob=(void *) (SvPV(ST(i+1),length[n]));
12262 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12263 }
12264 if ((items >= 3) && strEQcase(list[n],"filename"))
12265 continue;
12266 if ((items >= 3) && strEQcase(list[n],"file"))
12267 {
12268 FILE
12269 *file;
12270
12271 PerlIO
12272 *io_info;
12273
12274 i++;
12275 io_info=IoIFP(sv_2io(ST(i+1)));
12276 if (io_info == (PerlIO *) NULL)
12277 {
12278 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12279 PackageName);
12280 continue;
12281 }
12282 file=PerlIO_findFILE(io_info);
12283 if (file == (FILE *) NULL)
12284 {
12285 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12286 PackageName);
12287 continue;
12288 }
12289 SetImageInfoFile(package_info->image_info,file);
12290 }
12291 if ((items >= 3) && strEQcase(list[n],"magick"))
12292 continue;
12293 n++;
12294 }
12295 list[n]=(char *) NULL;
12296 keep=list;
12297 status=ExpandFilenames(&n,&list);
12298 if (status == MagickFalse)
12299 {
12300 ThrowPerlException(exception,ResourceLimitError,
12301 "MemoryAllocationFailed",PackageName);
12302 goto PerlException;
12303 }
12304 count=0;
12305 for (i=0; i < n; i++)
12306 {
12307 (void) CopyMagickString(package_info->image_info->filename,list[i],
cristy151b66d2015-04-15 10:50:31 +000012308 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012309 image=PingImage(package_info->image_info,exception);
12310 if (image == (Image *) NULL)
12311 break;
12312 if ((package_info->image_info->file != (FILE *) NULL) ||
12313 (package_info->image_info->blob != (void *) NULL))
12314 DisassociateImageStream(image);
12315 count+=GetImageListLength(image);
12316 EXTEND(sp,4*count);
12317 for (next=image; next; next=next->next)
12318 {
12319 PUSHs(sv_2mortal(newSViv(next->columns)));
12320 PUSHs(sv_2mortal(newSViv(next->rows)));
12321 PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12322 PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12323 }
12324 image=DestroyImageList(image);
12325 }
12326 /*
12327 Free resources.
12328 */
12329 for (i=0; i < n; i++)
12330 if (list[i] != (char *) NULL)
12331 for (p=keep; list[i] != *p++; )
12332 if (*p == NULL)
12333 {
12334 list[i]=(char *) RelinquishMagickMemory(list[i]);
12335 break;
12336 }
12337
12338 PerlException:
12339 if (package_info != (struct PackageInfo *) NULL)
12340 DestroyPackageInfo(package_info);
12341 if (list && (list != keep))
12342 list=(char **) RelinquishMagickMemory(list);
12343 if (keep)
12344 keep=(char **) RelinquishMagickMemory(keep);
12345 if (length)
12346 length=(STRLEN *) RelinquishMagickMemory(length);
12347 InheritPerlException(exception,perl_exception);
12348 exception=DestroyExceptionInfo(exception);
12349 SvREFCNT_dec(perl_exception); /* throw away all errors */
12350 }
12351
12352#
12353###############################################################################
12354# #
12355# #
12356# #
12357# P r e v i e w #
12358# #
12359# #
12360# #
12361###############################################################################
12362#
12363#
12364void
12365Preview(ref,...)
12366 Image::Magick ref=NO_INIT
12367 ALIAS:
12368 PreviewImage = 1
12369 preview = 2
12370 previewimage = 3
12371 PPCODE:
12372 {
12373 AV
12374 *av;
12375
12376 ExceptionInfo
12377 *exception;
12378
12379 HV
12380 *hv;
12381
12382 Image
12383 *image,
12384 *preview_image;
12385
12386 PreviewType
12387 preview_type;
12388
12389 struct PackageInfo
12390 *info;
12391
12392 SV
12393 *av_reference,
12394 *perl_exception,
12395 *reference,
12396 *rv,
12397 *sv;
12398
12399 PERL_UNUSED_VAR(ref);
12400 PERL_UNUSED_VAR(ix);
12401 exception=AcquireExceptionInfo();
12402 perl_exception=newSVpv("",0);
12403 sv=NULL;
12404 av=NULL;
12405 if (sv_isobject(ST(0)) == 0)
12406 {
12407 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12408 PackageName);
12409 goto PerlException;
12410 }
12411 reference=SvRV(ST(0));
12412 hv=SvSTASH(reference);
12413 av=newAV();
12414 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12415 SvREFCNT_dec(av);
12416 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12417 if (image == (Image *) NULL)
12418 {
12419 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12420 PackageName);
12421 goto PerlException;
12422 }
12423 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12424 preview_type=GammaPreview;
12425 if (items > 1)
12426 preview_type=(PreviewType)
12427 ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12428 for ( ; image; image=image->next)
12429 {
12430 preview_image=PreviewImage(image,preview_type,exception);
12431 if (preview_image == (Image *) NULL)
12432 goto PerlException;
12433 AddImageToRegistry(sv,preview_image);
12434 rv=newRV(sv);
12435 av_push(av,sv_bless(rv,hv));
12436 SvREFCNT_dec(sv);
12437 }
12438 exception=DestroyExceptionInfo(exception);
12439 ST(0)=av_reference;
12440 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12441 XSRETURN(1);
12442
12443 PerlException:
12444 InheritPerlException(exception,perl_exception);
12445 exception=DestroyExceptionInfo(exception);
12446 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12447 SvPOK_on(perl_exception);
12448 ST(0)=sv_2mortal(perl_exception);
12449 XSRETURN(1);
12450 }
12451
12452#
12453###############################################################################
12454# #
12455# #
12456# #
12457# Q u e r y C o l o r #
12458# #
12459# #
12460# #
12461###############################################################################
12462#
12463#
12464void
12465QueryColor(ref,...)
12466 Image::Magick ref=NO_INIT
12467 ALIAS:
12468 querycolor = 1
12469 PPCODE:
12470 {
12471 char
12472 *name;
12473
12474 ExceptionInfo
12475 *exception;
12476
12477 PixelInfo
12478 color;
12479
12480 register ssize_t
12481 i;
12482
12483 SV
12484 *perl_exception;
12485
12486 PERL_UNUSED_VAR(ref);
12487 PERL_UNUSED_VAR(ix);
12488 exception=AcquireExceptionInfo();
12489 perl_exception=newSVpv("",0);
12490 if (items == 1)
12491 {
12492 const ColorInfo
12493 **colorlist;
12494
12495 size_t
12496 colors;
12497
12498 colorlist=GetColorInfoList("*",&colors,exception);
12499 EXTEND(sp,colors);
12500 for (i=0; i < (ssize_t) colors; i++)
12501 {
12502 PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12503 }
12504 colorlist=(const ColorInfo **)
12505 RelinquishMagickMemory((ColorInfo **) colorlist);
12506 goto PerlException;
12507 }
12508 EXTEND(sp,5*items);
12509 for (i=1; i < items; i++)
12510 {
12511 name=(char *) SvPV(ST(i),na);
12512 if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12513 {
12514 PUSHs(&sv_undef);
12515 continue;
12516 }
12517 PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12518 PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12519 PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12520 if (color.colorspace == CMYKColorspace)
12521 PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
cristy17f11b02014-12-20 19:37:04 +000012522 if (color.alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +000012523 PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12524 }
12525
12526 PerlException:
12527 InheritPerlException(exception,perl_exception);
12528 exception=DestroyExceptionInfo(exception);
12529 SvREFCNT_dec(perl_exception);
12530 }
12531
12532#
12533###############################################################################
12534# #
12535# #
12536# #
12537# Q u e r y C o l o r N a m e #
12538# #
12539# #
12540# #
12541###############################################################################
12542#
12543#
12544void
12545QueryColorname(ref,...)
12546 Image::Magick ref=NO_INIT
12547 ALIAS:
12548 querycolorname = 1
12549 PPCODE:
12550 {
12551 AV
12552 *av;
12553
12554 char
cristy151b66d2015-04-15 10:50:31 +000012555 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012556
12557 ExceptionInfo
12558 *exception;
12559
12560 Image
12561 *image;
12562
12563 PixelInfo
12564 target_color;
12565
12566 register ssize_t
12567 i;
12568
12569 struct PackageInfo
12570 *info;
12571
12572 SV
12573 *perl_exception,
12574 *reference; /* reference is the SV* of ref=SvIV(reference) */
12575
12576 PERL_UNUSED_VAR(ref);
12577 PERL_UNUSED_VAR(ix);
12578 exception=AcquireExceptionInfo();
12579 perl_exception=newSVpv("",0);
12580 reference=SvRV(ST(0));
12581 av=(AV *) reference;
12582 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12583 exception);
12584 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12585 if (image == (Image *) NULL)
12586 {
12587 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12588 PackageName);
12589 goto PerlException;
12590 }
12591 EXTEND(sp,items);
12592 for (i=1; i < items; i++)
12593 {
12594 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12595 exception);
12596 (void) QueryColorname(image,&target_color,SVGCompliance,message,
12597 exception);
12598 PUSHs(sv_2mortal(newSVpv(message,0)));
12599 }
12600
12601 PerlException:
12602 InheritPerlException(exception,perl_exception);
12603 exception=DestroyExceptionInfo(exception);
12604 SvREFCNT_dec(perl_exception);
12605 }
12606
12607#
12608###############################################################################
12609# #
12610# #
12611# #
12612# Q u e r y F o n t #
12613# #
12614# #
12615# #
12616###############################################################################
12617#
12618#
12619void
12620QueryFont(ref,...)
12621 Image::Magick ref=NO_INIT
12622 ALIAS:
12623 queryfont = 1
12624 PPCODE:
12625 {
12626 char
12627 *name,
cristy151b66d2015-04-15 10:50:31 +000012628 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012629
12630 ExceptionInfo
12631 *exception;
12632
12633 register ssize_t
12634 i;
12635
12636 SV
12637 *perl_exception;
12638
12639 volatile const TypeInfo
12640 *type_info;
12641
12642 PERL_UNUSED_VAR(ref);
12643 PERL_UNUSED_VAR(ix);
12644 exception=AcquireExceptionInfo();
12645 perl_exception=newSVpv("",0);
12646 if (items == 1)
12647 {
12648 const TypeInfo
12649 **typelist;
12650
12651 size_t
12652 types;
12653
12654 typelist=GetTypeInfoList("*",&types,exception);
12655 EXTEND(sp,types);
12656 for (i=0; i < (ssize_t) types; i++)
12657 {
12658 PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12659 }
12660 typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12661 typelist);
12662 goto PerlException;
12663 }
12664 EXTEND(sp,10*items);
12665 for (i=1; i < items; i++)
12666 {
12667 name=(char *) SvPV(ST(i),na);
12668 type_info=GetTypeInfo(name,exception);
12669 if (type_info == (TypeInfo *) NULL)
12670 {
12671 PUSHs(&sv_undef);
12672 continue;
12673 }
12674 if (type_info->name == (char *) NULL)
12675 PUSHs(&sv_undef);
12676 else
12677 PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12678 if (type_info->description == (char *) NULL)
12679 PUSHs(&sv_undef);
12680 else
12681 PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12682 if (type_info->family == (char *) NULL)
12683 PUSHs(&sv_undef);
12684 else
12685 PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12686 if (type_info->style == UndefinedStyle)
12687 PUSHs(&sv_undef);
12688 else
12689 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12690 type_info->style),0)));
12691 if (type_info->stretch == UndefinedStretch)
12692 PUSHs(&sv_undef);
12693 else
12694 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12695 type_info->stretch),0)));
cristy151b66d2015-04-15 10:50:31 +000012696 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
cristy4a3ce0a2013-08-03 20:06:59 +000012697 type_info->weight);
12698 PUSHs(sv_2mortal(newSVpv(message,0)));
12699 if (type_info->encoding == (char *) NULL)
12700 PUSHs(&sv_undef);
12701 else
12702 PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12703 if (type_info->foundry == (char *) NULL)
12704 PUSHs(&sv_undef);
12705 else
12706 PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12707 if (type_info->format == (char *) NULL)
12708 PUSHs(&sv_undef);
12709 else
12710 PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12711 if (type_info->metrics == (char *) NULL)
12712 PUSHs(&sv_undef);
12713 else
12714 PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12715 if (type_info->glyphs == (char *) NULL)
12716 PUSHs(&sv_undef);
12717 else
12718 PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12719 }
12720
12721 PerlException:
12722 InheritPerlException(exception,perl_exception);
12723 exception=DestroyExceptionInfo(exception);
12724 SvREFCNT_dec(perl_exception);
12725 }
12726
12727#
12728###############################################################################
12729# #
12730# #
12731# #
12732# Q u e r y F o n t M e t r i c s #
12733# #
12734# #
12735# #
12736###############################################################################
12737#
12738#
12739void
12740QueryFontMetrics(ref,...)
12741 Image::Magick ref=NO_INIT
12742 ALIAS:
12743 queryfontmetrics = 1
12744 PPCODE:
12745 {
12746 AffineMatrix
12747 affine,
12748 current;
12749
12750 AV
12751 *av;
12752
12753 char
12754 *attribute;
12755
12756 double
12757 x,
12758 y;
12759
12760 DrawInfo
12761 *draw_info;
12762
12763 ExceptionInfo
12764 *exception;
12765
12766 GeometryInfo
12767 geometry_info;
12768
12769 Image
12770 *image;
12771
12772 MagickBooleanType
12773 status;
12774
12775 MagickStatusType
12776 flags;
12777
12778 register ssize_t
12779 i;
12780
12781 ssize_t
12782 type;
12783
12784 struct PackageInfo
12785 *info,
12786 *package_info;
12787
12788 SV
12789 *perl_exception,
12790 *reference; /* reference is the SV* of ref=SvIV(reference) */
12791
12792 TypeMetric
12793 metrics;
12794
12795 PERL_UNUSED_VAR(ref);
12796 PERL_UNUSED_VAR(ix);
12797 exception=AcquireExceptionInfo();
12798 package_info=(struct PackageInfo *) NULL;
12799 perl_exception=newSVpv("",0);
12800 reference=SvRV(ST(0));
12801 av=(AV *) reference;
12802 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12803 exception);
12804 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12805 if (image == (Image *) NULL)
12806 {
12807 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12808 PackageName);
12809 goto PerlException;
12810 }
12811 package_info=ClonePackageInfo(info,exception);
12812 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12813 CloneString(&draw_info->text,"");
12814 current=draw_info->affine;
12815 GetAffineMatrix(&affine);
12816 x=0.0;
12817 y=0.0;
12818 EXTEND(sp,7*items);
12819 for (i=2; i < items; i+=2)
12820 {
12821 attribute=(char *) SvPV(ST(i-1),na);
12822 switch (*attribute)
12823 {
12824 case 'A':
12825 case 'a':
12826 {
12827 if (LocaleCompare(attribute,"antialias") == 0)
12828 {
12829 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12830 SvPV(ST(i),na));
12831 if (type < 0)
12832 {
12833 ThrowPerlException(exception,OptionError,"UnrecognizedType",
12834 SvPV(ST(i),na));
12835 break;
12836 }
12837 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12838 break;
12839 }
12840 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12841 attribute);
12842 break;
12843 }
12844 case 'd':
12845 case 'D':
12846 {
12847 if (LocaleCompare(attribute,"density") == 0)
12848 {
12849 CloneString(&draw_info->density,SvPV(ST(i),na));
12850 break;
12851 }
12852 if (LocaleCompare(attribute,"direction") == 0)
12853 {
12854 draw_info->direction=(DirectionType) ParseCommandOption(
12855 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12856 break;
12857 }
12858 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12859 attribute);
12860 break;
12861 }
12862 case 'e':
12863 case 'E':
12864 {
12865 if (LocaleCompare(attribute,"encoding") == 0)
12866 {
12867 CloneString(&draw_info->encoding,SvPV(ST(i),na));
12868 break;
12869 }
12870 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12871 attribute);
12872 break;
12873 }
12874 case 'f':
12875 case 'F':
12876 {
12877 if (LocaleCompare(attribute,"family") == 0)
12878 {
12879 CloneString(&draw_info->family,SvPV(ST(i),na));
12880 break;
12881 }
12882 if (LocaleCompare(attribute,"fill") == 0)
12883 {
12884 if (info)
12885 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12886 &draw_info->fill,exception);
12887 break;
12888 }
12889 if (LocaleCompare(attribute,"font") == 0)
12890 {
12891 CloneString(&draw_info->font,SvPV(ST(i),na));
12892 break;
12893 }
12894 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12895 attribute);
12896 break;
12897 }
12898 case 'g':
12899 case 'G':
12900 {
12901 if (LocaleCompare(attribute,"geometry") == 0)
12902 {
12903 CloneString(&draw_info->geometry,SvPV(ST(i),na));
12904 break;
12905 }
12906 if (LocaleCompare(attribute,"gravity") == 0)
12907 {
12908 draw_info->gravity=(GravityType) ParseCommandOption(
12909 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12910 break;
12911 }
12912 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12913 attribute);
12914 break;
12915 }
12916 case 'i':
12917 case 'I':
12918 {
12919 if (LocaleCompare(attribute,"interline-spacing") == 0)
12920 {
12921 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12922 draw_info->interline_spacing=geometry_info.rho;
12923 break;
12924 }
12925 if (LocaleCompare(attribute,"interword-spacing") == 0)
12926 {
12927 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12928 draw_info->interword_spacing=geometry_info.rho;
12929 break;
12930 }
12931 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12932 attribute);
12933 break;
12934 }
12935 case 'k':
12936 case 'K':
12937 {
12938 if (LocaleCompare(attribute,"kerning") == 0)
12939 {
12940 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12941 draw_info->kerning=geometry_info.rho;
12942 break;
12943 }
12944 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12945 attribute);
12946 break;
12947 }
12948 case 'p':
12949 case 'P':
12950 {
12951 if (LocaleCompare(attribute,"pointsize") == 0)
12952 {
12953 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12954 draw_info->pointsize=geometry_info.rho;
12955 break;
12956 }
12957 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12958 attribute);
12959 break;
12960 }
12961 case 'r':
12962 case 'R':
12963 {
12964 if (LocaleCompare(attribute,"rotate") == 0)
12965 {
12966 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12967 affine.rx=geometry_info.rho;
12968 affine.ry=geometry_info.sigma;
12969 if ((flags & SigmaValue) == 0)
12970 affine.ry=affine.rx;
12971 break;
12972 }
12973 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12974 attribute);
12975 break;
12976 }
12977 case 's':
12978 case 'S':
12979 {
12980 if (LocaleCompare(attribute,"scale") == 0)
12981 {
12982 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12983 affine.sx=geometry_info.rho;
12984 affine.sy=geometry_info.sigma;
12985 if ((flags & SigmaValue) == 0)
12986 affine.sy=affine.sx;
12987 break;
12988 }
12989 if (LocaleCompare(attribute,"skew") == 0)
12990 {
12991 double
12992 x_angle,
12993 y_angle;
12994
12995 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12996 x_angle=geometry_info.rho;
12997 y_angle=geometry_info.sigma;
12998 if ((flags & SigmaValue) == 0)
12999 y_angle=x_angle;
13000 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13001 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13002 break;
13003 }
13004 if (LocaleCompare(attribute,"stroke") == 0)
13005 {
13006 if (info)
13007 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13008 &draw_info->stroke,exception);
13009 break;
13010 }
13011 if (LocaleCompare(attribute,"style") == 0)
13012 {
13013 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13014 SvPV(ST(i),na));
13015 if (type < 0)
13016 {
13017 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13018 SvPV(ST(i),na));
13019 break;
13020 }
13021 draw_info->style=(StyleType) type;
13022 break;
13023 }
13024 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13025 attribute);
13026 break;
13027 }
13028 case 't':
13029 case 'T':
13030 {
13031 if (LocaleCompare(attribute,"text") == 0)
13032 {
13033 CloneString(&draw_info->text,SvPV(ST(i),na));
13034 break;
13035 }
13036 if (LocaleCompare(attribute,"translate") == 0)
13037 {
13038 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13039 affine.tx=geometry_info.rho;
13040 affine.ty=geometry_info.sigma;
13041 if ((flags & SigmaValue) == 0)
13042 affine.ty=affine.tx;
13043 break;
13044 }
13045 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13046 attribute);
13047 break;
13048 }
13049 case 'w':
13050 case 'W':
13051 {
13052 if (LocaleCompare(attribute,"weight") == 0)
13053 {
13054 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13055 draw_info->weight=(size_t) geometry_info.rho;
13056 break;
13057 }
13058 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13059 attribute);
13060 break;
13061 }
13062 case 'x':
13063 case 'X':
13064 {
13065 if (LocaleCompare(attribute,"x") == 0)
13066 {
13067 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13068 x=geometry_info.rho;
13069 break;
13070 }
13071 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13072 attribute);
13073 break;
13074 }
13075 case 'y':
13076 case 'Y':
13077 {
13078 if (LocaleCompare(attribute,"y") == 0)
13079 {
13080 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13081 y=geometry_info.rho;
13082 break;
13083 }
13084 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13085 attribute);
13086 break;
13087 }
13088 default:
13089 {
13090 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13091 attribute);
13092 break;
13093 }
13094 }
13095 }
13096 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13097 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13098 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13099 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13100 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13101 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13102 if (draw_info->geometry == (char *) NULL)
13103 {
13104 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013105 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013106 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013107 }
13108 status=GetTypeMetrics(image,draw_info,&metrics,exception);
13109 (void) CatchImageException(image);
13110 if (status == MagickFalse)
13111 PUSHs(&sv_undef);
13112 else
13113 {
13114 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13115 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13116 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13117 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13118 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13119 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13120 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13121 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13122 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13123 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13124 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13125 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13126 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13127 }
13128 draw_info=DestroyDrawInfo(draw_info);
13129
13130 PerlException:
13131 if (package_info != (struct PackageInfo *) NULL)
13132 DestroyPackageInfo(package_info);
13133 InheritPerlException(exception,perl_exception);
13134 exception=DestroyExceptionInfo(exception);
13135 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13136 }
13137
13138#
13139###############################################################################
13140# #
13141# #
13142# #
13143# Q u e r y M u l t i l i n e F o n t M e t r i c s #
13144# #
13145# #
13146# #
13147###############################################################################
13148#
13149#
13150void
13151QueryMultilineFontMetrics(ref,...)
13152 Image::Magick ref=NO_INIT
13153 ALIAS:
13154 querymultilinefontmetrics = 1
13155 PPCODE:
13156 {
13157 AffineMatrix
13158 affine,
13159 current;
13160
13161 AV
13162 *av;
13163
13164 char
13165 *attribute;
13166
13167 double
13168 x,
13169 y;
13170
13171 DrawInfo
13172 *draw_info;
13173
13174 ExceptionInfo
13175 *exception;
13176
13177 GeometryInfo
13178 geometry_info;
13179
13180 Image
13181 *image;
13182
13183 MagickBooleanType
13184 status;
13185
13186 MagickStatusType
13187 flags;
13188
13189 register ssize_t
13190 i;
13191
13192 ssize_t
13193 type;
13194
13195 struct PackageInfo
13196 *info,
13197 *package_info;
13198
13199 SV
13200 *perl_exception,
13201 *reference; /* reference is the SV* of ref=SvIV(reference) */
13202
13203 TypeMetric
13204 metrics;
13205
13206 PERL_UNUSED_VAR(ref);
13207 PERL_UNUSED_VAR(ix);
13208 exception=AcquireExceptionInfo();
13209 package_info=(struct PackageInfo *) NULL;
13210 perl_exception=newSVpv("",0);
13211 reference=SvRV(ST(0));
13212 av=(AV *) reference;
13213 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13214 exception);
13215 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13216 if (image == (Image *) NULL)
13217 {
13218 ThrowPerlException(exception,OptionError,"NoImagesDefined",
13219 PackageName);
13220 goto PerlException;
13221 }
13222 package_info=ClonePackageInfo(info,exception);
13223 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13224 CloneString(&draw_info->text,"");
13225 current=draw_info->affine;
13226 GetAffineMatrix(&affine);
13227 x=0.0;
13228 y=0.0;
13229 EXTEND(sp,7*items);
13230 for (i=2; i < items; i+=2)
13231 {
13232 attribute=(char *) SvPV(ST(i-1),na);
13233 switch (*attribute)
13234 {
13235 case 'A':
13236 case 'a':
13237 {
13238 if (LocaleCompare(attribute,"antialias") == 0)
13239 {
13240 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13241 SvPV(ST(i),na));
13242 if (type < 0)
13243 {
13244 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13245 SvPV(ST(i),na));
13246 break;
13247 }
13248 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13249 break;
13250 }
13251 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13252 attribute);
13253 break;
13254 }
13255 case 'd':
13256 case 'D':
13257 {
13258 if (LocaleCompare(attribute,"density") == 0)
13259 {
13260 CloneString(&draw_info->density,SvPV(ST(i),na));
13261 break;
13262 }
13263 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13264 attribute);
13265 break;
13266 }
13267 case 'e':
13268 case 'E':
13269 {
13270 if (LocaleCompare(attribute,"encoding") == 0)
13271 {
13272 CloneString(&draw_info->encoding,SvPV(ST(i),na));
13273 break;
13274 }
13275 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13276 attribute);
13277 break;
13278 }
13279 case 'f':
13280 case 'F':
13281 {
13282 if (LocaleCompare(attribute,"family") == 0)
13283 {
13284 CloneString(&draw_info->family,SvPV(ST(i),na));
13285 break;
13286 }
13287 if (LocaleCompare(attribute,"fill") == 0)
13288 {
13289 if (info)
13290 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13291 &draw_info->fill,exception);
13292 break;
13293 }
13294 if (LocaleCompare(attribute,"font") == 0)
13295 {
13296 CloneString(&draw_info->font,SvPV(ST(i),na));
13297 break;
13298 }
13299 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13300 attribute);
13301 break;
13302 }
13303 case 'g':
13304 case 'G':
13305 {
13306 if (LocaleCompare(attribute,"geometry") == 0)
13307 {
13308 CloneString(&draw_info->geometry,SvPV(ST(i),na));
13309 break;
13310 }
13311 if (LocaleCompare(attribute,"gravity") == 0)
13312 {
13313 draw_info->gravity=(GravityType) ParseCommandOption(
13314 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13315 break;
13316 }
13317 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13318 attribute);
13319 break;
13320 }
13321 case 'p':
13322 case 'P':
13323 {
13324 if (LocaleCompare(attribute,"pointsize") == 0)
13325 {
13326 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13327 draw_info->pointsize=geometry_info.rho;
13328 break;
13329 }
13330 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13331 attribute);
13332 break;
13333 }
13334 case 'r':
13335 case 'R':
13336 {
13337 if (LocaleCompare(attribute,"rotate") == 0)
13338 {
13339 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13340 affine.rx=geometry_info.rho;
13341 affine.ry=geometry_info.sigma;
13342 if ((flags & SigmaValue) == 0)
13343 affine.ry=affine.rx;
13344 break;
13345 }
13346 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13347 attribute);
13348 break;
13349 }
13350 case 's':
13351 case 'S':
13352 {
13353 if (LocaleCompare(attribute,"scale") == 0)
13354 {
13355 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13356 affine.sx=geometry_info.rho;
13357 affine.sy=geometry_info.sigma;
13358 if ((flags & SigmaValue) == 0)
13359 affine.sy=affine.sx;
13360 break;
13361 }
13362 if (LocaleCompare(attribute,"skew") == 0)
13363 {
13364 double
13365 x_angle,
13366 y_angle;
13367
13368 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13369 x_angle=geometry_info.rho;
13370 y_angle=geometry_info.sigma;
13371 if ((flags & SigmaValue) == 0)
13372 y_angle=x_angle;
13373 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13374 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13375 break;
13376 }
13377 if (LocaleCompare(attribute,"stroke") == 0)
13378 {
13379 if (info)
13380 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13381 &draw_info->stroke,exception);
13382 break;
13383 }
13384 if (LocaleCompare(attribute,"style") == 0)
13385 {
13386 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13387 SvPV(ST(i),na));
13388 if (type < 0)
13389 {
13390 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13391 SvPV(ST(i),na));
13392 break;
13393 }
13394 draw_info->style=(StyleType) type;
13395 break;
13396 }
13397 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13398 attribute);
13399 break;
13400 }
13401 case 't':
13402 case 'T':
13403 {
13404 if (LocaleCompare(attribute,"text") == 0)
13405 {
13406 CloneString(&draw_info->text,SvPV(ST(i),na));
13407 break;
13408 }
13409 if (LocaleCompare(attribute,"translate") == 0)
13410 {
13411 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13412 affine.tx=geometry_info.rho;
13413 affine.ty=geometry_info.sigma;
13414 if ((flags & SigmaValue) == 0)
13415 affine.ty=affine.tx;
13416 break;
13417 }
13418 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13419 attribute);
13420 break;
13421 }
13422 case 'w':
13423 case 'W':
13424 {
13425 if (LocaleCompare(attribute,"weight") == 0)
13426 {
13427 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13428 draw_info->weight=(size_t) geometry_info.rho;
13429 break;
13430 }
13431 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13432 attribute);
13433 break;
13434 }
13435 case 'x':
13436 case 'X':
13437 {
13438 if (LocaleCompare(attribute,"x") == 0)
13439 {
13440 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13441 x=geometry_info.rho;
13442 break;
13443 }
13444 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13445 attribute);
13446 break;
13447 }
13448 case 'y':
13449 case 'Y':
13450 {
13451 if (LocaleCompare(attribute,"y") == 0)
13452 {
13453 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13454 y=geometry_info.rho;
13455 break;
13456 }
13457 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13458 attribute);
13459 break;
13460 }
13461 default:
13462 {
13463 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13464 attribute);
13465 break;
13466 }
13467 }
13468 }
13469 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13470 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13471 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13472 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13473 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13474 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13475 if (draw_info->geometry == (char *) NULL)
13476 {
13477 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013478 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013479 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013480 }
13481 status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13482 (void) CatchException(exception);
13483 if (status == MagickFalse)
13484 PUSHs(&sv_undef);
13485 else
13486 {
13487 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13488 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13489 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13490 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13491 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13492 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13493 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13494 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13495 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13496 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13497 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13498 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13499 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13500 }
13501 draw_info=DestroyDrawInfo(draw_info);
13502
13503 PerlException:
13504 if (package_info != (struct PackageInfo *) NULL)
13505 DestroyPackageInfo(package_info);
13506 InheritPerlException(exception,perl_exception);
13507 exception=DestroyExceptionInfo(exception);
13508 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13509 }
13510
13511#
13512###############################################################################
13513# #
13514# #
13515# #
13516# Q u e r y F o r m a t #
13517# #
13518# #
13519# #
13520###############################################################################
13521#
13522#
13523void
13524QueryFormat(ref,...)
13525 Image::Magick ref=NO_INIT
13526 ALIAS:
13527 queryformat = 1
13528 PPCODE:
13529 {
13530 char
13531 *name;
13532
13533 ExceptionInfo
13534 *exception;
13535
13536 register ssize_t
13537 i;
13538
13539 SV
13540 *perl_exception;
13541
13542 volatile const MagickInfo
13543 *magick_info;
13544
13545 PERL_UNUSED_VAR(ref);
13546 PERL_UNUSED_VAR(ix);
13547 exception=AcquireExceptionInfo();
13548 perl_exception=newSVpv("",0);
13549 if (items == 1)
13550 {
13551 char
cristy151b66d2015-04-15 10:50:31 +000013552 format[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000013553
13554 const MagickInfo
13555 **format_list;
13556
13557 size_t
13558 types;
13559
13560 format_list=GetMagickInfoList("*",&types,exception);
13561 EXTEND(sp,types);
13562 for (i=0; i < (ssize_t) types; i++)
13563 {
cristy151b66d2015-04-15 10:50:31 +000013564 (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000013565 LocaleLower(format);
13566 PUSHs(sv_2mortal(newSVpv(format,0)));
13567 }
13568 format_list=(const MagickInfo **)
13569 RelinquishMagickMemory((MagickInfo *) format_list);
13570 goto PerlException;
13571 }
13572 EXTEND(sp,8*items);
13573 for (i=1; i < items; i++)
13574 {
13575 name=(char *) SvPV(ST(i),na);
13576 magick_info=GetMagickInfo(name,exception);
13577 if (magick_info == (const MagickInfo *) NULL)
13578 {
13579 PUSHs(&sv_undef);
13580 continue;
13581 }
cristy4a3ce0a2013-08-03 20:06:59 +000013582 if (magick_info->description == (char *) NULL)
13583 PUSHs(&sv_undef);
13584 else
13585 PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13586 if (magick_info->module == (char *) NULL)
13587 PUSHs(&sv_undef);
13588 else
13589 PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13590 }
13591
13592 PerlException:
13593 InheritPerlException(exception,perl_exception);
13594 exception=DestroyExceptionInfo(exception);
13595 SvREFCNT_dec(perl_exception);
13596 }
13597
13598#
13599###############################################################################
13600# #
13601# #
13602# #
13603# Q u e r y O p t i o n #
13604# #
13605# #
13606# #
13607###############################################################################
13608#
13609#
13610void
13611QueryOption(ref,...)
13612 Image::Magick ref=NO_INIT
13613 ALIAS:
13614 queryoption = 1
13615 PPCODE:
13616 {
13617 char
13618 **options;
13619
13620 ExceptionInfo
13621 *exception;
13622
13623 register ssize_t
13624 i;
13625
13626 ssize_t
13627 j,
13628 option;
13629
13630 SV
13631 *perl_exception;
13632
13633 PERL_UNUSED_VAR(ref);
13634 PERL_UNUSED_VAR(ix);
13635 exception=AcquireExceptionInfo();
13636 perl_exception=newSVpv("",0);
13637 EXTEND(sp,8*items);
13638 for (i=1; i < items; i++)
13639 {
13640 option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13641 SvPV(ST(i),na));
13642 options=GetCommandOptions((CommandOption) option);
13643 if (options == (char **) NULL)
13644 PUSHs(&sv_undef);
13645 else
13646 {
13647 for (j=0; options[j] != (char *) NULL; j++)
13648 PUSHs(sv_2mortal(newSVpv(options[j],0)));
13649 options=DestroyStringList(options);
13650 }
13651 }
13652
13653 InheritPerlException(exception,perl_exception);
13654 exception=DestroyExceptionInfo(exception);
13655 SvREFCNT_dec(perl_exception);
13656 }
13657
13658#
13659###############################################################################
13660# #
13661# #
13662# #
13663# R e a d #
13664# #
13665# #
13666# #
13667###############################################################################
13668#
13669#
13670void
13671Read(ref,...)
13672 Image::Magick ref=NO_INIT
13673 ALIAS:
13674 ReadImage = 1
13675 read = 2
13676 readimage = 3
13677 PPCODE:
13678 {
13679 AV
13680 *av;
13681
13682 char
13683 **keep,
13684 **list;
13685
13686 ExceptionInfo
13687 *exception;
13688
13689 HV
13690 *hv;
13691
13692 Image
13693 *image;
13694
13695 int
13696 n;
13697
13698 MagickBooleanType
13699 status;
13700
13701 register char
13702 **p;
13703
13704 register ssize_t
13705 i;
13706
13707 ssize_t
13708 ac,
13709 number_images;
13710
13711 STRLEN
13712 *length;
13713
13714 struct PackageInfo
13715 *info,
13716 *package_info;
13717
13718 SV
13719 *perl_exception, /* Perl variable for storing messages */
13720 *reference,
13721 *rv,
13722 *sv;
13723
13724 PERL_UNUSED_VAR(ref);
13725 PERL_UNUSED_VAR(ix);
13726 exception=AcquireExceptionInfo();
13727 perl_exception=newSVpv("",0);
13728 sv=NULL;
13729 package_info=(struct PackageInfo *) NULL;
13730 number_images=0;
13731 ac=(items < 2) ? 1 : items-1;
13732 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13733 keep=list;
13734 length=(STRLEN *) NULL;
13735 if (list == (char **) NULL)
13736 {
13737 ThrowPerlException(exception,ResourceLimitError,
13738 "MemoryAllocationFailed",PackageName);
13739 goto PerlException;
13740 }
13741 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13742 if (length == (STRLEN *) NULL)
13743 {
13744 ThrowPerlException(exception,ResourceLimitError,
13745 "MemoryAllocationFailed",PackageName);
13746 goto PerlException;
13747 }
13748 if (sv_isobject(ST(0)) == 0)
13749 {
13750 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13751 PackageName);
13752 goto PerlException;
13753 }
13754 reference=SvRV(ST(0));
13755 hv=SvSTASH(reference);
13756 if (SvTYPE(reference) != SVt_PVAV)
13757 {
13758 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13759 PackageName);
13760 goto PerlException;
13761 }
13762 av=(AV *) reference;
13763 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13764 exception);
13765 package_info=ClonePackageInfo(info,exception);
13766 n=1;
13767 if (items <= 1)
13768 *list=(char *) (*package_info->image_info->filename ?
13769 package_info->image_info->filename : "XC:black");
13770 else
13771 for (n=0, i=0; i < ac; i++)
13772 {
13773 list[n]=(char *) SvPV(ST(i+1),length[n]);
13774 if ((items >= 3) && strEQcase(list[n],"blob"))
13775 {
13776 void
13777 *blob;
13778
13779 i++;
13780 blob=(void *) (SvPV(ST(i+1),length[n]));
13781 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13782 }
13783 if ((items >= 3) && strEQcase(list[n],"filename"))
13784 continue;
13785 if ((items >= 3) && strEQcase(list[n],"file"))
13786 {
13787 FILE
13788 *file;
13789
13790 PerlIO
13791 *io_info;
13792
13793 i++;
13794 io_info=IoIFP(sv_2io(ST(i+1)));
13795 if (io_info == (PerlIO *) NULL)
13796 {
13797 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13798 PackageName);
13799 continue;
13800 }
13801 file=PerlIO_findFILE(io_info);
13802 if (file == (FILE *) NULL)
13803 {
13804 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13805 PackageName);
13806 continue;
13807 }
13808 SetImageInfoFile(package_info->image_info,file);
13809 }
13810 if ((items >= 3) && strEQcase(list[n],"magick"))
13811 continue;
13812 n++;
13813 }
13814 list[n]=(char *) NULL;
13815 keep=list;
13816 status=ExpandFilenames(&n,&list);
13817 if (status == MagickFalse)
13818 {
13819 ThrowPerlException(exception,ResourceLimitError,
13820 "MemoryAllocationFailed",PackageName);
13821 goto PerlException;
13822 }
13823 number_images=0;
13824 for (i=0; i < n; i++)
13825 {
13826 if ((package_info->image_info->file == (FILE *) NULL) &&
13827 (package_info->image_info->blob == (void *) NULL))
13828 image=ReadImages(package_info->image_info,list[i],exception);
13829 else
13830 {
13831 image=ReadImages(package_info->image_info,
13832 package_info->image_info->filename,exception);
13833 if (image != (Image *) NULL)
13834 DisassociateImageStream(image);
13835 }
13836 if (image == (Image *) NULL)
13837 break;
13838 for ( ; image; image=image->next)
13839 {
13840 AddImageToRegistry(sv,image);
13841 rv=newRV(sv);
13842 av_push(av,sv_bless(rv,hv));
13843 SvREFCNT_dec(sv);
13844 number_images++;
13845 }
13846 }
13847 /*
13848 Free resources.
13849 */
13850 for (i=0; i < n; i++)
13851 if (list[i] != (char *) NULL)
13852 for (p=keep; list[i] != *p++; )
13853 if (*p == (char *) NULL)
13854 {
13855 list[i]=(char *) RelinquishMagickMemory(list[i]);
13856 break;
13857 }
13858
13859 PerlException:
13860 if (package_info != (struct PackageInfo *) NULL)
13861 DestroyPackageInfo(package_info);
13862 if (list && (list != keep))
13863 list=(char **) RelinquishMagickMemory(list);
13864 if (keep)
13865 keep=(char **) RelinquishMagickMemory(keep);
13866 if (length)
13867 length=(STRLEN *) RelinquishMagickMemory(length);
13868 InheritPerlException(exception,perl_exception);
13869 exception=DestroyExceptionInfo(exception);
13870 sv_setiv(perl_exception,(IV) number_images);
13871 SvPOK_on(perl_exception);
13872 ST(0)=sv_2mortal(perl_exception);
13873 XSRETURN(1);
13874 }
13875
13876#
13877###############################################################################
13878# #
13879# #
13880# #
13881# R e m o t e #
13882# #
13883# #
13884# #
13885###############################################################################
13886#
13887#
13888void
13889Remote(ref,...)
13890 Image::Magick ref=NO_INIT
13891 ALIAS:
13892 RemoteCommand = 1
13893 remote = 2
13894 remoteCommand = 3
13895 PPCODE:
13896 {
13897 AV
13898 *av;
13899
13900 ExceptionInfo
13901 *exception;
13902
13903 register ssize_t
13904 i;
13905
13906 SV
13907 *perl_exception,
13908 *reference;
13909
13910 struct PackageInfo
13911 *info;
13912
13913 PERL_UNUSED_VAR(ref);
13914 PERL_UNUSED_VAR(ix);
13915 exception=AcquireExceptionInfo();
13916 perl_exception=newSVpv("",0);
13917 reference=SvRV(ST(0));
13918 av=(AV *) reference;
13919 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13920 exception);
13921 for (i=1; i < items; i++)
13922 (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13923 SvPV(ST(i),na),exception);
13924 InheritPerlException(exception,perl_exception);
13925 exception=DestroyExceptionInfo(exception);
13926 SvREFCNT_dec(perl_exception); /* throw away all errors */
13927 }
13928
13929#
13930###############################################################################
13931# #
13932# #
13933# #
13934# S e t #
13935# #
13936# #
13937# #
13938###############################################################################
13939#
13940#
13941void
13942Set(ref,...)
13943 Image::Magick ref=NO_INIT
13944 ALIAS:
13945 SetAttributes = 1
13946 SetAttribute = 2
13947 set = 3
13948 setattributes = 4
13949 setattribute = 5
13950 PPCODE:
13951 {
13952 ExceptionInfo
13953 *exception;
13954
13955 Image
13956 *image;
13957
13958 register ssize_t
13959 i;
13960
13961 struct PackageInfo
13962 *info;
13963
13964 SV
13965 *perl_exception,
13966 *reference; /* reference is the SV* of ref=SvIV(reference) */
13967
13968 PERL_UNUSED_VAR(ref);
13969 PERL_UNUSED_VAR(ix);
13970 exception=AcquireExceptionInfo();
13971 perl_exception=newSVpv("",0);
13972 if (sv_isobject(ST(0)) == 0)
13973 {
13974 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13975 PackageName);
13976 goto PerlException;
13977 }
13978 reference=SvRV(ST(0));
13979 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13980 if (items == 2)
13981 SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13982 else
13983 for (i=2; i < items; i+=2)
13984 SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13985
13986 PerlException:
13987 InheritPerlException(exception,perl_exception);
13988 exception=DestroyExceptionInfo(exception);
13989 sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13990 SvPOK_on(perl_exception);
13991 ST(0)=sv_2mortal(perl_exception);
13992 XSRETURN(1);
13993 }
13994
13995#
13996###############################################################################
13997# #
13998# #
13999# #
14000# S e t P i x e l #
14001# #
14002# #
14003# #
14004###############################################################################
14005#
14006#
14007void
14008SetPixel(ref,...)
14009 Image::Magick ref=NO_INIT
14010 ALIAS:
14011 setpixel = 1
14012 setPixel = 2
14013 PPCODE:
14014 {
14015 AV
14016 *av;
14017
14018 char
14019 *attribute;
14020
14021 ChannelType
14022 channel,
14023 channel_mask;
14024
14025 ExceptionInfo
14026 *exception;
14027
14028 Image
14029 *image;
14030
14031 MagickBooleanType
14032 normalize;
14033
14034 RectangleInfo
14035 region;
14036
14037 register ssize_t
14038 i;
14039
14040 register Quantum
14041 *q;
14042
14043 ssize_t
14044 option;
14045
14046 struct PackageInfo
14047 *info;
14048
14049 SV
14050 *perl_exception,
14051 *reference; /* reference is the SV* of ref=SvIV(reference) */
14052
14053 PERL_UNUSED_VAR(ref);
14054 PERL_UNUSED_VAR(ix);
14055 exception=AcquireExceptionInfo();
14056 perl_exception=newSVpv("",0);
14057 reference=SvRV(ST(0));
14058 av=(AV *) reference;
14059 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14060 exception);
14061 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14062 if (image == (Image *) NULL)
14063 {
14064 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14065 PackageName);
14066 goto PerlException;
14067 }
14068 av=(AV *) NULL;
14069 normalize=MagickTrue;
14070 region.x=0;
14071 region.y=0;
14072 region.width=image->columns;
14073 region.height=1;
14074 if (items == 1)
14075 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14076 channel=DefaultChannels;
14077 for (i=2; i < items; i+=2)
14078 {
14079 attribute=(char *) SvPV(ST(i-1),na);
14080 switch (*attribute)
14081 {
14082 case 'C':
14083 case 'c':
14084 {
14085 if (LocaleCompare(attribute,"channel") == 0)
14086 {
14087 ssize_t
14088 option;
14089
14090 option=ParseChannelOption(SvPV(ST(i),na));
14091 if (option < 0)
14092 {
14093 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14094 SvPV(ST(i),na));
14095 return;
14096 }
14097 channel=(ChannelType) option;
14098 break;
14099 }
14100 if (LocaleCompare(attribute,"color") == 0)
14101 {
14102 if (SvTYPE(ST(i)) != SVt_RV)
14103 {
14104 char
cristy151b66d2015-04-15 10:50:31 +000014105 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014106
cristy151b66d2015-04-15 10:50:31 +000014107 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +000014108 "invalid %.60s value",attribute);
14109 ThrowPerlException(exception,OptionError,message,
14110 SvPV(ST(i),na));
14111 }
14112 av=(AV *) SvRV(ST(i));
14113 break;
14114 }
14115 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14116 attribute);
14117 break;
14118 }
14119 case 'g':
14120 case 'G':
14121 {
14122 if (LocaleCompare(attribute,"geometry") == 0)
14123 {
14124 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14125 break;
14126 }
14127 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14128 attribute);
14129 break;
14130 }
14131 case 'N':
14132 case 'n':
14133 {
14134 if (LocaleCompare(attribute,"normalize") == 0)
14135 {
14136 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14137 SvPV(ST(i),na));
14138 if (option < 0)
14139 {
14140 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14141 SvPV(ST(i),na));
14142 break;
14143 }
14144 normalize=option != 0 ? MagickTrue : MagickFalse;
14145 break;
14146 }
14147 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14148 attribute);
14149 break;
14150 }
14151 case 'x':
14152 case 'X':
14153 {
14154 if (LocaleCompare(attribute,"x") == 0)
14155 {
14156 region.x=SvIV(ST(i));
14157 break;
14158 }
14159 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14160 attribute);
14161 break;
14162 }
14163 case 'y':
14164 case 'Y':
14165 {
14166 if (LocaleCompare(attribute,"y") == 0)
14167 {
14168 region.y=SvIV(ST(i));
14169 break;
14170 }
14171 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14172 attribute);
14173 break;
14174 }
14175 default:
14176 {
14177 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14178 attribute);
14179 break;
14180 }
14181 }
14182 }
14183 (void) SetImageStorageClass(image,DirectClass,exception);
14184 channel_mask=SetImageChannelMask(image,channel);
14185 q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14186 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14187 (SvTYPE(av) != SVt_PVAV))
14188 PUSHs(&sv_undef);
14189 else
14190 {
14191 double
14192 scale;
14193
14194 register ssize_t
14195 i;
14196
14197 i=0;
14198 scale=1.0;
14199 if (normalize != MagickFalse)
14200 scale=QuantumRange;
14201 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14202 (i <= av_len(av)))
14203 {
14204 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14205 av_fetch(av,i,0)))),q);
14206 i++;
14207 }
14208 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14209 (i <= av_len(av)))
14210 {
14211 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14212 av_fetch(av,i,0)))),q);
14213 i++;
14214 }
14215 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14216 (i <= av_len(av)))
14217 {
14218 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14219 av_fetch(av,i,0)))),q);
14220 i++;
14221 }
14222 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14223 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14224 {
14225 SetPixelBlack(image,ClampToQuantum(scale*
14226 SvNV(*(av_fetch(av,i,0)))),q);
14227 i++;
14228 }
14229 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14230 (i <= av_len(av)))
14231 {
14232 SetPixelAlpha(image,ClampToQuantum(scale*
14233 SvNV(*(av_fetch(av,i,0)))),q);
14234 i++;
14235 }
14236 (void) SyncAuthenticPixels(image,exception);
14237 }
14238 (void) SetImageChannelMask(image,channel_mask);
14239
14240 PerlException:
14241 InheritPerlException(exception,perl_exception);
14242 exception=DestroyExceptionInfo(exception);
14243 SvREFCNT_dec(perl_exception);
14244 }
14245
14246#
14247###############################################################################
14248# #
14249# #
14250# #
Cristybba545b2018-07-04 15:00:12 -040014251# S e t P i x e l s #
14252# #
14253# #
14254# #
14255###############################################################################
14256#
14257#
14258void
14259SetPixels(ref,...)
14260 Image::Magick ref=NO_INIT
14261 ALIAS:
14262 setpixels = 1
14263 setPixels = 2
14264 PPCODE:
14265 {
14266 AV
14267 *av;
14268
14269 char
14270 *attribute;
14271
14272 ChannelType
14273 channel,
14274 channel_mask;
14275
14276 ExceptionInfo
14277 *exception;
14278
14279 Image
14280 *image;
14281
14282 RectangleInfo
14283 region;
14284
14285 register ssize_t
14286 i;
14287
14288 register Quantum
14289 *q;
14290
14291 struct PackageInfo
14292 *info;
14293
14294 SV
14295 *perl_exception,
14296 *reference; /* reference is the SV* of ref=SvIV(reference) */
14297
14298 PERL_UNUSED_VAR(ref);
14299 PERL_UNUSED_VAR(ix);
14300 exception=AcquireExceptionInfo();
14301 perl_exception=newSVpv("",0);
14302 reference=SvRV(ST(0));
14303 av=(AV *) reference;
14304 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14305 exception);
14306 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14307 if (image == (Image *) NULL)
14308 {
14309 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14310 PackageName);
14311 goto PerlException;
14312 }
14313 av=(AV *) NULL;
14314 region.x=0;
14315 region.y=0;
14316 region.width=image->columns;
14317 region.height=1;
14318 if (items == 1)
14319 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14320 channel=DefaultChannels;
14321 for (i=2; i < items; i+=2)
14322 {
14323 attribute=(char *) SvPV(ST(i-1),na);
14324 switch (*attribute)
14325 {
14326 case 'C':
14327 case 'c':
14328 {
14329 if (LocaleCompare(attribute,"channel") == 0)
14330 {
14331 ssize_t
14332 option;
14333
14334 option=ParseChannelOption(SvPV(ST(i),na));
14335 if (option < 0)
14336 {
14337 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14338 SvPV(ST(i),na));
14339 return;
14340 }
14341 channel=(ChannelType) option;
14342 break;
14343 }
14344 if (LocaleCompare(attribute,"color") == 0)
14345 {
14346 if (SvTYPE(ST(i)) != SVt_RV)
14347 {
14348 char
14349 message[MagickPathExtent];
14350
14351 (void) FormatLocaleString(message,MagickPathExtent,
14352 "invalid %.60s value",attribute);
14353 ThrowPerlException(exception,OptionError,message,
14354 SvPV(ST(i),na));
14355 }
14356 av=(AV *) SvRV(ST(i));
14357 break;
14358 }
14359 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14360 attribute);
14361 break;
14362 }
14363 case 'g':
14364 case 'G':
14365 {
14366 if (LocaleCompare(attribute,"geometry") == 0)
14367 {
14368 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14369 break;
14370 }
14371 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14372 attribute);
14373 break;
14374 }
14375 case 'h':
14376 case 'H':
14377 {
14378 if (LocaleCompare(attribute,"height") == 0)
14379 {
14380 region.height=SvIV(ST(i));
14381 break;
14382 }
14383 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14384 attribute);
14385 break;
14386 }
14387 case 'w':
14388 case 'W':
14389 {
14390 if (LocaleCompare(attribute,"width") == 0)
14391 {
14392 region.width=SvIV(ST(i));
14393 break;
14394 }
14395 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14396 attribute);
14397 break;
14398 }
14399 case 'x':
14400 case 'X':
14401 {
14402 if (LocaleCompare(attribute,"x") == 0)
14403 {
14404 region.x=SvIV(ST(i));
14405 break;
14406 }
14407 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14408 attribute);
14409 break;
14410 }
14411 case 'y':
14412 case 'Y':
14413 {
14414 if (LocaleCompare(attribute,"y") == 0)
14415 {
14416 region.y=SvIV(ST(i));
14417 break;
14418 }
14419 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14420 attribute);
14421 break;
14422 }
14423 default:
14424 {
14425 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14426 attribute);
14427 break;
14428 }
14429 }
14430 }
14431 (void) SetImageStorageClass(image,DirectClass,exception);
14432 channel_mask=SetImageChannelMask(image,channel);
14433 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
14434 exception);
14435 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14436 (SvTYPE(av) != SVt_PVAV))
14437 PUSHs(&sv_undef);
14438 else
14439 {
14440 double
14441 scale;
14442
14443 register ssize_t
14444 i,
14445 n,
14446 number_pixels;
14447
14448 i=0;
14449 n=0;
14450 scale=(double) QuantumRange;
14451 number_pixels=region.width*region.height;
14452 while ((n < number_pixels) && (i < av_len(av)))
14453 {
14454 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14455 (i <= av_len(av)))
14456 {
14457 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14458 av_fetch(av,i,0)))),q);
14459 i++;
14460 }
14461 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14462 (i <= av_len(av)))
14463 {
14464 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14465 av_fetch(av,i,0)))),q);
14466 i++;
14467 }
14468 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14469 (i <= av_len(av)))
14470 {
14471 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14472 av_fetch(av,i,0)))),q);
14473 i++;
14474 }
14475 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14476 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14477 {
14478 SetPixelBlack(image,ClampToQuantum(scale*
14479 SvNV(*(av_fetch(av,i,0)))),q);
14480 i++;
14481 }
14482 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14483 (i <= av_len(av)))
14484 {
14485 SetPixelAlpha(image,ClampToQuantum(scale*
14486 SvNV(*(av_fetch(av,i,0)))),q);
14487 i++;
14488 }
14489 n++;
14490 q+=image->number_channels;
14491 }
14492 (void) SyncAuthenticPixels(image,exception);
14493 }
14494 (void) SetImageChannelMask(image,channel_mask);
14495
14496 PerlException:
14497 InheritPerlException(exception,perl_exception);
14498 exception=DestroyExceptionInfo(exception);
14499 SvREFCNT_dec(perl_exception);
14500 }
14501
14502#
14503###############################################################################
14504# #
14505# #
14506# #
cristy4a3ce0a2013-08-03 20:06:59 +000014507# S m u s h #
14508# #
14509# #
14510# #
14511###############################################################################
14512#
14513#
14514void
14515Smush(ref,...)
14516 Image::Magick ref=NO_INIT
14517 ALIAS:
14518 SmushImage = 1
14519 smush = 2
14520 smushimage = 3
14521 PPCODE:
14522 {
14523 AV
14524 *av;
14525
14526 char
14527 *attribute;
14528
14529 ExceptionInfo
14530 *exception;
14531
14532 HV
14533 *hv;
14534
14535 Image
14536 *image;
14537
14538 register ssize_t
14539 i;
14540
14541 ssize_t
14542 offset,
14543 stack;
14544
14545 struct PackageInfo
14546 *info;
14547
14548 SV
14549 *av_reference,
14550 *perl_exception,
14551 *reference,
14552 *rv,
14553 *sv;
14554
14555 PERL_UNUSED_VAR(ref);
14556 PERL_UNUSED_VAR(ix);
14557 exception=AcquireExceptionInfo();
14558 perl_exception=newSVpv("",0);
14559 sv=NULL;
14560 attribute=NULL;
14561 av=NULL;
14562 if (sv_isobject(ST(0)) == 0)
14563 {
14564 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14565 PackageName);
14566 goto PerlException;
14567 }
14568 reference=SvRV(ST(0));
14569 hv=SvSTASH(reference);
14570 av=newAV();
14571 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14572 SvREFCNT_dec(av);
14573 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14574 if (image == (Image *) NULL)
14575 {
14576 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14577 PackageName);
14578 goto PerlException;
14579 }
14580 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14581 /*
14582 Get options.
14583 */
14584 offset=0;
14585 stack=MagickTrue;
14586 for (i=2; i < items; i+=2)
14587 {
14588 attribute=(char *) SvPV(ST(i-1),na);
14589 switch (*attribute)
14590 {
14591 case 'O':
14592 case 'o':
14593 {
14594 if (LocaleCompare(attribute,"offset") == 0)
14595 {
14596 offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14597 break;
14598 }
14599 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14600 attribute);
14601 break;
14602 }
14603 case 'S':
14604 case 's':
14605 {
14606 if (LocaleCompare(attribute,"stack") == 0)
14607 {
14608 stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14609 SvPV(ST(i),na));
14610 if (stack < 0)
14611 {
14612 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14613 SvPV(ST(i),na));
14614 return;
14615 }
14616 break;
14617 }
14618 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14619 attribute);
14620 break;
14621 }
14622 default:
14623 {
14624 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14625 attribute);
14626 break;
14627 }
14628 }
14629 }
14630 image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14631 exception);
14632 if (image == (Image *) NULL)
14633 goto PerlException;
14634 for ( ; image; image=image->next)
14635 {
14636 AddImageToRegistry(sv,image);
14637 rv=newRV(sv);
14638 av_push(av,sv_bless(rv,hv));
14639 SvREFCNT_dec(sv);
14640 }
14641 exception=DestroyExceptionInfo(exception);
14642 ST(0)=av_reference;
14643 SvREFCNT_dec(perl_exception);
14644 XSRETURN(1);
14645
14646 PerlException:
14647 InheritPerlException(exception,perl_exception);
14648 exception=DestroyExceptionInfo(exception);
14649 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14650 SvPOK_on(perl_exception);
14651 ST(0)=sv_2mortal(perl_exception);
14652 XSRETURN(1);
14653 }
14654
14655#
14656###############################################################################
14657# #
14658# #
14659# #
14660# S t a t i s t i c s #
14661# #
14662# #
14663# #
14664###############################################################################
14665#
14666#
14667void
14668Statistics(ref,...)
14669 Image::Magick ref=NO_INIT
14670 ALIAS:
14671 StatisticsImage = 1
14672 statistics = 2
14673 statisticsimage = 3
14674 PPCODE:
14675 {
14676#define ChannelStatistics(channel) \
14677{ \
cristy151b66d2015-04-15 10:50:31 +000014678 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014679 (double) channel_statistics[channel].depth); \
14680 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014681 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014682 channel_statistics[channel].minima/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014683 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014684 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014685 channel_statistics[channel].maxima/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014686 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014687 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014688 channel_statistics[channel].mean/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014689 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014690 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014691 channel_statistics[channel].standard_deviation/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014692 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014693 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014694 channel_statistics[channel].kurtosis); \
14695 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014696 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014697 channel_statistics[channel].skewness); \
14698 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014699 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy275bdd92014-11-08 23:45:03 +000014700 channel_statistics[channel].entropy); \
14701 PUSHs(sv_2mortal(newSVpv(message,0))); \
cristy4a3ce0a2013-08-03 20:06:59 +000014702}
14703
14704 AV
14705 *av;
14706
14707 char
cristy151b66d2015-04-15 10:50:31 +000014708 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014709
14710 ChannelStatistics
14711 *channel_statistics;
14712
cristy4a3ce0a2013-08-03 20:06:59 +000014713 ExceptionInfo
14714 *exception;
14715
14716 Image
14717 *image;
14718
14719 ssize_t
14720 count;
14721
14722 struct PackageInfo
14723 *info;
14724
14725 SV
14726 *perl_exception,
14727 *reference;
14728
14729 PERL_UNUSED_VAR(ref);
14730 PERL_UNUSED_VAR(ix);
14731 exception=AcquireExceptionInfo();
14732 perl_exception=newSVpv("",0);
14733 av=NULL;
14734 if (sv_isobject(ST(0)) == 0)
14735 {
14736 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14737 PackageName);
14738 goto PerlException;
14739 }
14740 reference=SvRV(ST(0));
14741 av=newAV();
14742 SvREFCNT_dec(av);
14743 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14744 if (image == (Image *) NULL)
14745 {
14746 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14747 PackageName);
14748 goto PerlException;
14749 }
cristy4a3ce0a2013-08-03 20:06:59 +000014750 count=0;
14751 for ( ; image; image=image->next)
14752 {
Cristyb1710fe2017-02-11 13:51:48 -050014753 register size_t
14754 i;
14755
cristy4a3ce0a2013-08-03 20:06:59 +000014756 channel_statistics=GetImageStatistics(image,exception);
14757 if (channel_statistics == (ChannelStatistics *) NULL)
14758 continue;
14759 count++;
Cristyb1710fe2017-02-11 13:51:48 -050014760 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
14761 {
14762 PixelChannel channel=GetPixelChannelChannel(image,i);
14763 PixelTrait traits=GetPixelChannelTraits(image,channel);
Cristy5a854dc2017-02-11 15:43:46 -050014764 if (traits == UndefinedPixelTrait)
Cristyb1710fe2017-02-11 13:51:48 -050014765 continue;
Cristy5a854dc2017-02-11 15:43:46 -050014766 EXTEND(sp,8*(i+1)*count);
Cristyb1710fe2017-02-11 13:51:48 -050014767 ChannelStatistics(channel);
14768 }
Cristy25813902017-02-11 15:47:52 -050014769 EXTEND(sp,8*(i+1)*count);
14770 ChannelStatistics(CompositePixelChannel);
cristy4a3ce0a2013-08-03 20:06:59 +000014771 channel_statistics=(ChannelStatistics *)
14772 RelinquishMagickMemory(channel_statistics);
14773 }
14774
14775 PerlException:
14776 InheritPerlException(exception,perl_exception);
14777 exception=DestroyExceptionInfo(exception);
14778 SvREFCNT_dec(perl_exception);
14779 }
14780
14781#
14782###############################################################################
14783# #
14784# #
14785# #
14786# S y n c A u t h e n t i c P i x e l s #
14787# #
14788# #
14789# #
14790###############################################################################
14791#
14792#
14793void
14794SyncAuthenticPixels(ref,...)
14795 Image::Magick ref = NO_INIT
14796 ALIAS:
14797 Syncauthenticpixels = 1
14798 SyncImagePixels = 2
14799 syncimagepixels = 3
14800 CODE:
14801 {
14802 ExceptionInfo
14803 *exception;
14804
14805 Image
14806 *image;
14807
14808 MagickBooleanType
14809 status;
14810
14811 struct PackageInfo
14812 *info;
14813
14814 SV
14815 *perl_exception,
14816 *reference;
14817
14818 PERL_UNUSED_VAR(ref);
14819 PERL_UNUSED_VAR(ix);
14820 exception=AcquireExceptionInfo();
14821 perl_exception=newSVpv("",0);
14822 if (sv_isobject(ST(0)) == 0)
14823 {
14824 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14825 PackageName);
14826 goto PerlException;
14827 }
14828
14829 reference=SvRV(ST(0));
14830 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14831 if (image == (Image *) NULL)
14832 {
14833 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14834 PackageName);
14835 goto PerlException;
14836 }
14837
14838 status=SyncAuthenticPixels(image,exception);
14839 if (status != MagickFalse)
14840 return;
14841
14842 PerlException:
14843 InheritPerlException(exception,perl_exception);
14844 exception=DestroyExceptionInfo(exception);
14845 SvREFCNT_dec(perl_exception); /* throw away all errors */
14846 }
14847
14848#
14849###############################################################################
14850# #
14851# #
14852# #
cristy4a3ce0a2013-08-03 20:06:59 +000014853# W r i t e #
14854# #
14855# #
14856# #
14857###############################################################################
14858#
14859#
14860void
14861Write(ref,...)
14862 Image::Magick ref=NO_INIT
14863 ALIAS:
14864 WriteImage = 1
14865 write = 2
14866 writeimage = 3
14867 PPCODE:
14868 {
14869 char
cristy151b66d2015-04-15 10:50:31 +000014870 filename[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014871
14872 ExceptionInfo
14873 *exception;
14874
14875 Image
14876 *image,
14877 *next;
14878
14879 register ssize_t
14880 i;
14881
14882 ssize_t
14883 number_images,
14884 scene;
14885
14886 struct PackageInfo
14887 *info,
14888 *package_info;
14889
14890 SV
14891 *perl_exception,
14892 *reference;
14893
14894 PERL_UNUSED_VAR(ref);
14895 PERL_UNUSED_VAR(ix);
14896 exception=AcquireExceptionInfo();
14897 perl_exception=newSVpv("",0);
14898 number_images=0;
14899 package_info=(struct PackageInfo *) NULL;
14900 if (sv_isobject(ST(0)) == 0)
14901 {
14902 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14903 PackageName);
14904 goto PerlException;
14905 }
14906 reference=SvRV(ST(0));
14907 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14908 if (image == (Image *) NULL)
14909 {
14910 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14911 PackageName);
14912 goto PerlException;
14913 }
Cristyb4ee45c2017-09-27 17:58:55 -040014914 scene=0;
14915 for (next=image; next; next=next->next)
14916 next->scene=scene++;
cristy4a3ce0a2013-08-03 20:06:59 +000014917 package_info=ClonePackageInfo(info,exception);
14918 if (items == 2)
14919 SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14920 else
14921 if (items > 2)
14922 for (i=2; i < items; i+=2)
14923 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14924 exception);
14925 (void) CopyMagickString(filename,package_info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +000014926 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000014927 for (next=image; next; next=next->next)
cristy151b66d2015-04-15 10:50:31 +000014928 (void) CopyMagickString(next->filename,filename,MagickPathExtent);
cristy68bd79a2015-02-25 12:23:36 +000014929 *package_info->image_info->magick='\0';
cristy4a3ce0a2013-08-03 20:06:59 +000014930 SetImageInfo(package_info->image_info,(unsigned int)
14931 GetImageListLength(image),exception);
14932 for (next=image; next; next=next->next)
14933 {
14934 (void) WriteImage(package_info->image_info,next,exception);
14935 number_images++;
14936 if (package_info->image_info->adjoin)
14937 break;
14938 }
14939
14940 PerlException:
14941 if (package_info != (struct PackageInfo *) NULL)
14942 DestroyPackageInfo(package_info);
14943 InheritPerlException(exception,perl_exception);
14944 exception=DestroyExceptionInfo(exception);
14945 sv_setiv(perl_exception,(IV) number_images);
14946 SvPOK_on(perl_exception);
14947 ST(0)=sv_2mortal(perl_exception);
14948 XSRETURN(1);
14949 }