blob: ea1ea2e3157ea7acf5565755717ba1414c9e3a32 [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},
Cristy72f24752018-08-14 20:17:26 -0400570 {"low-black", RealReference}, {"low-white", RealReference},
571 {"high-white", RealReference}, {"high-black", RealReference},
Cristy532b3382018-08-05 17:56:56 -0400572 {"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
cristy4a3ce0a2013-08-03 20:06:59 +00007678 MagickStatusType
7679 flags;
7680
7681 PixelInfo
7682 fill_color;
7683
7684 RectangleInfo
7685 geometry,
7686 region_info;
7687
7688 register ssize_t
7689 i;
7690
7691 ssize_t
7692 base,
7693 j,
7694 number_images;
7695
7696 struct Methods
7697 *rp;
7698
7699 struct PackageInfo
7700 *info;
7701
7702 SV
7703 *perl_exception,
7704 **pv,
7705 *reference,
7706 **reference_vector;
7707
7708 struct ArgumentList
7709 argument_list[MaxArguments];
7710
7711 PERL_UNUSED_VAR(ref);
7712 PERL_UNUSED_VAR(ix);
7713 exception=AcquireExceptionInfo();
7714 perl_exception=newSVpv("",0);
7715 reference_vector=NULL;
cristy4a3ce0a2013-08-03 20:06:59 +00007716 number_images=0;
7717 base=2;
7718 if (sv_isobject(ST(0)) == 0)
7719 {
7720 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7721 PackageName);
7722 goto PerlException;
7723 }
7724 reference=SvRV(ST(0));
7725 region_info.width=0;
7726 region_info.height=0;
7727 region_info.x=0;
7728 region_info.y=0;
cristy4a3ce0a2013-08-03 20:06:59 +00007729 image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7730 if (ix && (ix != 666))
7731 {
7732 /*
7733 Called as Method(...)
7734 */
7735 ix=(ix+1)/2;
7736 rp=(&Methods[ix-1]);
7737 attribute=rp->name;
7738 }
7739 else
7740 {
7741 /*
7742 Called as Mogrify("Method",...)
7743 */
7744 attribute=(char *) SvPV(ST(1),na);
7745 if (ix)
7746 {
7747 flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7748 attribute=(char *) SvPV(ST(2),na);
7749 base++;
7750 }
7751 for (rp=Methods; ; rp++)
7752 {
7753 if (rp >= EndOf(Methods))
7754 {
7755 ThrowPerlException(exception,OptionError,
7756 "UnrecognizedPerlMagickMethod",attribute);
7757 goto PerlException;
7758 }
7759 if (strEQcase(attribute,rp->name))
7760 break;
7761 }
7762 ix=rp-Methods+1;
7763 base++;
7764 }
7765 if (image == (Image *) NULL)
7766 {
7767 ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7768 goto PerlException;
7769 }
7770 Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7771 Zero(&attribute_flag,NumberOf(attribute_flag),char);
7772 for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7773 {
7774 Arguments
7775 *pp,
7776 *qq;
7777
7778 ssize_t
7779 ssize_test;
7780
7781 struct ArgumentList
7782 *al;
7783
7784 SV
7785 *sv;
7786
7787 sv=NULL;
7788 ssize_test=0;
7789 pp=(Arguments *) NULL;
7790 qq=rp->arguments;
7791 if (i == items)
7792 {
7793 pp=rp->arguments,
7794 sv=ST(i-1);
7795 }
7796 else
7797 for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7798 {
7799 if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7800 break;
7801 if (strEQcase(attribute,qq->method) > ssize_test)
7802 {
7803 pp=qq;
7804 ssize_test=strEQcase(attribute,qq->method);
7805 }
7806 }
7807 if (pp == (Arguments *) NULL)
7808 {
7809 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7810 attribute);
7811 goto continue_outer_loop;
7812 }
7813 al=(&argument_list[pp-rp->arguments]);
7814 switch (pp->type)
7815 {
7816 case ArrayReference:
7817 {
7818 if (SvTYPE(sv) != SVt_RV)
7819 {
cristy151b66d2015-04-15 10:50:31 +00007820 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007821 "invalid %.60s value",pp->method);
7822 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7823 goto continue_outer_loop;
7824 }
7825 al->array_reference=SvRV(sv);
7826 break;
7827 }
7828 case RealReference:
7829 {
7830 al->real_reference=SvNV(sv);
7831 break;
7832 }
7833 case FileReference:
7834 {
7835 al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7836 break;
7837 }
7838 case ImageReference:
7839 {
7840 if (!sv_isobject(sv) ||
7841 !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7842 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7843 {
7844 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7845 PackageName);
7846 goto PerlException;
7847 }
7848 break;
7849 }
7850 case IntegerReference:
7851 {
7852 al->integer_reference=SvIV(sv);
7853 break;
7854 }
7855 case StringReference:
7856 {
7857 al->string_reference=(char *) SvPV(sv,al->length);
7858 if (sv_isobject(sv))
7859 al->image_reference=SetupList(aTHX_ SvRV(sv),
7860 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7861 break;
7862 }
7863 default:
7864 {
7865 /*
7866 Is a string; look up name.
7867 */
7868 if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7869 {
7870 al->string_reference=(char *) SvPV(sv,al->length);
7871 al->integer_reference=(-1);
7872 break;
7873 }
7874 al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7875 MagickFalse,SvPV(sv,na));
7876 if (pp->type == MagickChannelOptions)
7877 al->integer_reference=ParseChannelOption(SvPV(sv,na));
7878 if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7879 {
cristy151b66d2015-04-15 10:50:31 +00007880 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007881 "invalid %.60s value",pp->method);
7882 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7883 goto continue_outer_loop;
7884 }
7885 break;
7886 }
7887 }
7888 attribute_flag[pp-rp->arguments]++;
7889 continue_outer_loop: ;
7890 }
7891 (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7892 pv=reference_vector;
7893 SetGeometryInfo(&geometry_info);
7894 channel=DefaultChannels;
7895 for (next=image; next; next=next->next)
7896 {
7897 image=next;
7898 SetGeometry(image,&geometry);
7899 if ((region_info.width*region_info.height) != 0)
Cristy7e567962018-02-03 12:42:20 -05007900 (void) SetImageRegionMask(image,WritePixelMask,&region_info,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007901 switch (ix)
7902 {
7903 default:
7904 {
cristy151b66d2015-04-15 10:50:31 +00007905 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
cristy4a3ce0a2013-08-03 20:06:59 +00007906 ThrowPerlException(exception,OptionError,
7907 "UnrecognizedPerlMagickMethod",message);
7908 goto PerlException;
7909 }
7910 case 1: /* Comment */
7911 {
7912 if (attribute_flag[0] == 0)
7913 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007914 (void) SetImageProperty(image,"comment",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007915 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007916 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007917 break;
7918 }
7919 case 2: /* Label */
7920 {
7921 if (attribute_flag[0] == 0)
7922 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007923 (void) SetImageProperty(image,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007924 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007925 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007926 break;
7927 }
7928 case 3: /* AddNoise */
7929 {
7930 double
7931 attenuate;
7932
7933 if (attribute_flag[0] == 0)
7934 argument_list[0].integer_reference=UniformNoise;
7935 attenuate=1.0;
7936 if (attribute_flag[1] != 0)
7937 attenuate=argument_list[1].real_reference;
7938 if (attribute_flag[2] != 0)
7939 channel=(ChannelType) argument_list[2].integer_reference;
7940 channel_mask=SetImageChannelMask(image,channel);
7941 image=AddNoiseImage(image,(NoiseType)
7942 argument_list[0].integer_reference,attenuate,exception);
7943 if (image != (Image *) NULL)
7944 (void) SetImageChannelMask(image,channel_mask);
7945 break;
7946 }
7947 case 4: /* Colorize */
7948 {
7949 PixelInfo
7950 target;
7951
7952 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7953 0,0,&target,exception);
7954 if (attribute_flag[0] != 0)
7955 (void) QueryColorCompliance(argument_list[0].string_reference,
7956 AllCompliance,&target,exception);
7957 if (attribute_flag[1] == 0)
7958 argument_list[1].string_reference="100%";
7959 image=ColorizeImage(image,argument_list[1].string_reference,&target,
7960 exception);
7961 break;
7962 }
7963 case 5: /* Border */
7964 {
7965 CompositeOperator
7966 compose;
7967
7968 geometry.width=0;
7969 geometry.height=0;
7970 if (attribute_flag[0] != 0)
7971 flags=ParsePageGeometry(image,argument_list[0].string_reference,
7972 &geometry,exception);
7973 if (attribute_flag[1] != 0)
7974 geometry.width=argument_list[1].integer_reference;
7975 if (attribute_flag[2] != 0)
7976 geometry.height=argument_list[2].integer_reference;
7977 if (attribute_flag[3] != 0)
7978 QueryColorCompliance(argument_list[3].string_reference,
7979 AllCompliance,&image->border_color,exception);
7980 if (attribute_flag[4] != 0)
7981 QueryColorCompliance(argument_list[4].string_reference,
7982 AllCompliance,&image->border_color,exception);
7983 if (attribute_flag[5] != 0)
7984 QueryColorCompliance(argument_list[5].string_reference,
7985 AllCompliance,&image->border_color,exception);
7986 compose=image->compose;
7987 if (attribute_flag[6] != 0)
7988 compose=(CompositeOperator) argument_list[6].integer_reference;
7989 image=BorderImage(image,&geometry,compose,exception);
7990 break;
7991 }
7992 case 6: /* Blur */
7993 {
7994 if (attribute_flag[0] != 0)
7995 {
7996 flags=ParseGeometry(argument_list[0].string_reference,
7997 &geometry_info);
7998 if ((flags & SigmaValue) == 0)
7999 geometry_info.sigma=1.0;
8000 }
8001 if (attribute_flag[1] != 0)
8002 geometry_info.rho=argument_list[1].real_reference;
8003 if (attribute_flag[2] != 0)
8004 geometry_info.sigma=argument_list[2].real_reference;
8005 if (attribute_flag[3] != 0)
8006 channel=(ChannelType) argument_list[3].integer_reference;
8007 channel_mask=SetImageChannelMask(image,channel);
8008 image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
8009 exception);
8010 if (image != (Image *) NULL)
8011 (void) SetImageChannelMask(image,channel_mask);
8012 break;
8013 }
8014 case 7: /* Chop */
8015 {
cristy260bd762014-08-15 12:46:34 +00008016 if (attribute_flag[5] != 0)
8017 image->gravity=(GravityType) argument_list[5].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00008018 if (attribute_flag[0] != 0)
8019 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8020 &geometry,exception);
8021 if (attribute_flag[1] != 0)
8022 geometry.width=argument_list[1].integer_reference;
8023 if (attribute_flag[2] != 0)
8024 geometry.height=argument_list[2].integer_reference;
8025 if (attribute_flag[3] != 0)
8026 geometry.x=argument_list[3].integer_reference;
8027 if (attribute_flag[4] != 0)
8028 geometry.y=argument_list[4].integer_reference;
8029 image=ChopImage(image,&geometry,exception);
8030 break;
8031 }
8032 case 8: /* Crop */
8033 {
8034 if (attribute_flag[6] != 0)
8035 image->gravity=(GravityType) argument_list[6].integer_reference;
8036 if (attribute_flag[0] != 0)
8037 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8038 &geometry,exception);
8039 if (attribute_flag[1] != 0)
8040 geometry.width=argument_list[1].integer_reference;
8041 if (attribute_flag[2] != 0)
8042 geometry.height=argument_list[2].integer_reference;
8043 if (attribute_flag[3] != 0)
8044 geometry.x=argument_list[3].integer_reference;
8045 if (attribute_flag[4] != 0)
8046 geometry.y=argument_list[4].integer_reference;
8047 if (attribute_flag[5] != 0)
8048 image->fuzz=StringToDoubleInterval(
8049 argument_list[5].string_reference,(double) QuantumRange+1.0);
8050 image=CropImage(image,&geometry,exception);
8051 break;
8052 }
8053 case 9: /* Despeckle */
8054 {
8055 image=DespeckleImage(image,exception);
8056 break;
8057 }
8058 case 10: /* Edge */
8059 {
8060 if (attribute_flag[0] != 0)
8061 geometry_info.rho=argument_list[0].real_reference;
8062 image=EdgeImage(image,geometry_info.rho,exception);
8063 break;
8064 }
8065 case 11: /* Emboss */
8066 {
8067 if (attribute_flag[0] != 0)
8068 {
8069 flags=ParseGeometry(argument_list[0].string_reference,
8070 &geometry_info);
8071 if ((flags & SigmaValue) == 0)
8072 geometry_info.sigma=1.0;
8073 }
8074 if (attribute_flag[1] != 0)
8075 geometry_info.rho=argument_list[1].real_reference;
8076 if (attribute_flag[2] != 0)
8077 geometry_info.sigma=argument_list[2].real_reference;
8078 image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8079 exception);
8080 break;
8081 }
8082 case 12: /* Enhance */
8083 {
8084 image=EnhanceImage(image,exception);
8085 break;
8086 }
8087 case 13: /* Flip */
8088 {
8089 image=FlipImage(image,exception);
8090 break;
8091 }
8092 case 14: /* Flop */
8093 {
8094 image=FlopImage(image,exception);
8095 break;
8096 }
8097 case 15: /* Frame */
8098 {
8099 CompositeOperator
8100 compose;
8101
8102 FrameInfo
8103 frame_info;
8104
8105 if (attribute_flag[0] != 0)
8106 {
8107 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8108 &geometry,exception);
8109 frame_info.width=geometry.width;
8110 frame_info.height=geometry.height;
8111 frame_info.outer_bevel=geometry.x;
8112 frame_info.inner_bevel=geometry.y;
8113 }
8114 if (attribute_flag[1] != 0)
8115 frame_info.width=argument_list[1].integer_reference;
8116 if (attribute_flag[2] != 0)
8117 frame_info.height=argument_list[2].integer_reference;
8118 if (attribute_flag[3] != 0)
8119 frame_info.inner_bevel=argument_list[3].integer_reference;
8120 if (attribute_flag[4] != 0)
8121 frame_info.outer_bevel=argument_list[4].integer_reference;
8122 if (attribute_flag[5] != 0)
8123 QueryColorCompliance(argument_list[5].string_reference,
8124 AllCompliance,&fill_color,exception);
8125 if (attribute_flag[6] != 0)
8126 QueryColorCompliance(argument_list[6].string_reference,
8127 AllCompliance,&fill_color,exception);
8128 frame_info.x=(ssize_t) frame_info.width;
8129 frame_info.y=(ssize_t) frame_info.height;
8130 frame_info.width=image->columns+2*frame_info.x;
8131 frame_info.height=image->rows+2*frame_info.y;
8132 if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
Cristy8645e042016-02-03 16:35:29 -05008133 image->alpha_color=fill_color;
cristy4a3ce0a2013-08-03 20:06:59 +00008134 compose=image->compose;
8135 if (attribute_flag[7] != 0)
8136 compose=(CompositeOperator) argument_list[7].integer_reference;
8137 image=FrameImage(image,&frame_info,compose,exception);
8138 break;
8139 }
8140 case 16: /* Implode */
8141 {
8142 PixelInterpolateMethod
8143 method;
8144
8145 if (attribute_flag[0] == 0)
8146 argument_list[0].real_reference=0.5;
8147 method=UndefinedInterpolatePixel;
8148 if (attribute_flag[1] != 0)
8149 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8150 image=ImplodeImage(image,argument_list[0].real_reference,
8151 method,exception);
8152 break;
8153 }
8154 case 17: /* Magnify */
8155 {
8156 image=MagnifyImage(image,exception);
8157 break;
8158 }
8159 case 18: /* MedianFilter */
8160 {
8161 if (attribute_flag[0] != 0)
8162 {
8163 flags=ParseGeometry(argument_list[0].string_reference,
8164 &geometry_info);
8165 if ((flags & SigmaValue) == 0)
8166 geometry_info.sigma=geometry_info.rho;
8167 }
8168 if (attribute_flag[1] != 0)
8169 geometry_info.rho=argument_list[1].real_reference;
8170 if (attribute_flag[2] != 0)
8171 geometry_info.sigma=argument_list[2].real_reference;
8172 if (attribute_flag[3] != 0)
8173 channel=(ChannelType) argument_list[3].integer_reference;
8174 channel_mask=SetImageChannelMask(image,channel);
8175 image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8176 (size_t) geometry_info.sigma,exception);
8177 if (image != (Image *) NULL)
8178 (void) SetImageChannelMask(image,channel_mask);
8179 break;
8180 }
8181 case 19: /* Minify */
8182 {
8183 image=MinifyImage(image,exception);
8184 break;
8185 }
8186 case 20: /* OilPaint */
8187 {
8188 if (attribute_flag[0] == 0)
8189 argument_list[0].real_reference=0.0;
8190 if (attribute_flag[1] == 0)
8191 argument_list[1].real_reference=1.0;
8192 image=OilPaintImage(image,argument_list[0].real_reference,
8193 argument_list[1].real_reference,exception);
8194 break;
8195 }
8196 case 21: /* ReduceNoise */
8197 {
8198 if (attribute_flag[0] != 0)
8199 {
8200 flags=ParseGeometry(argument_list[0].string_reference,
8201 &geometry_info);
8202 if ((flags & SigmaValue) == 0)
8203 geometry_info.sigma=1.0;
8204 }
8205 if (attribute_flag[1] != 0)
8206 geometry_info.rho=argument_list[1].real_reference;
8207 if (attribute_flag[2] != 0)
8208 geometry_info.sigma=argument_list[2].real_reference;
8209 if (attribute_flag[3] != 0)
8210 channel=(ChannelType) argument_list[3].integer_reference;
8211 channel_mask=SetImageChannelMask(image,channel);
8212 image=StatisticImage(image,NonpeakStatistic,(size_t)
8213 geometry_info.rho,(size_t) geometry_info.sigma,exception);
8214 if (image != (Image *) NULL)
8215 (void) SetImageChannelMask(image,channel_mask);
8216 break;
8217 }
8218 case 22: /* Roll */
8219 {
8220 if (attribute_flag[0] != 0)
Cristyf94b0842017-07-14 07:05:02 -04008221 {
8222 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8223 &geometry,exception);
8224 if ((flags & PercentValue) != 0)
8225 {
8226 geometry.x*=(double) image->columns/100.0;
8227 geometry.y*=(double) image->rows/100.0;
8228 }
8229 }
cristy4a3ce0a2013-08-03 20:06:59 +00008230 if (attribute_flag[1] != 0)
8231 geometry.x=argument_list[1].integer_reference;
8232 if (attribute_flag[2] != 0)
8233 geometry.y=argument_list[2].integer_reference;
8234 image=RollImage(image,geometry.x,geometry.y,exception);
8235 break;
8236 }
8237 case 23: /* Rotate */
8238 {
8239 if (attribute_flag[0] == 0)
8240 argument_list[0].real_reference=90.0;
8241 if (attribute_flag[1] != 0)
8242 {
8243 QueryColorCompliance(argument_list[1].string_reference,
8244 AllCompliance,&image->background_color,exception);
cristy17f11b02014-12-20 19:37:04 +00008245 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8246 (image->alpha_trait == UndefinedPixelTrait))
cristy4a3ce0a2013-08-03 20:06:59 +00008247 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8248 }
8249 image=RotateImage(image,argument_list[0].real_reference,exception);
8250 break;
8251 }
8252 case 24: /* Sample */
8253 {
8254 if (attribute_flag[0] != 0)
8255 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8256 &geometry,exception);
8257 if (attribute_flag[1] != 0)
8258 geometry.width=argument_list[1].integer_reference;
8259 if (attribute_flag[2] != 0)
8260 geometry.height=argument_list[2].integer_reference;
8261 image=SampleImage(image,geometry.width,geometry.height,exception);
8262 break;
8263 }
8264 case 25: /* Scale */
8265 {
8266 if (attribute_flag[0] != 0)
8267 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8268 &geometry,exception);
8269 if (attribute_flag[1] != 0)
8270 geometry.width=argument_list[1].integer_reference;
8271 if (attribute_flag[2] != 0)
8272 geometry.height=argument_list[2].integer_reference;
8273 image=ScaleImage(image,geometry.width,geometry.height,exception);
8274 break;
8275 }
8276 case 26: /* Shade */
8277 {
8278 if (attribute_flag[0] != 0)
8279 {
8280 flags=ParseGeometry(argument_list[0].string_reference,
8281 &geometry_info);
8282 if ((flags & SigmaValue) == 0)
8283 geometry_info.sigma=0.0;
8284 }
8285 if (attribute_flag[1] != 0)
8286 geometry_info.rho=argument_list[1].real_reference;
8287 if (attribute_flag[2] != 0)
8288 geometry_info.sigma=argument_list[2].real_reference;
8289 image=ShadeImage(image,
8290 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8291 geometry_info.rho,geometry_info.sigma,exception);
8292 break;
8293 }
8294 case 27: /* Sharpen */
8295 {
8296 if (attribute_flag[0] != 0)
8297 {
8298 flags=ParseGeometry(argument_list[0].string_reference,
8299 &geometry_info);
8300 if ((flags & SigmaValue) == 0)
8301 geometry_info.sigma=1.0;
8302 }
8303 if (attribute_flag[1] != 0)
8304 geometry_info.rho=argument_list[1].real_reference;
8305 if (attribute_flag[2] != 0)
8306 geometry_info.sigma=argument_list[2].real_reference;
8307 if (attribute_flag[3] != 0)
8308 channel=(ChannelType) argument_list[3].integer_reference;
8309 channel_mask=SetImageChannelMask(image,channel);
8310 image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8311 exception);
8312 if (image != (Image *) NULL)
8313 (void) SetImageChannelMask(image,channel_mask);
8314 break;
8315 }
8316 case 28: /* Shear */
8317 {
8318 if (attribute_flag[0] != 0)
8319 {
8320 flags=ParseGeometry(argument_list[0].string_reference,
8321 &geometry_info);
8322 if ((flags & SigmaValue) == 0)
8323 geometry_info.sigma=geometry_info.rho;
8324 }
8325 if (attribute_flag[1] != 0)
8326 geometry_info.rho=argument_list[1].real_reference;
8327 if (attribute_flag[2] != 0)
8328 geometry_info.sigma=argument_list[2].real_reference;
8329 if (attribute_flag[3] != 0)
8330 QueryColorCompliance(argument_list[3].string_reference,
8331 AllCompliance,&image->background_color,exception);
8332 if (attribute_flag[4] != 0)
8333 QueryColorCompliance(argument_list[4].string_reference,
8334 AllCompliance,&image->background_color,exception);
8335 image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8336 exception);
8337 break;
8338 }
8339 case 29: /* Spread */
8340 {
Cristye3319c12015-08-24 07:11:48 -04008341 PixelInterpolateMethod
8342 method;
8343
cristy4a3ce0a2013-08-03 20:06:59 +00008344 if (attribute_flag[0] == 0)
8345 argument_list[0].real_reference=1.0;
Cristye3319c12015-08-24 07:11:48 -04008346 method=UndefinedInterpolatePixel;
8347 if (attribute_flag[1] != 0)
8348 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8349 image=SpreadImage(image,method,argument_list[0].real_reference,
8350 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008351 break;
8352 }
8353 case 30: /* Swirl */
8354 {
8355 PixelInterpolateMethod
8356 method;
8357
8358 if (attribute_flag[0] == 0)
8359 argument_list[0].real_reference=50.0;
8360 method=UndefinedInterpolatePixel;
8361 if (attribute_flag[1] != 0)
8362 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8363 image=SwirlImage(image,argument_list[0].real_reference,
8364 method,exception);
8365 break;
8366 }
8367 case 31: /* Resize */
8368 case 32: /* Zoom */
8369 {
8370 if (attribute_flag[0] != 0)
8371 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8372 &geometry,exception);
8373 if (attribute_flag[1] != 0)
8374 geometry.width=argument_list[1].integer_reference;
8375 if (attribute_flag[2] != 0)
8376 geometry.height=argument_list[2].integer_reference;
8377 if (attribute_flag[3] == 0)
8378 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8379 if (attribute_flag[4] != 0)
8380 SetImageArtifact(image,"filter:support",
8381 argument_list[4].string_reference);
8382 image=ResizeImage(image,geometry.width,geometry.height,
Cristy8645e042016-02-03 16:35:29 -05008383 (FilterType) argument_list[3].integer_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00008384 exception);
8385 break;
8386 }
8387 case 33: /* Annotate */
8388 {
8389 DrawInfo
8390 *draw_info;
8391
8392 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8393 (DrawInfo *) NULL);
8394 if (attribute_flag[0] != 0)
8395 {
8396 char
8397 *text;
8398
8399 text=InterpretImageProperties(info ? info->image_info :
8400 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8401 exception);
8402 (void) CloneString(&draw_info->text,text);
8403 text=DestroyString(text);
8404 }
8405 if (attribute_flag[1] != 0)
8406 (void) CloneString(&draw_info->font,
8407 argument_list[1].string_reference);
8408 if (attribute_flag[2] != 0)
8409 draw_info->pointsize=argument_list[2].real_reference;
8410 if (attribute_flag[3] != 0)
8411 (void) CloneString(&draw_info->density,
8412 argument_list[3].string_reference);
8413 if (attribute_flag[4] != 0)
8414 (void) QueryColorCompliance(argument_list[4].string_reference,
8415 AllCompliance,&draw_info->undercolor,exception);
8416 if (attribute_flag[5] != 0)
8417 {
8418 (void) QueryColorCompliance(argument_list[5].string_reference,
8419 AllCompliance,&draw_info->stroke,exception);
8420 if (argument_list[5].image_reference != (Image *) NULL)
8421 draw_info->stroke_pattern=CloneImage(
8422 argument_list[5].image_reference,0,0,MagickTrue,exception);
8423 }
8424 if (attribute_flag[6] != 0)
8425 {
8426 (void) QueryColorCompliance(argument_list[6].string_reference,
8427 AllCompliance,&draw_info->fill,exception);
8428 if (argument_list[6].image_reference != (Image *) NULL)
8429 draw_info->fill_pattern=CloneImage(
8430 argument_list[6].image_reference,0,0,MagickTrue,exception);
8431 }
8432 if (attribute_flag[7] != 0)
8433 {
8434 (void) CloneString(&draw_info->geometry,
8435 argument_list[7].string_reference);
8436 flags=ParsePageGeometry(image,argument_list[7].string_reference,
8437 &geometry,exception);
8438 if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8439 geometry_info.sigma=geometry_info.xi;
8440 }
8441 if (attribute_flag[8] != 0)
8442 (void) QueryColorCompliance(argument_list[8].string_reference,
8443 AllCompliance,&draw_info->fill,exception);
8444 if (attribute_flag[11] != 0)
8445 draw_info->gravity=(GravityType)
8446 argument_list[11].integer_reference;
8447 if (attribute_flag[25] != 0)
8448 {
8449 AV
8450 *av;
8451
8452 av=(AV *) argument_list[25].array_reference;
8453 if ((av_len(av) != 3) && (av_len(av) != 5))
8454 {
8455 ThrowPerlException(exception,OptionError,
8456 "affine matrix must have 4 or 6 elements",PackageName);
8457 goto PerlException;
8458 }
8459 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8460 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8461 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8462 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8463 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8464 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8465 {
8466 ThrowPerlException(exception,OptionError,
8467 "affine matrix is singular",PackageName);
8468 goto PerlException;
8469 }
8470 if (av_len(av) == 5)
8471 {
8472 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8473 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8474 }
8475 }
8476 for (j=12; j < 17; j++)
8477 {
8478 if (attribute_flag[j] == 0)
8479 continue;
8480 value=argument_list[j].string_reference;
8481 angle=argument_list[j].real_reference;
8482 current=draw_info->affine;
8483 GetAffineMatrix(&affine);
8484 switch (j)
8485 {
8486 case 12:
8487 {
8488 /*
8489 Translate.
8490 */
8491 flags=ParseGeometry(value,&geometry_info);
8492 affine.tx=geometry_info.xi;
8493 affine.ty=geometry_info.psi;
8494 if ((flags & PsiValue) == 0)
8495 affine.ty=affine.tx;
8496 break;
8497 }
8498 case 13:
8499 {
8500 /*
8501 Scale.
8502 */
8503 flags=ParseGeometry(value,&geometry_info);
8504 affine.sx=geometry_info.rho;
8505 affine.sy=geometry_info.sigma;
8506 if ((flags & SigmaValue) == 0)
8507 affine.sy=affine.sx;
8508 break;
8509 }
8510 case 14:
8511 {
8512 /*
8513 Rotate.
8514 */
8515 if (angle == 0.0)
8516 break;
8517 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8518 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8519 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8520 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8521 break;
8522 }
8523 case 15:
8524 {
8525 /*
8526 SkewX.
8527 */
8528 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8529 break;
8530 }
8531 case 16:
8532 {
8533 /*
8534 SkewY.
8535 */
8536 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8537 break;
8538 }
8539 }
8540 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8541 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8542 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8543 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8544 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8545 current.tx;
8546 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8547 current.ty;
8548 }
8549 if (attribute_flag[9] == 0)
8550 argument_list[9].real_reference=0.0;
8551 if (attribute_flag[10] == 0)
8552 argument_list[10].real_reference=0.0;
8553 if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8554 {
8555 char
cristy151b66d2015-04-15 10:50:31 +00008556 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008557
cristy151b66d2015-04-15 10:50:31 +00008558 (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
cristy4a3ce0a2013-08-03 20:06:59 +00008559 (double) argument_list[9].real_reference+draw_info->affine.tx,
8560 (double) argument_list[10].real_reference+draw_info->affine.ty);
8561 (void) CloneString(&draw_info->geometry,geometry);
8562 }
8563 if (attribute_flag[17] != 0)
8564 draw_info->stroke_width=argument_list[17].real_reference;
8565 if (attribute_flag[18] != 0)
8566 {
8567 draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8568 MagickTrue : MagickFalse;
8569 draw_info->stroke_antialias=draw_info->text_antialias;
8570 }
8571 if (attribute_flag[19] != 0)
8572 (void) CloneString(&draw_info->family,
8573 argument_list[19].string_reference);
8574 if (attribute_flag[20] != 0)
8575 draw_info->style=(StyleType) argument_list[20].integer_reference;
8576 if (attribute_flag[21] != 0)
8577 draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8578 if (attribute_flag[22] != 0)
8579 draw_info->weight=argument_list[22].integer_reference;
8580 if (attribute_flag[23] != 0)
8581 draw_info->align=(AlignType) argument_list[23].integer_reference;
8582 if (attribute_flag[24] != 0)
8583 (void) CloneString(&draw_info->encoding,
8584 argument_list[24].string_reference);
8585 if (attribute_flag[25] != 0)
8586 draw_info->fill_pattern=CloneImage(
8587 argument_list[25].image_reference,0,0,MagickTrue,exception);
8588 if (attribute_flag[26] != 0)
8589 draw_info->fill_pattern=CloneImage(
8590 argument_list[26].image_reference,0,0,MagickTrue,exception);
8591 if (attribute_flag[27] != 0)
8592 draw_info->stroke_pattern=CloneImage(
8593 argument_list[27].image_reference,0,0,MagickTrue,exception);
8594 if (attribute_flag[29] != 0)
8595 draw_info->kerning=argument_list[29].real_reference;
8596 if (attribute_flag[30] != 0)
8597 draw_info->interline_spacing=argument_list[30].real_reference;
8598 if (attribute_flag[31] != 0)
8599 draw_info->interword_spacing=argument_list[31].real_reference;
8600 if (attribute_flag[32] != 0)
8601 draw_info->direction=(DirectionType)
8602 argument_list[32].integer_reference;
8603 (void) AnnotateImage(image,draw_info,exception);
8604 draw_info=DestroyDrawInfo(draw_info);
8605 break;
8606 }
8607 case 34: /* ColorFloodfill */
8608 {
8609 DrawInfo
8610 *draw_info;
8611
8612 MagickBooleanType
8613 invert;
8614
8615 PixelInfo
8616 target;
8617
8618 draw_info=CloneDrawInfo(info ? info->image_info :
8619 (ImageInfo *) NULL,(DrawInfo *) NULL);
8620 if (attribute_flag[0] != 0)
8621 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8622 &geometry,exception);
8623 if (attribute_flag[1] != 0)
8624 geometry.x=argument_list[1].integer_reference;
8625 if (attribute_flag[2] != 0)
8626 geometry.y=argument_list[2].integer_reference;
8627 if (attribute_flag[3] != 0)
8628 (void) QueryColorCompliance(argument_list[3].string_reference,
8629 AllCompliance,&draw_info->fill,exception);
8630 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8631 geometry.x,geometry.y,&target,exception);
8632 invert=MagickFalse;
8633 if (attribute_flag[4] != 0)
8634 {
8635 QueryColorCompliance(argument_list[4].string_reference,
8636 AllCompliance,&target,exception);
8637 invert=MagickTrue;
8638 }
8639 if (attribute_flag[5] != 0)
8640 image->fuzz=StringToDoubleInterval(
8641 argument_list[5].string_reference,(double) QuantumRange+1.0);
8642 if (attribute_flag[6] != 0)
8643 invert=(MagickBooleanType) argument_list[6].integer_reference;
8644 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8645 geometry.y,invert,exception);
8646 draw_info=DestroyDrawInfo(draw_info);
8647 break;
8648 }
8649 case 35: /* Composite */
8650 {
8651 char
cristy151b66d2015-04-15 10:50:31 +00008652 composite_geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008653
8654 Image
8655 *composite_image,
8656 *rotate_image;
8657
8658 MagickBooleanType
8659 clip_to_self;
8660
8661 compose=OverCompositeOp;
8662 if (attribute_flag[0] != 0)
8663 composite_image=argument_list[0].image_reference;
8664 else
8665 {
8666 ThrowPerlException(exception,OptionError,
8667 "CompositeImageRequired",PackageName);
8668 goto PerlException;
8669 }
8670 /*
8671 Parameter Handling used for BOTH normal and tiled composition.
8672 */
8673 if (attribute_flag[1] != 0) /* compose */
8674 compose=(CompositeOperator) argument_list[1].integer_reference;
8675 if (attribute_flag[6] != 0) /* opacity */
8676 {
8677 if (compose != DissolveCompositeOp)
8678 (void) SetImageAlpha(composite_image,(Quantum)
8679 StringToDoubleInterval(argument_list[6].string_reference,
8680 (double) QuantumRange+1.0),exception);
8681 else
8682 {
8683 CacheView
8684 *composite_view;
8685
8686 double
8687 opacity;
8688
8689 MagickBooleanType
8690 sync;
8691
8692 register ssize_t
8693 x;
8694
8695 register Quantum
8696 *q;
8697
8698 ssize_t
8699 y;
8700
8701 /*
8702 Handle dissolve composite operator (patch by
8703 Kevin A. McGrail).
8704 */
8705 (void) CloneString(&image->geometry,
8706 argument_list[6].string_reference);
8707 opacity=(Quantum) StringToDoubleInterval(
8708 argument_list[6].string_reference,(double) QuantumRange+
8709 1.0);
cristy17f11b02014-12-20 19:37:04 +00008710 if (composite_image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00008711 (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8712 composite_view=AcquireAuthenticCacheView(composite_image,exception);
8713 for (y=0; y < (ssize_t) composite_image->rows ; y++)
8714 {
8715 q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8716 composite_image->columns,1,exception);
8717 for (x=0; x < (ssize_t) composite_image->columns; x++)
8718 {
8719 if (GetPixelAlpha(image,q) == OpaqueAlpha)
8720 SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8721 q);
8722 q+=GetPixelChannels(composite_image);
8723 }
8724 sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8725 if (sync == MagickFalse)
8726 break;
8727 }
8728 composite_view=DestroyCacheView(composite_view);
8729 }
8730 }
8731 if (attribute_flag[9] != 0) /* "color=>" */
8732 QueryColorCompliance(argument_list[9].string_reference,
8733 AllCompliance,&composite_image->background_color,exception);
8734 if (attribute_flag[12] != 0) /* "interpolate=>" */
8735 image->interpolate=(PixelInterpolateMethod)
8736 argument_list[12].integer_reference;
8737 if (attribute_flag[13] != 0) /* "args=>" */
8738 (void) SetImageArtifact(composite_image,"compose:args",
8739 argument_list[13].string_reference);
8740 if (attribute_flag[14] != 0) /* "blend=>" depreciated */
8741 (void) SetImageArtifact(composite_image,"compose:args",
8742 argument_list[14].string_reference);
Cristy72aed842018-07-08 18:25:50 -04008743 clip_to_self=MagickTrue;
8744 switch (compose)
8745 {
8746 case ClearCompositeOp:
8747 case SrcCompositeOp:
8748 case InCompositeOp:
8749 case SrcInCompositeOp:
8750 case OutCompositeOp:
8751 case SrcOutCompositeOp:
8752 case DstInCompositeOp:
8753 case DstAtopCompositeOp:
Cristy901f5212018-07-08 18:43:34 -04008754 case CopyAlphaCompositeOp:
Cristy72aed842018-07-08 18:25:50 -04008755 case ChangeMaskCompositeOp:
8756 case DissolveCompositeOp:
8757 case BlendCompositeOp:
8758 {
Cristy901f5212018-07-08 18:43:34 -04008759 clip_to_self=MagickFalse;
Cristy72aed842018-07-08 18:25:50 -04008760 break;
8761 }
8762 default:
8763 break;
8764 }
cristy4a3ce0a2013-08-03 20:06:59 +00008765 if (attribute_flag[15] != 0)
8766 clip_to_self=(MagickBooleanType)
8767 argument_list[15].integer_reference;
8768 /*
8769 Tiling Composition (with orthogonal rotate).
8770 */
8771 rotate_image=(Image *) NULL;
8772 if (attribute_flag[8] != 0) /* "rotate=>" */
8773 {
8774 /*
8775 Rotate image.
8776 */
8777 rotate_image=RotateImage(composite_image,
8778 argument_list[8].real_reference,exception);
8779 if (rotate_image == (Image *) NULL)
8780 break;
8781 }
8782 if ((attribute_flag[7] != 0) &&
8783 (argument_list[7].integer_reference != 0)) /* tile */
8784 {
8785 ssize_t
8786 x,
8787 y;
8788
8789 /*
8790 Tile the composite image.
8791 */
cristy4a3ce0a2013-08-03 20:06:59 +00008792 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8793 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8794 {
8795 if (attribute_flag[8] != 0) /* rotate */
8796 (void) CompositeImage(image,rotate_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008797 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008798 else
8799 (void) CompositeImage(image,composite_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008800 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008801 }
8802 if (attribute_flag[8] != 0) /* rotate */
8803 rotate_image=DestroyImage(rotate_image);
8804 break;
8805 }
8806 /*
8807 Parameter Handling used used ONLY for normal composition.
8808 */
8809 if (attribute_flag[5] != 0) /* gravity */
8810 image->gravity=(GravityType) argument_list[5].integer_reference;
8811 if (attribute_flag[2] != 0) /* geometry offset */
8812 {
8813 SetGeometry(image,&geometry);
8814 (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8815 &geometry);
8816 GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8817 &geometry);
8818 }
8819 if (attribute_flag[3] != 0) /* x offset */
8820 geometry.x=argument_list[3].integer_reference;
8821 if (attribute_flag[4] != 0) /* y offset */
8822 geometry.y=argument_list[4].integer_reference;
8823 if (attribute_flag[10] != 0) /* mask */
8824 {
8825 if ((image->compose == DisplaceCompositeOp) ||
8826 (image->compose == DistortCompositeOp))
8827 {
8828 /*
8829 Merge Y displacement into X displacement image.
8830 */
8831 composite_image=CloneImage(composite_image,0,0,MagickTrue,
8832 exception);
8833 (void) CompositeImage(composite_image,
8834 argument_list[10].image_reference,CopyGreenCompositeOp,
Cristy74e39292018-07-08 13:13:20 -04008835 clip_to_self,0,0,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008836 }
8837 else
8838 {
8839 Image
8840 *mask_image;
8841
8842 /*
8843 Set a blending mask for the composition.
8844 */
8845 mask_image=CloneImage(argument_list[10].image_reference,0,0,
8846 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +00008847 (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
cristyf3023752015-07-28 17:13:22 +00008848 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008849 mask_image=DestroyImage(mask_image);
8850 }
8851 }
8852 if (attribute_flag[11] != 0) /* channel */
8853 channel=(ChannelType) argument_list[11].integer_reference;
8854 /*
8855 Composite two images (normal composition).
8856 */
cristy151b66d2015-04-15 10:50:31 +00008857 (void) FormatLocaleString(composite_geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00008858 "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8859 (double) composite_image->rows,(double) geometry.x,(double)
8860 geometry.y);
8861 flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8862 exception);
8863 channel_mask=SetImageChannelMask(image,channel);
8864 if (attribute_flag[8] == 0) /* no rotate */
8865 CompositeImage(image,composite_image,compose,clip_to_self,
8866 geometry.x,geometry.y,exception);
8867 else
8868 {
8869 /*
8870 Position adjust rotated image then composite.
8871 */
8872 geometry.x-=(ssize_t) (rotate_image->columns-
8873 composite_image->columns)/2;
8874 geometry.y-=(ssize_t) (rotate_image->rows-
8875 composite_image->rows)/2;
8876 CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8877 geometry.y,exception);
8878 rotate_image=DestroyImage(rotate_image);
8879 }
8880 if (attribute_flag[10] != 0) /* mask */
8881 {
8882 if ((image->compose == DisplaceCompositeOp) ||
8883 (image->compose == DistortCompositeOp))
8884 composite_image=DestroyImage(composite_image);
8885 else
cristy1f7ffb72015-07-29 11:07:03 +00008886 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
cristyf3023752015-07-28 17:13:22 +00008887 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008888 }
8889 (void) SetImageChannelMask(image,channel_mask);
8890 break;
8891 }
8892 case 36: /* Contrast */
8893 {
8894 if (attribute_flag[0] == 0)
8895 argument_list[0].integer_reference=0;
8896 (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8897 MagickTrue : MagickFalse,exception);
8898 break;
8899 }
8900 case 37: /* CycleColormap */
8901 {
8902 if (attribute_flag[0] == 0)
8903 argument_list[0].integer_reference=6;
8904 (void) CycleColormapImage(image,argument_list[0].integer_reference,
8905 exception);
8906 break;
8907 }
8908 case 38: /* Draw */
8909 {
8910 DrawInfo
8911 *draw_info;
8912
8913 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8914 (DrawInfo *) NULL);
8915 (void) CloneString(&draw_info->primitive,"point");
8916 if (attribute_flag[0] != 0)
8917 {
8918 if (argument_list[0].integer_reference < 0)
8919 (void) CloneString(&draw_info->primitive,
8920 argument_list[0].string_reference);
8921 else
8922 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8923 MagickPrimitiveOptions,argument_list[0].integer_reference));
8924 }
8925 if (attribute_flag[1] != 0)
8926 {
8927 if (LocaleCompare(draw_info->primitive,"path") == 0)
8928 {
8929 (void) ConcatenateString(&draw_info->primitive," '");
8930 ConcatenateString(&draw_info->primitive,
8931 argument_list[1].string_reference);
8932 (void) ConcatenateString(&draw_info->primitive,"'");
8933 }
8934 else
8935 {
8936 (void) ConcatenateString(&draw_info->primitive," ");
8937 ConcatenateString(&draw_info->primitive,
8938 argument_list[1].string_reference);
8939 }
8940 }
8941 if (attribute_flag[2] != 0)
8942 {
8943 (void) ConcatenateString(&draw_info->primitive," ");
8944 (void) ConcatenateString(&draw_info->primitive,
8945 CommandOptionToMnemonic(MagickMethodOptions,
8946 argument_list[2].integer_reference));
8947 }
8948 if (attribute_flag[3] != 0)
8949 {
8950 (void) QueryColorCompliance(argument_list[3].string_reference,
8951 AllCompliance,&draw_info->stroke,exception);
8952 if (argument_list[3].image_reference != (Image *) NULL)
8953 draw_info->stroke_pattern=CloneImage(
8954 argument_list[3].image_reference,0,0,MagickTrue,exception);
8955 }
8956 if (attribute_flag[4] != 0)
8957 {
8958 (void) QueryColorCompliance(argument_list[4].string_reference,
8959 AllCompliance,&draw_info->fill,exception);
8960 if (argument_list[4].image_reference != (Image *) NULL)
8961 draw_info->fill_pattern=CloneImage(
8962 argument_list[4].image_reference,0,0,MagickTrue,exception);
8963 }
8964 if (attribute_flag[5] != 0)
8965 draw_info->stroke_width=argument_list[5].real_reference;
8966 if (attribute_flag[6] != 0)
8967 (void) CloneString(&draw_info->font,
8968 argument_list[6].string_reference);
8969 if (attribute_flag[7] != 0)
8970 (void) QueryColorCompliance(argument_list[7].string_reference,
8971 AllCompliance,&draw_info->border_color,exception);
8972 if (attribute_flag[8] != 0)
8973 draw_info->affine.tx=argument_list[8].real_reference;
8974 if (attribute_flag[9] != 0)
8975 draw_info->affine.ty=argument_list[9].real_reference;
8976 if (attribute_flag[20] != 0)
8977 {
8978 AV
8979 *av;
8980
8981 av=(AV *) argument_list[20].array_reference;
8982 if ((av_len(av) != 3) && (av_len(av) != 5))
8983 {
8984 ThrowPerlException(exception,OptionError,
8985 "affine matrix must have 4 or 6 elements",PackageName);
8986 goto PerlException;
8987 }
8988 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8989 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8990 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8991 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8992 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8993 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8994 {
8995 ThrowPerlException(exception,OptionError,
8996 "affine matrix is singular",PackageName);
8997 goto PerlException;
8998 }
8999 if (av_len(av) == 5)
9000 {
9001 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9002 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9003 }
9004 }
9005 for (j=10; j < 15; j++)
9006 {
9007 if (attribute_flag[j] == 0)
9008 continue;
9009 value=argument_list[j].string_reference;
9010 angle=argument_list[j].real_reference;
9011 current=draw_info->affine;
9012 GetAffineMatrix(&affine);
9013 switch (j)
9014 {
9015 case 10:
9016 {
9017 /*
9018 Translate.
9019 */
9020 flags=ParseGeometry(value,&geometry_info);
9021 affine.tx=geometry_info.xi;
9022 affine.ty=geometry_info.psi;
9023 if ((flags & PsiValue) == 0)
9024 affine.ty=affine.tx;
9025 break;
9026 }
9027 case 11:
9028 {
9029 /*
9030 Scale.
9031 */
9032 flags=ParseGeometry(value,&geometry_info);
9033 affine.sx=geometry_info.rho;
9034 affine.sy=geometry_info.sigma;
9035 if ((flags & SigmaValue) == 0)
9036 affine.sy=affine.sx;
9037 break;
9038 }
9039 case 12:
9040 {
9041 /*
9042 Rotate.
9043 */
9044 if (angle == 0.0)
9045 break;
9046 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9047 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9048 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9049 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9050 break;
9051 }
9052 case 13:
9053 {
9054 /*
9055 SkewX.
9056 */
9057 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9058 break;
9059 }
9060 case 14:
9061 {
9062 /*
9063 SkewY.
9064 */
9065 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9066 break;
9067 }
9068 }
9069 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9070 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9071 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9072 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9073 draw_info->affine.tx=
9074 current.sx*affine.tx+current.ry*affine.ty+current.tx;
9075 draw_info->affine.ty=
9076 current.rx*affine.tx+current.sy*affine.ty+current.ty;
9077 }
9078 if (attribute_flag[15] != 0)
9079 draw_info->fill_pattern=CloneImage(
9080 argument_list[15].image_reference,0,0,MagickTrue,exception);
9081 if (attribute_flag[16] != 0)
9082 draw_info->pointsize=argument_list[16].real_reference;
9083 if (attribute_flag[17] != 0)
9084 {
9085 draw_info->stroke_antialias=argument_list[17].integer_reference != 0
9086 ? MagickTrue : MagickFalse;
9087 draw_info->text_antialias=draw_info->stroke_antialias;
9088 }
9089 if (attribute_flag[18] != 0)
9090 (void) CloneString(&draw_info->density,
9091 argument_list[18].string_reference);
9092 if (attribute_flag[19] != 0)
9093 draw_info->stroke_width=argument_list[19].real_reference;
9094 if (attribute_flag[21] != 0)
9095 draw_info->dash_offset=argument_list[21].real_reference;
9096 if (attribute_flag[22] != 0)
9097 {
9098 AV
9099 *av;
9100
9101 av=(AV *) argument_list[22].array_reference;
9102 draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9103 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9104 if (draw_info->dash_pattern != (double *) NULL)
9105 {
9106 for (i=0; i <= av_len(av); i++)
9107 draw_info->dash_pattern[i]=(double)
9108 SvNV(*(av_fetch(av,i,0)));
9109 draw_info->dash_pattern[i]=0.0;
9110 }
9111 }
9112 if (attribute_flag[23] != 0)
9113 image->interpolate=(PixelInterpolateMethod)
9114 argument_list[23].integer_reference;
9115 if ((attribute_flag[24] != 0) &&
9116 (draw_info->fill_pattern != (Image *) NULL))
9117 flags=ParsePageGeometry(draw_info->fill_pattern,
9118 argument_list[24].string_reference,
9119 &draw_info->fill_pattern->tile_offset,exception);
9120 if (attribute_flag[25] != 0)
9121 {
9122 (void) ConcatenateString(&draw_info->primitive," '");
9123 (void) ConcatenateString(&draw_info->primitive,
9124 argument_list[25].string_reference);
9125 (void) ConcatenateString(&draw_info->primitive,"'");
9126 }
9127 if (attribute_flag[26] != 0)
9128 draw_info->fill_pattern=CloneImage(
9129 argument_list[26].image_reference,0,0,MagickTrue,exception);
9130 if (attribute_flag[27] != 0)
9131 draw_info->stroke_pattern=CloneImage(
9132 argument_list[27].image_reference,0,0,MagickTrue,exception);
9133 if (attribute_flag[28] != 0)
9134 (void) CloneString(&draw_info->primitive,
9135 argument_list[28].string_reference);
9136 if (attribute_flag[29] != 0)
9137 draw_info->kerning=argument_list[29].real_reference;
9138 if (attribute_flag[30] != 0)
9139 draw_info->interline_spacing=argument_list[30].real_reference;
9140 if (attribute_flag[31] != 0)
9141 draw_info->interword_spacing=argument_list[31].real_reference;
9142 if (attribute_flag[32] != 0)
9143 draw_info->direction=(DirectionType)
9144 argument_list[32].integer_reference;
9145 DrawImage(image,draw_info,exception);
9146 draw_info=DestroyDrawInfo(draw_info);
9147 break;
9148 }
9149 case 39: /* Equalize */
9150 {
9151 if (attribute_flag[0] != 0)
9152 channel=(ChannelType) argument_list[0].integer_reference;
9153 channel_mask=SetImageChannelMask(image,channel);
9154 EqualizeImage(image,exception);
9155 (void) SetImageChannelMask(image,channel_mask);
9156 break;
9157 }
9158 case 40: /* Gamma */
9159 {
9160 if (attribute_flag[1] != 0)
9161 channel=(ChannelType) argument_list[1].integer_reference;
9162 if (attribute_flag[2] == 0)
9163 argument_list[2].real_reference=1.0;
9164 if (attribute_flag[3] == 0)
9165 argument_list[3].real_reference=1.0;
9166 if (attribute_flag[4] == 0)
9167 argument_list[4].real_reference=1.0;
9168 if (attribute_flag[0] == 0)
9169 {
cristy151b66d2015-04-15 10:50:31 +00009170 (void) FormatLocaleString(message,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -05009171 "%.20g,%.20g,%.20g",(double) argument_list[2].real_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009172 (double) argument_list[3].real_reference,
9173 (double) argument_list[4].real_reference);
9174 argument_list[0].string_reference=message;
9175 }
9176 (void) GammaImage(image,StringToDouble(
9177 argument_list[0].string_reference,(char **) NULL),exception);
9178 break;
9179 }
9180 case 41: /* Map */
9181 {
9182 QuantizeInfo
9183 *quantize_info;
9184
9185 if (attribute_flag[0] == 0)
9186 {
9187 ThrowPerlException(exception,OptionError,"MapImageRequired",
9188 PackageName);
9189 goto PerlException;
9190 }
9191 quantize_info=AcquireQuantizeInfo(info->image_info);
9192 if (attribute_flag[1] != 0)
9193 quantize_info->dither_method=(DitherMethod)
9194 argument_list[1].integer_reference;
9195 (void) RemapImages(quantize_info,image,
9196 argument_list[0].image_reference,exception);
9197 quantize_info=DestroyQuantizeInfo(quantize_info);
9198 break;
9199 }
9200 case 42: /* MatteFloodfill */
9201 {
9202 DrawInfo
9203 *draw_info;
9204
9205 MagickBooleanType
9206 invert;
9207
9208 PixelInfo
9209 target;
9210
9211 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9212 (DrawInfo *) NULL);
9213 if (attribute_flag[0] != 0)
9214 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9215 &geometry,exception);
9216 if (attribute_flag[1] != 0)
9217 geometry.x=argument_list[1].integer_reference;
9218 if (attribute_flag[2] != 0)
9219 geometry.y=argument_list[2].integer_reference;
cristy17f11b02014-12-20 19:37:04 +00009220 if (image->alpha_trait == UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00009221 (void) SetImageAlpha(image,OpaqueAlpha,exception);
9222 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9223 geometry.x,geometry.y,&target,exception);
9224 if (attribute_flag[4] != 0)
9225 QueryColorCompliance(argument_list[4].string_reference,
9226 AllCompliance,&target,exception);
9227 if (attribute_flag[3] != 0)
9228 target.alpha=StringToDoubleInterval(
9229 argument_list[3].string_reference,(double) (double) QuantumRange+
9230 1.0);
9231 if (attribute_flag[5] != 0)
9232 image->fuzz=StringToDoubleInterval(
9233 argument_list[5].string_reference,(double) QuantumRange+1.0);
9234 invert=MagickFalse;
9235 if (attribute_flag[6] != 0)
9236 invert=(MagickBooleanType) argument_list[6].integer_reference;
9237 channel_mask=SetImageChannelMask(image,AlphaChannel);
9238 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9239 geometry.y,invert,exception);
9240 (void) SetImageChannelMask(image,channel_mask);
9241 draw_info=DestroyDrawInfo(draw_info);
9242 break;
9243 }
9244 case 43: /* Modulate */
9245 {
9246 char
cristy151b66d2015-04-15 10:50:31 +00009247 modulate[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00009248
9249 geometry_info.rho=100.0;
9250 geometry_info.sigma=100.0;
9251 geometry_info.xi=100.0;
9252 if (attribute_flag[0] != 0)
9253 (void)ParseGeometry(argument_list[0].string_reference,
9254 &geometry_info);
9255 if (attribute_flag[1] != 0)
9256 geometry_info.xi=argument_list[1].real_reference;
9257 if (attribute_flag[2] != 0)
9258 geometry_info.sigma=argument_list[2].real_reference;
9259 if (attribute_flag[3] != 0)
9260 {
9261 geometry_info.sigma=argument_list[3].real_reference;
9262 SetImageArtifact(image,"modulate:colorspace","HWB");
9263 }
9264 if (attribute_flag[4] != 0)
9265 {
9266 geometry_info.rho=argument_list[4].real_reference;
9267 SetImageArtifact(image,"modulate:colorspace","HSB");
9268 }
9269 if (attribute_flag[5] != 0)
9270 {
9271 geometry_info.sigma=argument_list[5].real_reference;
9272 SetImageArtifact(image,"modulate:colorspace","HSL");
9273 }
9274 if (attribute_flag[6] != 0)
9275 {
9276 geometry_info.rho=argument_list[6].real_reference;
9277 SetImageArtifact(image,"modulate:colorspace","HWB");
9278 }
Cristy935a4052017-03-31 17:45:37 -04009279 (void) FormatLocaleString(modulate,MagickPathExtent,"%.20g,%.20g,%.20g",
9280 geometry_info.rho,geometry_info.sigma,geometry_info.xi);
cristy4a3ce0a2013-08-03 20:06:59 +00009281 (void) ModulateImage(image,modulate,exception);
9282 break;
9283 }
9284 case 44: /* Negate */
9285 {
9286 if (attribute_flag[0] == 0)
9287 argument_list[0].integer_reference=0;
9288 if (attribute_flag[1] != 0)
9289 channel=(ChannelType) argument_list[1].integer_reference;
9290 channel_mask=SetImageChannelMask(image,channel);
9291 (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9292 MagickTrue : MagickFalse,exception);
9293 (void) SetImageChannelMask(image,channel_mask);
9294 break;
9295 }
9296 case 45: /* Normalize */
9297 {
9298 if (attribute_flag[0] != 0)
9299 channel=(ChannelType) argument_list[0].integer_reference;
9300 channel_mask=SetImageChannelMask(image,channel);
9301 NormalizeImage(image,exception);
9302 (void) SetImageChannelMask(image,channel_mask);
9303 break;
9304 }
9305 case 46: /* NumberColors */
9306 break;
9307 case 47: /* Opaque */
9308 {
9309 MagickBooleanType
9310 invert;
9311
9312 PixelInfo
9313 fill_color,
9314 target;
9315
9316 (void) QueryColorCompliance("none",AllCompliance,&target,
9317 exception);
9318 (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9319 exception);
9320 if (attribute_flag[0] != 0)
9321 (void) QueryColorCompliance(argument_list[0].string_reference,
9322 AllCompliance,&target,exception);
9323 if (attribute_flag[1] != 0)
9324 (void) QueryColorCompliance(argument_list[1].string_reference,
9325 AllCompliance,&fill_color,exception);
9326 if (attribute_flag[2] != 0)
9327 image->fuzz=StringToDoubleInterval(
9328 argument_list[2].string_reference,(double) QuantumRange+1.0);
9329 if (attribute_flag[3] != 0)
9330 channel=(ChannelType) argument_list[3].integer_reference;
9331 invert=MagickFalse;
9332 if (attribute_flag[4] != 0)
9333 invert=(MagickBooleanType) argument_list[4].integer_reference;
9334 channel_mask=SetImageChannelMask(image,channel);
9335 (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9336 (void) SetImageChannelMask(image,channel_mask);
9337 break;
9338 }
9339 case 48: /* Quantize */
9340 {
9341 QuantizeInfo
9342 *quantize_info;
9343
9344 quantize_info=AcquireQuantizeInfo(info->image_info);
9345 if (attribute_flag[0] != 0)
9346 quantize_info->number_colors=(size_t)
9347 argument_list[0].integer_reference;
9348 if (attribute_flag[1] != 0)
9349 quantize_info->tree_depth=(size_t)
9350 argument_list[1].integer_reference;
9351 if (attribute_flag[2] != 0)
9352 quantize_info->colorspace=(ColorspaceType)
9353 argument_list[2].integer_reference;
9354 if (attribute_flag[3] != 0)
cristy785c9342014-03-19 22:06:39 +00009355 quantize_info->dither_method=(DitherMethod)
9356 argument_list[3].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00009357 if (attribute_flag[4] != 0)
cristy71716d52014-03-19 10:11:11 +00009358 quantize_info->measure_error=
9359 argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
cristy4a3ce0a2013-08-03 20:06:59 +00009360 if (attribute_flag[6] != 0)
cristyd472dd82014-03-19 22:04:36 +00009361 (void) QueryColorCompliance(argument_list[6].string_reference,
cristyf7563392014-03-25 13:54:04 +00009362 AllCompliance,&image->transparent_color,exception);
cristy71716d52014-03-19 10:11:11 +00009363 if (attribute_flag[7] != 0)
cristy4a3ce0a2013-08-03 20:06:59 +00009364 quantize_info->dither_method=(DitherMethod)
cristy71716d52014-03-19 10:11:11 +00009365 argument_list[7].integer_reference;
9366 if (attribute_flag[5] && argument_list[5].integer_reference)
cristyf7563392014-03-25 13:54:04 +00009367 (void) QuantizeImages(quantize_info,image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009368 else
cristyf7563392014-03-25 13:54:04 +00009369 if ((image->storage_class == DirectClass) ||
9370 (image->colors > quantize_info->number_colors) ||
9371 (quantize_info->colorspace == GRAYColorspace))
9372 (void) QuantizeImage(quantize_info,image,exception);
9373 else
9374 CompressImageColormap(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009375 quantize_info=DestroyQuantizeInfo(quantize_info);
9376 break;
9377 }
9378 case 49: /* Raise */
9379 {
9380 if (attribute_flag[0] != 0)
9381 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9382 &geometry,exception);
9383 if (attribute_flag[1] != 0)
9384 geometry.width=argument_list[1].integer_reference;
9385 if (attribute_flag[2] != 0)
9386 geometry.height=argument_list[2].integer_reference;
9387 if (attribute_flag[3] == 0)
9388 argument_list[3].integer_reference=1;
9389 (void) RaiseImage(image,&geometry,
9390 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9391 exception);
9392 break;
9393 }
9394 case 50: /* Segment */
9395 {
9396 ColorspaceType
9397 colorspace;
9398
9399 double
9400 cluster_threshold,
9401 smoothing_threshold;
9402
9403 MagickBooleanType
9404 verbose;
9405
9406 cluster_threshold=1.0;
9407 smoothing_threshold=1.5;
9408 colorspace=sRGBColorspace;
9409 verbose=MagickFalse;
9410 if (attribute_flag[0] != 0)
9411 {
9412 flags=ParseGeometry(argument_list[0].string_reference,
9413 &geometry_info);
9414 cluster_threshold=geometry_info.rho;
9415 if (flags & SigmaValue)
9416 smoothing_threshold=geometry_info.sigma;
9417 }
9418 if (attribute_flag[1] != 0)
9419 cluster_threshold=argument_list[1].real_reference;
9420 if (attribute_flag[2] != 0)
9421 smoothing_threshold=argument_list[2].real_reference;
9422 if (attribute_flag[3] != 0)
9423 colorspace=(ColorspaceType) argument_list[3].integer_reference;
9424 if (attribute_flag[4] != 0)
9425 verbose=argument_list[4].integer_reference != 0 ?
9426 MagickTrue : MagickFalse;
9427 (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9428 smoothing_threshold,exception);
9429 break;
9430 }
9431 case 51: /* Signature */
9432 {
9433 (void) SignatureImage(image,exception);
9434 break;
9435 }
9436 case 52: /* Solarize */
9437 {
9438 geometry_info.rho=QuantumRange/2.0;
9439 if (attribute_flag[0] != 0)
9440 flags=ParseGeometry(argument_list[0].string_reference,
9441 &geometry_info);
9442 if (attribute_flag[1] != 0)
9443 geometry_info.rho=StringToDoubleInterval(
9444 argument_list[1].string_reference,(double) QuantumRange+1.0);
9445 (void) SolarizeImage(image,geometry_info.rho,exception);
9446 break;
9447 }
9448 case 53: /* Sync */
9449 {
9450 (void) SyncImage(image,exception);
9451 break;
9452 }
9453 case 54: /* Texture */
9454 {
9455 if (attribute_flag[0] == 0)
9456 break;
9457 TextureImage(image,argument_list[0].image_reference,exception);
9458 break;
9459 }
9460 case 55: /* Evalute */
9461 {
9462 MagickEvaluateOperator
9463 op;
9464
9465 op=SetEvaluateOperator;
9466 if (attribute_flag[0] == MagickFalse)
9467 argument_list[0].real_reference=0.0;
9468 if (attribute_flag[1] != MagickFalse)
9469 op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9470 if (attribute_flag[2] != MagickFalse)
9471 channel=(ChannelType) argument_list[2].integer_reference;
9472 channel_mask=SetImageChannelMask(image,channel);
9473 (void) EvaluateImage(image,op,argument_list[0].real_reference,
9474 exception);
9475 (void) SetImageChannelMask(image,channel_mask);
9476 break;
9477 }
9478 case 56: /* Transparent */
9479 {
9480 double
9481 opacity;
9482
9483 MagickBooleanType
9484 invert;
9485
9486 PixelInfo
9487 target;
9488
9489 (void) QueryColorCompliance("none",AllCompliance,&target,
9490 exception);
9491 if (attribute_flag[0] != 0)
9492 (void) QueryColorCompliance(argument_list[0].string_reference,
9493 AllCompliance,&target,exception);
9494 opacity=TransparentAlpha;
9495 if (attribute_flag[1] != 0)
9496 opacity=StringToDoubleInterval(argument_list[1].string_reference,
9497 (double) QuantumRange+1.0);
9498 if (attribute_flag[2] != 0)
9499 image->fuzz=StringToDoubleInterval(
9500 argument_list[2].string_reference,(double) QuantumRange+1.0);
9501 if (attribute_flag[3] == 0)
9502 argument_list[3].integer_reference=0;
9503 invert=MagickFalse;
9504 if (attribute_flag[3] != 0)
9505 invert=(MagickBooleanType) argument_list[3].integer_reference;
9506 (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9507 invert,exception);
9508 break;
9509 }
9510 case 57: /* Threshold */
9511 {
9512 double
9513 threshold;
9514
9515 if (attribute_flag[0] == 0)
9516 argument_list[0].string_reference="50%";
9517 if (attribute_flag[1] != 0)
9518 channel=(ChannelType) argument_list[1].integer_reference;
9519 threshold=StringToDoubleInterval(argument_list[0].string_reference,
9520 (double) QuantumRange+1.0);
9521 channel_mask=SetImageChannelMask(image,channel);
9522 (void) BilevelImage(image,threshold,exception);
9523 (void) SetImageChannelMask(image,channel_mask);
9524 break;
9525 }
9526 case 58: /* Charcoal */
9527 {
9528 if (attribute_flag[0] != 0)
9529 {
9530 flags=ParseGeometry(argument_list[0].string_reference,
9531 &geometry_info);
9532 if ((flags & SigmaValue) == 0)
9533 geometry_info.sigma=1.0;
9534 }
9535 if (attribute_flag[1] != 0)
9536 geometry_info.rho=argument_list[1].real_reference;
9537 if (attribute_flag[2] != 0)
9538 geometry_info.sigma=argument_list[2].real_reference;
9539 image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9540 exception);
9541 break;
9542 }
9543 case 59: /* Trim */
9544 {
9545 if (attribute_flag[0] != 0)
9546 image->fuzz=StringToDoubleInterval(
9547 argument_list[0].string_reference,(double) QuantumRange+1.0);
9548 image=TrimImage(image,exception);
9549 break;
9550 }
9551 case 60: /* Wave */
9552 {
9553 PixelInterpolateMethod
9554 method;
9555
9556 if (attribute_flag[0] != 0)
9557 {
9558 flags=ParseGeometry(argument_list[0].string_reference,
9559 &geometry_info);
9560 if ((flags & SigmaValue) == 0)
9561 geometry_info.sigma=1.0;
9562 }
9563 if (attribute_flag[1] != 0)
9564 geometry_info.rho=argument_list[1].real_reference;
9565 if (attribute_flag[2] != 0)
9566 geometry_info.sigma=argument_list[2].real_reference;
9567 method=UndefinedInterpolatePixel;
9568 if (attribute_flag[3] != 0)
9569 method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9570 image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9571 method,exception);
9572 break;
9573 }
9574 case 61: /* Separate */
9575 {
9576 if (attribute_flag[0] != 0)
9577 channel=(ChannelType) argument_list[0].integer_reference;
9578 image=SeparateImage(image,channel,exception);
9579 break;
9580 }
9581 case 63: /* Stereo */
9582 {
9583 if (attribute_flag[0] == 0)
9584 {
9585 ThrowPerlException(exception,OptionError,"StereoImageRequired",
9586 PackageName);
9587 goto PerlException;
9588 }
9589 if (attribute_flag[1] != 0)
9590 geometry.x=argument_list[1].integer_reference;
9591 if (attribute_flag[2] != 0)
9592 geometry.y=argument_list[2].integer_reference;
9593 image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9594 geometry.x,geometry.y,exception);
9595 break;
9596 }
9597 case 64: /* Stegano */
9598 {
9599 if (attribute_flag[0] == 0)
9600 {
9601 ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9602 PackageName);
9603 goto PerlException;
9604 }
9605 if (attribute_flag[1] == 0)
9606 argument_list[1].integer_reference=0;
9607 image->offset=argument_list[1].integer_reference;
9608 image=SteganoImage(image,argument_list[0].image_reference,exception);
9609 break;
9610 }
9611 case 65: /* Deconstruct */
9612 {
9613 image=CompareImagesLayers(image,CompareAnyLayer,exception);
9614 break;
9615 }
9616 case 66: /* GaussianBlur */
9617 {
9618 if (attribute_flag[0] != 0)
9619 {
9620 flags=ParseGeometry(argument_list[0].string_reference,
9621 &geometry_info);
9622 if ((flags & SigmaValue) == 0)
9623 geometry_info.sigma=1.0;
9624 }
9625 if (attribute_flag[1] != 0)
9626 geometry_info.rho=argument_list[1].real_reference;
9627 if (attribute_flag[2] != 0)
9628 geometry_info.sigma=argument_list[2].real_reference;
9629 if (attribute_flag[3] != 0)
9630 channel=(ChannelType) argument_list[3].integer_reference;
9631 channel_mask=SetImageChannelMask(image,channel);
9632 image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9633 exception);
9634 if (image != (Image *) NULL)
9635 (void) SetImageChannelMask(image,channel_mask);
9636 break;
9637 }
9638 case 67: /* Convolve */
9639 {
9640 KernelInfo
9641 *kernel;
9642
9643 kernel=(KernelInfo *) NULL;
9644 if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9645 break;
9646 if (attribute_flag[0] != 0)
9647 {
9648 AV
9649 *av;
9650
9651 size_t
9652 order;
9653
cristy2c57b742014-10-31 00:40:34 +00009654 kernel=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009655 if (kernel == (KernelInfo *) NULL)
9656 break;
9657 av=(AV *) argument_list[0].array_reference;
9658 order=(size_t) sqrt(av_len(av)+1);
9659 kernel->width=order;
9660 kernel->height=order;
9661 kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9662 order*sizeof(*kernel->values));
9663 if (kernel->values == (MagickRealType *) NULL)
9664 {
9665 kernel=DestroyKernelInfo(kernel);
9666 ThrowPerlException(exception,ResourceLimitFatalError,
9667 "MemoryAllocationFailed",PackageName);
9668 goto PerlException;
9669 }
9670 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9671 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9672 for ( ; j < (ssize_t) (order*order); j++)
9673 kernel->values[j]=0.0;
9674 }
9675 if (attribute_flag[1] != 0)
9676 channel=(ChannelType) argument_list[1].integer_reference;
9677 if (attribute_flag[2] != 0)
Cristyc4ff6bd2017-07-05 21:00:11 -04009678 SetImageArtifact(image,"convolve:bias",
cristy4a3ce0a2013-08-03 20:06:59 +00009679 argument_list[2].string_reference);
9680 if (attribute_flag[3] != 0)
9681 {
cristy2c57b742014-10-31 00:40:34 +00009682 kernel=AcquireKernelInfo(argument_list[3].string_reference,
9683 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009684 if (kernel == (KernelInfo *) NULL)
9685 break;
9686 }
9687 channel_mask=SetImageChannelMask(image,channel);
9688 image=ConvolveImage(image,kernel,exception);
9689 if (image != (Image *) NULL)
9690 (void) SetImageChannelMask(image,channel_mask);
9691 kernel=DestroyKernelInfo(kernel);
9692 break;
9693 }
9694 case 68: /* Profile */
9695 {
9696 const char
9697 *name;
9698
9699 Image
9700 *profile_image;
9701
9702 ImageInfo
9703 *profile_info;
9704
9705 StringInfo
9706 *profile;
9707
9708 name="*";
9709 if (attribute_flag[0] != 0)
9710 name=argument_list[0].string_reference;
9711 if (attribute_flag[2] != 0)
9712 image->rendering_intent=(RenderingIntent)
9713 argument_list[2].integer_reference;
9714 if (attribute_flag[3] != 0)
9715 image->black_point_compensation=
9716 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9717 if (attribute_flag[1] != 0)
9718 {
9719 if (argument_list[1].length == 0)
9720 {
9721 /*
9722 Remove a profile from the image.
9723 */
9724 (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9725 exception);
9726 break;
9727 }
9728 /*
9729 Associate user supplied profile with the image.
9730 */
9731 profile=AcquireStringInfo(argument_list[1].length);
9732 SetStringInfoDatum(profile,(const unsigned char *)
9733 argument_list[1].string_reference);
9734 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9735 (size_t) GetStringInfoLength(profile),exception);
9736 profile=DestroyStringInfo(profile);
9737 break;
9738 }
9739 /*
9740 Associate a profile with the image.
9741 */
9742 profile_info=CloneImageInfo(info ? info->image_info :
9743 (ImageInfo *) NULL);
9744 profile_image=ReadImages(profile_info,name,exception);
9745 if (profile_image == (Image *) NULL)
9746 break;
9747 ResetImageProfileIterator(profile_image);
9748 name=GetNextImageProfile(profile_image);
9749 while (name != (const char *) NULL)
9750 {
9751 const StringInfo
9752 *profile;
9753
9754 profile=GetImageProfile(profile_image,name);
9755 if (profile != (const StringInfo *) NULL)
9756 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9757 (size_t) GetStringInfoLength(profile),exception);
9758 name=GetNextImageProfile(profile_image);
9759 }
9760 profile_image=DestroyImage(profile_image);
9761 profile_info=DestroyImageInfo(profile_info);
9762 break;
9763 }
9764 case 69: /* UnsharpMask */
9765 {
9766 if (attribute_flag[0] != 0)
9767 {
9768 flags=ParseGeometry(argument_list[0].string_reference,
9769 &geometry_info);
9770 if ((flags & SigmaValue) == 0)
9771 geometry_info.sigma=1.0;
9772 if ((flags & XiValue) == 0)
9773 geometry_info.xi=1.0;
9774 if ((flags & PsiValue) == 0)
9775 geometry_info.psi=0.5;
9776 }
9777 if (attribute_flag[1] != 0)
9778 geometry_info.rho=argument_list[1].real_reference;
9779 if (attribute_flag[2] != 0)
9780 geometry_info.sigma=argument_list[2].real_reference;
9781 if (attribute_flag[3] != 0)
9782 geometry_info.xi=argument_list[3].real_reference;
9783 if (attribute_flag[4] != 0)
9784 geometry_info.psi=argument_list[4].real_reference;
9785 if (attribute_flag[5] != 0)
9786 channel=(ChannelType) argument_list[5].integer_reference;
9787 channel_mask=SetImageChannelMask(image,channel);
9788 image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9789 geometry_info.xi,geometry_info.psi,exception);
9790 if (image != (Image *) NULL)
9791 (void) SetImageChannelMask(image,channel_mask);
9792 break;
9793 }
9794 case 70: /* MotionBlur */
9795 {
9796 if (attribute_flag[0] != 0)
9797 {
9798 flags=ParseGeometry(argument_list[0].string_reference,
9799 &geometry_info);
9800 if ((flags & SigmaValue) == 0)
9801 geometry_info.sigma=1.0;
9802 if ((flags & XiValue) == 0)
9803 geometry_info.xi=1.0;
9804 }
9805 if (attribute_flag[1] != 0)
9806 geometry_info.rho=argument_list[1].real_reference;
9807 if (attribute_flag[2] != 0)
9808 geometry_info.sigma=argument_list[2].real_reference;
9809 if (attribute_flag[3] != 0)
9810 geometry_info.xi=argument_list[3].real_reference;
9811 if (attribute_flag[4] != 0)
9812 channel=(ChannelType) argument_list[4].integer_reference;
9813 channel_mask=SetImageChannelMask(image,channel);
9814 image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9815 geometry_info.xi,exception);
9816 if (image != (Image *) NULL)
9817 (void) SetImageChannelMask(image,channel_mask);
9818 break;
9819 }
9820 case 71: /* OrderedDither */
9821 {
9822 if (attribute_flag[0] == 0)
9823 argument_list[0].string_reference="o8x8";
9824 if (attribute_flag[1] != 0)
9825 channel=(ChannelType) argument_list[1].integer_reference;
9826 channel_mask=SetImageChannelMask(image,channel);
Cristy6b93c072016-02-04 07:45:48 -05009827 (void) OrderedDitherImage(image,argument_list[0].string_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009828 exception);
9829 (void) SetImageChannelMask(image,channel_mask);
9830 break;
9831 }
9832 case 72: /* Shave */
9833 {
9834 if (attribute_flag[0] != 0)
9835 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9836 &geometry,exception);
9837 if (attribute_flag[1] != 0)
9838 geometry.width=argument_list[1].integer_reference;
9839 if (attribute_flag[2] != 0)
9840 geometry.height=argument_list[2].integer_reference;
9841 image=ShaveImage(image,&geometry,exception);
9842 break;
9843 }
9844 case 73: /* Level */
9845 {
9846 double
9847 black_point,
9848 gamma,
9849 white_point;
9850
9851 black_point=0.0;
9852 white_point=(double) image->columns*image->rows;
9853 gamma=1.0;
9854 if (attribute_flag[0] != 0)
9855 {
9856 flags=ParseGeometry(argument_list[0].string_reference,
9857 &geometry_info);
9858 black_point=geometry_info.rho;
9859 if ((flags & SigmaValue) != 0)
9860 white_point=geometry_info.sigma;
9861 if ((flags & XiValue) != 0)
9862 gamma=geometry_info.xi;
9863 if ((flags & PercentValue) != 0)
9864 {
9865 black_point*=(double) (QuantumRange/100.0);
9866 white_point*=(double) (QuantumRange/100.0);
9867 }
9868 if ((flags & SigmaValue) == 0)
9869 white_point=(double) QuantumRange-black_point;
9870 }
9871 if (attribute_flag[1] != 0)
9872 black_point=argument_list[1].real_reference;
9873 if (attribute_flag[2] != 0)
9874 white_point=argument_list[2].real_reference;
9875 if (attribute_flag[3] != 0)
9876 gamma=argument_list[3].real_reference;
9877 if (attribute_flag[4] != 0)
9878 channel=(ChannelType) argument_list[4].integer_reference;
9879 if (attribute_flag[5] != 0)
9880 {
9881 argument_list[0].real_reference=argument_list[5].real_reference;
9882 attribute_flag[0]=attribute_flag[5];
9883 }
9884 channel_mask=SetImageChannelMask(image,channel);
9885 (void) LevelImage(image,black_point,white_point,gamma,exception);
9886 (void) SetImageChannelMask(image,channel_mask);
9887 break;
9888 }
9889 case 74: /* Clip */
9890 {
9891 if (attribute_flag[0] == 0)
9892 argument_list[0].string_reference="#1";
9893 if (attribute_flag[1] == 0)
9894 argument_list[1].integer_reference=MagickTrue;
9895 (void) ClipImagePath(image,argument_list[0].string_reference,
9896 argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9897 exception);
9898 break;
9899 }
9900 case 75: /* AffineTransform */
9901 {
9902 DrawInfo
9903 *draw_info;
9904
9905 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9906 (DrawInfo *) NULL);
9907 if (attribute_flag[0] != 0)
9908 {
9909 AV
9910 *av;
9911
9912 av=(AV *) argument_list[0].array_reference;
9913 if ((av_len(av) != 3) && (av_len(av) != 5))
9914 {
9915 ThrowPerlException(exception,OptionError,
9916 "affine matrix must have 4 or 6 elements",PackageName);
9917 goto PerlException;
9918 }
9919 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9920 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9921 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9922 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9923 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9924 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9925 {
9926 ThrowPerlException(exception,OptionError,
9927 "affine matrix is singular",PackageName);
9928 goto PerlException;
9929 }
9930 if (av_len(av) == 5)
9931 {
9932 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9933 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9934 }
9935 }
9936 for (j=1; j < 6; j++)
9937 {
9938 if (attribute_flag[j] == 0)
9939 continue;
9940 value=argument_list[j].string_reference;
9941 angle=argument_list[j].real_reference;
9942 current=draw_info->affine;
9943 GetAffineMatrix(&affine);
9944 switch (j)
9945 {
9946 case 1:
9947 {
9948 /*
9949 Translate.
9950 */
9951 flags=ParseGeometry(value,&geometry_info);
9952 affine.tx=geometry_info.xi;
9953 affine.ty=geometry_info.psi;
9954 if ((flags & PsiValue) == 0)
9955 affine.ty=affine.tx;
9956 break;
9957 }
9958 case 2:
9959 {
9960 /*
9961 Scale.
9962 */
9963 flags=ParseGeometry(value,&geometry_info);
9964 affine.sx=geometry_info.rho;
9965 affine.sy=geometry_info.sigma;
9966 if ((flags & SigmaValue) == 0)
9967 affine.sy=affine.sx;
9968 break;
9969 }
9970 case 3:
9971 {
9972 /*
9973 Rotate.
9974 */
9975 if (angle == 0.0)
9976 break;
9977 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9978 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9979 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9980 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9981 break;
9982 }
9983 case 4:
9984 {
9985 /*
9986 SkewX.
9987 */
9988 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9989 break;
9990 }
9991 case 5:
9992 {
9993 /*
9994 SkewY.
9995 */
9996 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9997 break;
9998 }
9999 }
10000 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
10001 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
10002 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
10003 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
10004 draw_info->affine.tx=
10005 current.sx*affine.tx+current.ry*affine.ty+current.tx;
10006 draw_info->affine.ty=
10007 current.rx*affine.tx+current.sy*affine.ty+current.ty;
10008 }
10009 if (attribute_flag[6] != 0)
10010 image->interpolate=(PixelInterpolateMethod)
10011 argument_list[6].integer_reference;
10012 if (attribute_flag[7] != 0)
10013 QueryColorCompliance(argument_list[7].string_reference,
10014 AllCompliance,&image->background_color,exception);
10015 image=AffineTransformImage(image,&draw_info->affine,exception);
10016 draw_info=DestroyDrawInfo(draw_info);
10017 break;
10018 }
10019 case 76: /* Difference */
10020 {
10021 if (attribute_flag[0] == 0)
10022 {
10023 ThrowPerlException(exception,OptionError,
10024 "ReferenceImageRequired",PackageName);
10025 goto PerlException;
10026 }
10027 if (attribute_flag[1] != 0)
10028 image->fuzz=StringToDoubleInterval(
10029 argument_list[1].string_reference,(double) QuantumRange+1.0);
Cristyf2479812015-12-12 12:17:43 -050010030 (void) SetImageColorMetric(image,argument_list[0].image_reference,
cristy4a3ce0a2013-08-03 20:06:59 +000010031 exception);
10032 break;
10033 }
10034 case 77: /* AdaptiveThreshold */
10035 {
10036 if (attribute_flag[0] != 0)
10037 {
10038 flags=ParseGeometry(argument_list[0].string_reference,
10039 &geometry_info);
10040 if ((flags & PercentValue) != 0)
10041 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10042 }
10043 if (attribute_flag[1] != 0)
10044 geometry_info.rho=argument_list[1].integer_reference;
10045 if (attribute_flag[2] != 0)
10046 geometry_info.sigma=argument_list[2].integer_reference;
10047 if (attribute_flag[3] != 0)
10048 geometry_info.xi=argument_list[3].integer_reference;;
10049 image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
10050 (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
10051 break;
10052 }
10053 case 78: /* Resample */
10054 {
10055 size_t
10056 height,
10057 width;
10058
10059 if (attribute_flag[0] != 0)
10060 {
10061 flags=ParseGeometry(argument_list[0].string_reference,
10062 &geometry_info);
10063 if ((flags & SigmaValue) == 0)
10064 geometry_info.sigma=geometry_info.rho;
10065 }
10066 if (attribute_flag[1] != 0)
10067 geometry_info.rho=argument_list[1].real_reference;
10068 if (attribute_flag[2] != 0)
10069 geometry_info.sigma=argument_list[2].real_reference;
10070 if (attribute_flag[3] == 0)
10071 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10072 if (attribute_flag[4] == 0)
10073 SetImageArtifact(image,"filter:support",
10074 argument_list[4].string_reference);
10075 width=(size_t) (geometry_info.rho*image->columns/
10076 (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10077 height=(size_t) (geometry_info.sigma*image->rows/
10078 (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
Cristy8645e042016-02-03 16:35:29 -050010079 image=ResizeImage(image,width,height,(FilterType)
cristy4a3ce0a2013-08-03 20:06:59 +000010080 argument_list[3].integer_reference,exception);
10081 if (image != (Image *) NULL)
10082 {
10083 image->resolution.x=geometry_info.rho;
10084 image->resolution.y=geometry_info.sigma;
10085 }
10086 break;
10087 }
10088 case 79: /* Describe */
10089 {
10090 if (attribute_flag[0] == 0)
10091 argument_list[0].file_reference=(FILE *) NULL;
10092 if (attribute_flag[1] != 0)
10093 (void) SetImageArtifact(image,"identify:features",
10094 argument_list[1].string_reference);
10095 (void) IdentifyImage(image,argument_list[0].file_reference,
10096 MagickTrue,exception);
10097 break;
10098 }
10099 case 80: /* BlackThreshold */
10100 {
10101 if (attribute_flag[0] == 0)
10102 argument_list[0].string_reference="50%";
10103 if (attribute_flag[2] != 0)
10104 channel=(ChannelType) argument_list[2].integer_reference;
10105 channel_mask=SetImageChannelMask(image,channel);
10106 BlackThresholdImage(image,argument_list[0].string_reference,
10107 exception);
10108 (void) SetImageChannelMask(image,channel_mask);
10109 break;
10110 }
10111 case 81: /* WhiteThreshold */
10112 {
10113 if (attribute_flag[0] == 0)
10114 argument_list[0].string_reference="50%";
10115 if (attribute_flag[2] != 0)
10116 channel=(ChannelType) argument_list[2].integer_reference;
10117 channel_mask=SetImageChannelMask(image,channel);
10118 WhiteThresholdImage(image,argument_list[0].string_reference,
10119 exception);
10120 (void) SetImageChannelMask(image,channel_mask);
10121 break;
10122 }
cristy60c73c02014-03-25 12:09:58 +000010123 case 82: /* RotationalBlur */
cristy4a3ce0a2013-08-03 20:06:59 +000010124 {
10125 if (attribute_flag[0] != 0)
10126 {
10127 flags=ParseGeometry(argument_list[0].string_reference,
10128 &geometry_info);
10129 }
10130 if (attribute_flag[1] != 0)
10131 geometry_info.rho=argument_list[1].real_reference;
10132 if (attribute_flag[2] != 0)
10133 channel=(ChannelType) argument_list[2].integer_reference;
10134 channel_mask=SetImageChannelMask(image,channel);
cristy49d4d222014-03-16 00:37:58 +000010135 image=RotationalBlurImage(image,geometry_info.rho,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010136 if (image != (Image *) NULL)
10137 (void) SetImageChannelMask(image,channel_mask);
10138 break;
10139 }
10140 case 83: /* Thumbnail */
10141 {
10142 if (attribute_flag[0] != 0)
10143 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10144 &geometry,exception);
10145 if (attribute_flag[1] != 0)
10146 geometry.width=argument_list[1].integer_reference;
10147 if (attribute_flag[2] != 0)
10148 geometry.height=argument_list[2].integer_reference;
10149 image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10150 break;
10151 }
10152 case 84: /* Strip */
10153 {
10154 (void) StripImage(image,exception);
10155 break;
10156 }
10157 case 85: /* Tint */
10158 {
10159 PixelInfo
10160 tint;
10161
10162 GetPixelInfo(image,&tint);
10163 if (attribute_flag[0] != 0)
10164 (void) QueryColorCompliance(argument_list[0].string_reference,
10165 AllCompliance,&tint,exception);
10166 if (attribute_flag[1] == 0)
10167 argument_list[1].string_reference="100";
10168 image=TintImage(image,argument_list[1].string_reference,&tint,
10169 exception);
10170 break;
10171 }
10172 case 86: /* Channel */
10173 {
10174 if (attribute_flag[0] != 0)
10175 channel=(ChannelType) argument_list[0].integer_reference;
10176 image=SeparateImage(image,channel,exception);
10177 break;
10178 }
10179 case 87: /* Splice */
10180 {
cristy260bd762014-08-15 12:46:34 +000010181 if (attribute_flag[7] != 0)
10182 image->gravity=(GravityType) argument_list[7].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010183 if (attribute_flag[0] != 0)
10184 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10185 &geometry,exception);
10186 if (attribute_flag[1] != 0)
10187 geometry.width=argument_list[1].integer_reference;
10188 if (attribute_flag[2] != 0)
10189 geometry.height=argument_list[2].integer_reference;
10190 if (attribute_flag[3] != 0)
10191 geometry.x=argument_list[3].integer_reference;
10192 if (attribute_flag[4] != 0)
10193 geometry.y=argument_list[4].integer_reference;
10194 if (attribute_flag[5] != 0)
10195 image->fuzz=StringToDoubleInterval(
10196 argument_list[5].string_reference,(double) QuantumRange+1.0);
10197 if (attribute_flag[6] != 0)
10198 (void) QueryColorCompliance(argument_list[6].string_reference,
10199 AllCompliance,&image->background_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010200 image=SpliceImage(image,&geometry,exception);
10201 break;
10202 }
10203 case 88: /* Posterize */
10204 {
10205 if (attribute_flag[0] == 0)
10206 argument_list[0].integer_reference=3;
10207 if (attribute_flag[1] == 0)
10208 argument_list[1].integer_reference=0;
10209 (void) PosterizeImage(image,argument_list[0].integer_reference,
10210 argument_list[1].integer_reference ? RiemersmaDitherMethod :
10211 NoDitherMethod,exception);
10212 break;
10213 }
10214 case 89: /* Shadow */
10215 {
10216 if (attribute_flag[0] != 0)
10217 {
10218 flags=ParseGeometry(argument_list[0].string_reference,
10219 &geometry_info);
10220 if ((flags & SigmaValue) == 0)
10221 geometry_info.sigma=1.0;
10222 if ((flags & XiValue) == 0)
10223 geometry_info.xi=4.0;
10224 if ((flags & PsiValue) == 0)
10225 geometry_info.psi=4.0;
10226 }
10227 if (attribute_flag[1] != 0)
10228 geometry_info.rho=argument_list[1].real_reference;
10229 if (attribute_flag[2] != 0)
10230 geometry_info.sigma=argument_list[2].real_reference;
10231 if (attribute_flag[3] != 0)
10232 geometry_info.xi=argument_list[3].integer_reference;
10233 if (attribute_flag[4] != 0)
10234 geometry_info.psi=argument_list[4].integer_reference;
10235 image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10236 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10237 ceil(geometry_info.psi-0.5),exception);
10238 break;
10239 }
10240 case 90: /* Identify */
10241 {
10242 if (attribute_flag[0] == 0)
10243 argument_list[0].file_reference=(FILE *) NULL;
10244 if (attribute_flag[1] != 0)
10245 (void) SetImageArtifact(image,"identify:features",
10246 argument_list[1].string_reference);
10247 if ((attribute_flag[2] != 0) &&
10248 (argument_list[2].integer_reference != 0))
10249 (void) SetImageArtifact(image,"identify:unique","true");
10250 (void) IdentifyImage(image,argument_list[0].file_reference,
10251 MagickTrue,exception);
10252 break;
10253 }
10254 case 91: /* SepiaTone */
10255 {
10256 if (attribute_flag[0] == 0)
10257 argument_list[0].real_reference=80.0*QuantumRange/100.0;
10258 image=SepiaToneImage(image,argument_list[0].real_reference,
10259 exception);
10260 break;
10261 }
10262 case 92: /* SigmoidalContrast */
10263 {
10264 MagickBooleanType
10265 sharpen;
10266
10267 if (attribute_flag[0] != 0)
10268 {
10269 flags=ParseGeometry(argument_list[0].string_reference,
10270 &geometry_info);
10271 if ((flags & SigmaValue) == 0)
10272 geometry_info.sigma=QuantumRange/2.0;
10273 if ((flags & PercentValue) != 0)
10274 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10275 }
10276 if (attribute_flag[1] != 0)
10277 geometry_info.rho=argument_list[1].real_reference;
10278 if (attribute_flag[2] != 0)
10279 geometry_info.sigma=argument_list[2].real_reference;
10280 if (attribute_flag[3] != 0)
10281 channel=(ChannelType) argument_list[3].integer_reference;
10282 sharpen=MagickTrue;
10283 if (attribute_flag[4] != 0)
10284 sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10285 MagickFalse;
10286 channel_mask=SetImageChannelMask(image,channel);
10287 (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10288 geometry_info.sigma,exception);
10289 (void) SetImageChannelMask(image,channel_mask);
10290 break;
10291 }
10292 case 93: /* Extent */
10293 {
10294 if (attribute_flag[7] != 0)
10295 image->gravity=(GravityType) argument_list[7].integer_reference;
10296 if (attribute_flag[0] != 0)
10297 {
10298 int
10299 flags;
10300
10301 flags=ParseGravityGeometry(image,
10302 argument_list[0].string_reference,&geometry,exception);
10303 (void) flags;
10304 if (geometry.width == 0)
10305 geometry.width=image->columns;
10306 if (geometry.height == 0)
10307 geometry.height=image->rows;
10308 }
10309 if (attribute_flag[1] != 0)
10310 geometry.width=argument_list[1].integer_reference;
10311 if (attribute_flag[2] != 0)
10312 geometry.height=argument_list[2].integer_reference;
10313 if (attribute_flag[3] != 0)
10314 geometry.x=argument_list[3].integer_reference;
10315 if (attribute_flag[4] != 0)
10316 geometry.y=argument_list[4].integer_reference;
10317 if (attribute_flag[5] != 0)
10318 image->fuzz=StringToDoubleInterval(
10319 argument_list[5].string_reference,(double) QuantumRange+1.0);
10320 if (attribute_flag[6] != 0)
10321 (void) QueryColorCompliance(argument_list[6].string_reference,
10322 AllCompliance,&image->background_color,exception);
10323 image=ExtentImage(image,&geometry,exception);
10324 break;
10325 }
10326 case 94: /* Vignette */
10327 {
10328 if (attribute_flag[0] != 0)
10329 {
10330 flags=ParseGeometry(argument_list[0].string_reference,
10331 &geometry_info);
10332 if ((flags & SigmaValue) == 0)
10333 geometry_info.sigma=1.0;
10334 if ((flags & XiValue) == 0)
10335 geometry_info.xi=0.1*image->columns;
10336 if ((flags & PsiValue) == 0)
10337 geometry_info.psi=0.1*image->rows;
10338 }
10339 if (attribute_flag[1] != 0)
10340 geometry_info.rho=argument_list[1].real_reference;
10341 if (attribute_flag[2] != 0)
10342 geometry_info.sigma=argument_list[2].real_reference;
10343 if (attribute_flag[3] != 0)
10344 geometry_info.xi=argument_list[3].integer_reference;
10345 if (attribute_flag[4] != 0)
10346 geometry_info.psi=argument_list[4].integer_reference;
10347 if (attribute_flag[5] != 0)
10348 (void) QueryColorCompliance(argument_list[5].string_reference,
10349 AllCompliance,&image->background_color,exception);
10350 image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10351 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10352 ceil(geometry_info.psi-0.5),exception);
10353 break;
10354 }
10355 case 95: /* ContrastStretch */
10356 {
10357 double
10358 black_point,
10359 white_point;
10360
10361 black_point=0.0;
10362 white_point=(double) image->columns*image->rows;
10363 if (attribute_flag[0] != 0)
10364 {
10365 flags=ParseGeometry(argument_list[0].string_reference,
10366 &geometry_info);
10367 black_point=geometry_info.rho;
10368 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10369 black_point;
10370 if ((flags & PercentValue) != 0)
10371 {
10372 black_point*=(double) image->columns*image->rows/100.0;
10373 white_point*=(double) image->columns*image->rows/100.0;
10374 }
10375 white_point=(double) image->columns*image->rows-
10376 white_point;
10377 }
10378 if (attribute_flag[1] != 0)
10379 black_point=argument_list[1].real_reference;
10380 if (attribute_flag[2] != 0)
10381 white_point=argument_list[2].real_reference;
10382 if (attribute_flag[4] != 0)
10383 channel=(ChannelType) argument_list[4].integer_reference;
10384 channel_mask=SetImageChannelMask(image,channel);
10385 (void) ContrastStretchImage(image,black_point,white_point,exception);
10386 (void) SetImageChannelMask(image,channel_mask);
10387 break;
10388 }
10389 case 96: /* Sans0 */
10390 {
10391 break;
10392 }
10393 case 97: /* Sans1 */
10394 {
10395 break;
10396 }
10397 case 98: /* AdaptiveSharpen */
10398 {
10399 if (attribute_flag[0] != 0)
10400 {
10401 flags=ParseGeometry(argument_list[0].string_reference,
10402 &geometry_info);
10403 if ((flags & SigmaValue) == 0)
10404 geometry_info.sigma=1.0;
10405 if ((flags & XiValue) == 0)
10406 geometry_info.xi=0.0;
10407 }
10408 if (attribute_flag[1] != 0)
10409 geometry_info.rho=argument_list[1].real_reference;
10410 if (attribute_flag[2] != 0)
10411 geometry_info.sigma=argument_list[2].real_reference;
10412 if (attribute_flag[3] != 0)
10413 geometry_info.xi=argument_list[3].real_reference;
10414 if (attribute_flag[4] != 0)
10415 channel=(ChannelType) argument_list[4].integer_reference;
10416 channel_mask=SetImageChannelMask(image,channel);
10417 image=AdaptiveSharpenImage(image,geometry_info.rho,
10418 geometry_info.sigma,exception);
10419 if (image != (Image *) NULL)
10420 (void) SetImageChannelMask(image,channel_mask);
10421 break;
10422 }
10423 case 99: /* Transpose */
10424 {
10425 image=TransposeImage(image,exception);
10426 break;
10427 }
10428 case 100: /* Tranverse */
10429 {
10430 image=TransverseImage(image,exception);
10431 break;
10432 }
10433 case 101: /* AutoOrient */
10434 {
10435 image=AutoOrientImage(image,image->orientation,exception);
10436 break;
10437 }
10438 case 102: /* AdaptiveBlur */
10439 {
10440 if (attribute_flag[0] != 0)
10441 {
10442 flags=ParseGeometry(argument_list[0].string_reference,
10443 &geometry_info);
10444 if ((flags & SigmaValue) == 0)
10445 geometry_info.sigma=1.0;
10446 if ((flags & XiValue) == 0)
10447 geometry_info.xi=0.0;
10448 }
10449 if (attribute_flag[1] != 0)
10450 geometry_info.rho=argument_list[1].real_reference;
10451 if (attribute_flag[2] != 0)
10452 geometry_info.sigma=argument_list[2].real_reference;
10453 if (attribute_flag[3] != 0)
10454 channel=(ChannelType) argument_list[3].integer_reference;
10455 channel_mask=SetImageChannelMask(image,channel);
10456 image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10457 exception);
10458 if (image != (Image *) NULL)
10459 (void) SetImageChannelMask(image,channel_mask);
10460 break;
10461 }
10462 case 103: /* Sketch */
10463 {
10464 if (attribute_flag[0] != 0)
10465 {
10466 flags=ParseGeometry(argument_list[0].string_reference,
10467 &geometry_info);
10468 if ((flags & SigmaValue) == 0)
10469 geometry_info.sigma=1.0;
10470 if ((flags & XiValue) == 0)
10471 geometry_info.xi=1.0;
10472 }
10473 if (attribute_flag[1] != 0)
10474 geometry_info.rho=argument_list[1].real_reference;
10475 if (attribute_flag[2] != 0)
10476 geometry_info.sigma=argument_list[2].real_reference;
10477 if (attribute_flag[3] != 0)
10478 geometry_info.xi=argument_list[3].real_reference;
10479 image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10480 geometry_info.xi,exception);
10481 break;
10482 }
10483 case 104: /* UniqueColors */
10484 {
10485 image=UniqueImageColors(image,exception);
10486 break;
10487 }
10488 case 105: /* AdaptiveResize */
10489 {
10490 if (attribute_flag[0] != 0)
10491 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10492 &geometry,exception);
10493 if (attribute_flag[1] != 0)
10494 geometry.width=argument_list[1].integer_reference;
10495 if (attribute_flag[2] != 0)
10496 geometry.height=argument_list[2].integer_reference;
10497 if (attribute_flag[3] != 0)
Cristy8645e042016-02-03 16:35:29 -050010498 image->filter=(FilterType) argument_list[4].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010499 if (attribute_flag[4] != 0)
10500 SetImageArtifact(image,"filter:support",
10501 argument_list[4].string_reference);
10502 image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10503 exception);
10504 break;
10505 }
10506 case 106: /* ClipMask */
10507 {
10508 Image
10509 *mask_image;
10510
10511 if (attribute_flag[0] == 0)
10512 {
10513 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10514 PackageName);
10515 goto PerlException;
10516 }
10517 mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10518 exception);
cristy1f7ffb72015-07-29 11:07:03 +000010519 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010520 mask_image=DestroyImage(mask_image);
10521 break;
10522 }
10523 case 107: /* LinearStretch */
10524 {
10525 double
10526 black_point,
10527 white_point;
10528
10529 black_point=0.0;
10530 white_point=(double) image->columns*image->rows;
10531 if (attribute_flag[0] != 0)
10532 {
10533 flags=ParseGeometry(argument_list[0].string_reference,
10534 &geometry_info);
10535 if ((flags & SigmaValue) != 0)
10536 white_point=geometry_info.sigma;
10537 if ((flags & PercentValue) != 0)
10538 {
10539 black_point*=(double) image->columns*image->rows/100.0;
10540 white_point*=(double) image->columns*image->rows/100.0;
10541 }
10542 if ((flags & SigmaValue) == 0)
10543 white_point=(double) image->columns*image->rows-black_point;
10544 }
10545 if (attribute_flag[1] != 0)
10546 black_point=argument_list[1].real_reference;
10547 if (attribute_flag[2] != 0)
10548 white_point=argument_list[2].real_reference;
10549 (void) LinearStretchImage(image,black_point,white_point,exception);
10550 break;
10551 }
10552 case 108: /* ColorMatrix */
10553 {
10554 AV
10555 *av;
10556
10557 double
10558 *color_matrix;
10559
10560 KernelInfo
10561 *kernel_info;
10562
10563 size_t
10564 order;
10565
10566 if (attribute_flag[0] == 0)
10567 break;
10568 av=(AV *) argument_list[0].array_reference;
10569 order=(size_t) sqrt(av_len(av)+1);
10570 color_matrix=(double *) AcquireQuantumMemory(order,order*
10571 sizeof(*color_matrix));
10572 if (color_matrix == (double *) NULL)
10573 {
10574 ThrowPerlException(exception,ResourceLimitFatalError,
10575 "MemoryAllocationFailed",PackageName);
10576 goto PerlException;
10577 }
10578 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10579 color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10580 for ( ; j < (ssize_t) (order*order); j++)
10581 color_matrix[j]=0.0;
cristy2c57b742014-10-31 00:40:34 +000010582 kernel_info=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010583 if (kernel_info == (KernelInfo *) NULL)
10584 break;
10585 kernel_info->width=order;
10586 kernel_info->height=order;
10587 kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10588 order*sizeof(*kernel_info->values));
10589 if (kernel_info->values != (MagickRealType *) NULL)
10590 {
10591 for (i=0; i < (ssize_t) (order*order); i++)
10592 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10593 image=ColorMatrixImage(image,kernel_info,exception);
10594 }
10595 kernel_info=DestroyKernelInfo(kernel_info);
10596 color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10597 break;
10598 }
10599 case 109: /* Mask */
10600 {
10601 Image
10602 *mask_image;
10603
10604 if (attribute_flag[0] == 0)
10605 {
10606 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10607 PackageName);
10608 goto PerlException;
10609 }
10610 mask_image=CloneImage(argument_list[0].image_reference,0,0,
10611 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +000010612 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010613 mask_image=DestroyImage(mask_image);
10614 break;
10615 }
10616 case 110: /* Polaroid */
10617 {
10618 char
10619 *caption;
10620
10621 DrawInfo
10622 *draw_info;
10623
10624 double
10625 angle;
10626
10627 PixelInterpolateMethod
10628 method;
10629
10630 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10631 (DrawInfo *) NULL);
10632 caption=(char *) NULL;
10633 if (attribute_flag[0] != 0)
10634 caption=InterpretImageProperties(info ? info->image_info :
10635 (ImageInfo *) NULL,image,argument_list[0].string_reference,
10636 exception);
10637 angle=0.0;
10638 if (attribute_flag[1] != 0)
10639 angle=argument_list[1].real_reference;
10640 if (attribute_flag[2] != 0)
10641 (void) CloneString(&draw_info->font,
10642 argument_list[2].string_reference);
10643 if (attribute_flag[3] != 0)
10644 (void) QueryColorCompliance(argument_list[3].string_reference,
10645 AllCompliance,&draw_info->stroke,exception);
10646 if (attribute_flag[4] != 0)
10647 (void) QueryColorCompliance(argument_list[4].string_reference,
10648 AllCompliance,&draw_info->fill,exception);
10649 if (attribute_flag[5] != 0)
10650 draw_info->stroke_width=argument_list[5].real_reference;
10651 if (attribute_flag[6] != 0)
10652 draw_info->pointsize=argument_list[6].real_reference;
10653 if (attribute_flag[7] != 0)
10654 draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10655 if (attribute_flag[8] != 0)
10656 (void) QueryColorCompliance(argument_list[8].string_reference,
10657 AllCompliance,&image->background_color,exception);
10658 method=UndefinedInterpolatePixel;
10659 if (attribute_flag[9] != 0)
10660 method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10661 image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10662 draw_info=DestroyDrawInfo(draw_info);
10663 if (caption != (char *) NULL)
10664 caption=DestroyString(caption);
10665 break;
10666 }
10667 case 111: /* FloodfillPaint */
10668 {
10669 DrawInfo
10670 *draw_info;
10671
10672 MagickBooleanType
10673 invert;
10674
10675 PixelInfo
10676 target;
10677
10678 draw_info=CloneDrawInfo(info ? info->image_info :
10679 (ImageInfo *) NULL,(DrawInfo *) NULL);
10680 if (attribute_flag[0] != 0)
10681 flags=ParsePageGeometry(image,argument_list[0].string_reference,
10682 &geometry,exception);
10683 if (attribute_flag[1] != 0)
10684 geometry.x=argument_list[1].integer_reference;
10685 if (attribute_flag[2] != 0)
10686 geometry.y=argument_list[2].integer_reference;
10687 if (attribute_flag[3] != 0)
10688 (void) QueryColorCompliance(argument_list[3].string_reference,
10689 AllCompliance,&draw_info->fill,exception);
10690 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10691 geometry.x,geometry.y,&target,exception);
10692 if (attribute_flag[4] != 0)
10693 QueryColorCompliance(argument_list[4].string_reference,
10694 AllCompliance,&target,exception);
10695 if (attribute_flag[5] != 0)
10696 image->fuzz=StringToDoubleInterval(
10697 argument_list[5].string_reference,(double) QuantumRange+1.0);
10698 if (attribute_flag[6] != 0)
10699 channel=(ChannelType) argument_list[6].integer_reference;
10700 invert=MagickFalse;
10701 if (attribute_flag[7] != 0)
10702 invert=(MagickBooleanType) argument_list[7].integer_reference;
10703 channel_mask=SetImageChannelMask(image,channel);
10704 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10705 geometry.y,invert,exception);
10706 (void) SetImageChannelMask(image,channel_mask);
10707 draw_info=DestroyDrawInfo(draw_info);
10708 break;
10709 }
10710 case 112: /* Distort */
10711 {
10712 AV
10713 *av;
10714
10715 double
10716 *coordinates;
10717
Cristy8645e042016-02-03 16:35:29 -050010718 DistortMethod
cristy4a3ce0a2013-08-03 20:06:59 +000010719 method;
10720
10721 size_t
10722 number_coordinates;
10723
10724 VirtualPixelMethod
10725 virtual_pixel;
10726
10727 if (attribute_flag[0] == 0)
10728 break;
10729 method=UndefinedDistortion;
10730 if (attribute_flag[1] != 0)
Cristy8645e042016-02-03 16:35:29 -050010731 method=(DistortMethod) argument_list[1].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010732 av=(AV *) argument_list[0].array_reference;
10733 number_coordinates=(size_t) av_len(av)+1;
10734 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10735 sizeof(*coordinates));
10736 if (coordinates == (double *) NULL)
10737 {
10738 ThrowPerlException(exception,ResourceLimitFatalError,
10739 "MemoryAllocationFailed",PackageName);
10740 goto PerlException;
10741 }
10742 for (j=0; j < (ssize_t) number_coordinates; j++)
10743 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10744 virtual_pixel=UndefinedVirtualPixelMethod;
10745 if (attribute_flag[2] != 0)
10746 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10747 argument_list[2].integer_reference,exception);
10748 image=DistortImage(image,method,number_coordinates,coordinates,
10749 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10750 exception);
10751 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10752 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10753 exception);
10754 coordinates=(double *) RelinquishMagickMemory(coordinates);
10755 break;
10756 }
10757 case 113: /* Clut */
10758 {
10759 PixelInterpolateMethod
10760 method;
10761
10762 if (attribute_flag[0] == 0)
10763 {
10764 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10765 PackageName);
10766 goto PerlException;
10767 }
10768 method=UndefinedInterpolatePixel;
10769 if (attribute_flag[1] != 0)
10770 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10771 if (attribute_flag[2] != 0)
10772 channel=(ChannelType) argument_list[2].integer_reference;
10773 channel_mask=SetImageChannelMask(image,channel);
10774 (void) ClutImage(image,argument_list[0].image_reference,method,
10775 exception);
10776 (void) SetImageChannelMask(image,channel_mask);
10777 break;
10778 }
10779 case 114: /* LiquidRescale */
10780 {
10781 if (attribute_flag[0] != 0)
10782 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10783 &geometry,exception);
10784 if (attribute_flag[1] != 0)
10785 geometry.width=argument_list[1].integer_reference;
10786 if (attribute_flag[2] != 0)
10787 geometry.height=argument_list[2].integer_reference;
10788 if (attribute_flag[3] == 0)
10789 argument_list[3].real_reference=1.0;
10790 if (attribute_flag[4] == 0)
10791 argument_list[4].real_reference=0.0;
10792 image=LiquidRescaleImage(image,geometry.width,geometry.height,
10793 argument_list[3].real_reference,argument_list[4].real_reference,
10794 exception);
10795 break;
10796 }
10797 case 115: /* EncipherImage */
10798 {
10799 (void) EncipherImage(image,argument_list[0].string_reference,
10800 exception);
10801 break;
10802 }
10803 case 116: /* DecipherImage */
10804 {
10805 (void) DecipherImage(image,argument_list[0].string_reference,
10806 exception);
10807 break;
10808 }
10809 case 117: /* Deskew */
10810 {
10811 geometry_info.rho=QuantumRange/2.0;
10812 if (attribute_flag[0] != 0)
10813 flags=ParseGeometry(argument_list[0].string_reference,
10814 &geometry_info);
10815 if (attribute_flag[1] != 0)
10816 geometry_info.rho=StringToDoubleInterval(
10817 argument_list[1].string_reference,(double) QuantumRange+1.0);
10818 image=DeskewImage(image,geometry_info.rho,exception);
10819 break;
10820 }
10821 case 118: /* Remap */
10822 {
10823 QuantizeInfo
10824 *quantize_info;
10825
10826 if (attribute_flag[0] == 0)
10827 {
10828 ThrowPerlException(exception,OptionError,"RemapImageRequired",
10829 PackageName);
10830 goto PerlException;
10831 }
10832 quantize_info=AcquireQuantizeInfo(info->image_info);
10833 if (attribute_flag[1] != 0)
10834 quantize_info->dither_method=(DitherMethod)
10835 argument_list[1].integer_reference;
10836 (void) RemapImages(quantize_info,image,
10837 argument_list[0].image_reference,exception);
10838 quantize_info=DestroyQuantizeInfo(quantize_info);
10839 break;
10840 }
10841 case 119: /* SparseColor */
10842 {
10843 AV
10844 *av;
10845
10846 double
10847 *coordinates;
10848
10849 SparseColorMethod
10850 method;
10851
10852 size_t
10853 number_coordinates;
10854
10855 VirtualPixelMethod
10856 virtual_pixel;
10857
10858 if (attribute_flag[0] == 0)
10859 break;
10860 method=UndefinedColorInterpolate;
10861 if (attribute_flag[1] != 0)
10862 method=(SparseColorMethod) argument_list[1].integer_reference;
10863 av=(AV *) argument_list[0].array_reference;
10864 number_coordinates=(size_t) av_len(av)+1;
10865 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10866 sizeof(*coordinates));
10867 if (coordinates == (double *) NULL)
10868 {
10869 ThrowPerlException(exception,ResourceLimitFatalError,
10870 "MemoryAllocationFailed",PackageName);
10871 goto PerlException;
10872 }
10873 for (j=0; j < (ssize_t) number_coordinates; j++)
10874 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10875 virtual_pixel=UndefinedVirtualPixelMethod;
10876 if (attribute_flag[2] != 0)
10877 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10878 argument_list[2].integer_reference,exception);
10879 if (attribute_flag[3] != 0)
10880 channel=(ChannelType) argument_list[3].integer_reference;
10881 channel_mask=SetImageChannelMask(image,channel);
10882 image=SparseColorImage(image,method,number_coordinates,coordinates,
10883 exception);
10884 if (image != (Image *) NULL)
10885 (void) SetImageChannelMask(image,channel_mask);
10886 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10887 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10888 exception);
10889 coordinates=(double *) RelinquishMagickMemory(coordinates);
10890 break;
10891 }
10892 case 120: /* Function */
10893 {
10894 AV
10895 *av;
10896
10897 double
10898 *parameters;
10899
10900 MagickFunction
10901 function;
10902
10903 size_t
10904 number_parameters;
10905
10906 VirtualPixelMethod
10907 virtual_pixel;
10908
10909 if (attribute_flag[0] == 0)
10910 break;
10911 function=UndefinedFunction;
10912 if (attribute_flag[1] != 0)
10913 function=(MagickFunction) argument_list[1].integer_reference;
10914 av=(AV *) argument_list[0].array_reference;
10915 number_parameters=(size_t) av_len(av)+1;
10916 parameters=(double *) AcquireQuantumMemory(number_parameters,
10917 sizeof(*parameters));
10918 if (parameters == (double *) NULL)
10919 {
10920 ThrowPerlException(exception,ResourceLimitFatalError,
10921 "MemoryAllocationFailed",PackageName);
10922 goto PerlException;
10923 }
10924 for (j=0; j < (ssize_t) number_parameters; j++)
10925 parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10926 virtual_pixel=UndefinedVirtualPixelMethod;
10927 if (attribute_flag[2] != 0)
10928 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10929 argument_list[2].integer_reference,exception);
10930 (void) FunctionImage(image,function,number_parameters,parameters,
10931 exception);
10932 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10933 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10934 exception);
10935 parameters=(double *) RelinquishMagickMemory(parameters);
10936 break;
10937 }
10938 case 121: /* SelectiveBlur */
10939 {
10940 if (attribute_flag[0] != 0)
10941 {
10942 flags=ParseGeometry(argument_list[0].string_reference,
10943 &geometry_info);
10944 if ((flags & SigmaValue) == 0)
10945 geometry_info.sigma=1.0;
10946 if ((flags & PercentValue) != 0)
10947 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10948 }
10949 if (attribute_flag[1] != 0)
10950 geometry_info.rho=argument_list[1].real_reference;
10951 if (attribute_flag[2] != 0)
10952 geometry_info.sigma=argument_list[2].real_reference;
10953 if (attribute_flag[3] != 0)
10954 geometry_info.xi=argument_list[3].integer_reference;;
10955 if (attribute_flag[5] != 0)
10956 channel=(ChannelType) argument_list[5].integer_reference;
10957 channel_mask=SetImageChannelMask(image,channel);
10958 image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10959 geometry_info.xi,exception);
10960 if (image != (Image *) NULL)
10961 (void) SetImageChannelMask(image,channel_mask);
10962 break;
10963 }
10964 case 122: /* HaldClut */
10965 {
10966 if (attribute_flag[0] == 0)
10967 {
10968 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10969 PackageName);
10970 goto PerlException;
10971 }
10972 if (attribute_flag[1] != 0)
10973 channel=(ChannelType) argument_list[1].integer_reference;
10974 channel_mask=SetImageChannelMask(image,channel);
10975 (void) HaldClutImage(image,argument_list[0].image_reference,
10976 exception);
10977 (void) SetImageChannelMask(image,channel_mask);
10978 break;
10979 }
10980 case 123: /* BlueShift */
10981 {
10982 if (attribute_flag[0] != 0)
10983 (void) ParseGeometry(argument_list[0].string_reference,
10984 &geometry_info);
10985 image=BlueShiftImage(image,geometry_info.rho,exception);
10986 break;
10987 }
10988 case 124: /* ForwardFourierTransformImage */
10989 {
10990 image=ForwardFourierTransformImage(image,
10991 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10992 exception);
10993 break;
10994 }
10995 case 125: /* InverseFourierTransformImage */
10996 {
10997 image=InverseFourierTransformImage(image,image->next,
10998 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10999 exception);
11000 break;
11001 }
11002 case 126: /* ColorDecisionList */
11003 {
11004 if (attribute_flag[0] == 0)
11005 argument_list[0].string_reference=(char *) NULL;
11006 (void) ColorDecisionListImage(image,
11007 argument_list[0].string_reference,exception);
11008 break;
11009 }
11010 case 127: /* AutoGamma */
11011 {
11012 if (attribute_flag[0] != 0)
11013 channel=(ChannelType) argument_list[0].integer_reference;
11014 channel_mask=SetImageChannelMask(image,channel);
11015 (void) AutoGammaImage(image,exception);
11016 (void) SetImageChannelMask(image,channel_mask);
11017 break;
11018 }
11019 case 128: /* AutoLevel */
11020 {
11021 if (attribute_flag[0] != 0)
11022 channel=(ChannelType) argument_list[0].integer_reference;
11023 channel_mask=SetImageChannelMask(image,channel);
11024 (void) AutoLevelImage(image,exception);
11025 (void) SetImageChannelMask(image,channel_mask);
11026 break;
11027 }
11028 case 129: /* LevelColors */
11029 {
11030 PixelInfo
11031 black_point,
11032 white_point;
11033
11034 (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
11035 exception);
11036 (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
11037 exception);
11038 if (attribute_flag[1] != 0)
11039 (void) QueryColorCompliance(
11040 argument_list[1].string_reference,AllCompliance,&black_point,
11041 exception);
11042 if (attribute_flag[2] != 0)
11043 (void) QueryColorCompliance(
11044 argument_list[2].string_reference,AllCompliance,&white_point,
11045 exception);
11046 if (attribute_flag[3] != 0)
11047 channel=(ChannelType) argument_list[3].integer_reference;
11048 channel_mask=SetImageChannelMask(image,channel);
11049 (void) LevelImageColors(image,&black_point,&white_point,
11050 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11051 exception);
11052 (void) SetImageChannelMask(image,channel_mask);
11053 break;
11054 }
11055 case 130: /* Clamp */
11056 {
11057 if (attribute_flag[0] != 0)
11058 channel=(ChannelType) argument_list[0].integer_reference;
11059 channel_mask=SetImageChannelMask(image,channel);
11060 (void) ClampImage(image,exception);
11061 (void) SetImageChannelMask(image,channel_mask);
11062 break;
11063 }
11064 case 131: /* BrightnessContrast */
11065 {
11066 double
11067 brightness,
11068 contrast;
11069
11070 brightness=0.0;
11071 contrast=0.0;
11072 if (attribute_flag[0] != 0)
11073 {
11074 flags=ParseGeometry(argument_list[0].string_reference,
11075 &geometry_info);
11076 brightness=geometry_info.rho;
11077 if ((flags & SigmaValue) == 0)
11078 contrast=geometry_info.sigma;
11079 }
11080 if (attribute_flag[1] != 0)
11081 brightness=argument_list[1].real_reference;
11082 if (attribute_flag[2] != 0)
11083 contrast=argument_list[2].real_reference;
11084 if (attribute_flag[4] != 0)
11085 channel=(ChannelType) argument_list[4].integer_reference;
11086 channel_mask=SetImageChannelMask(image,channel);
11087 (void) BrightnessContrastImage(image,brightness,contrast,exception);
11088 (void) SetImageChannelMask(image,channel_mask);
11089 break;
11090 }
11091 case 132: /* Morphology */
11092 {
11093 KernelInfo
11094 *kernel;
11095
11096 MorphologyMethod
11097 method;
11098
11099 ssize_t
11100 iterations;
11101
11102 if (attribute_flag[0] == 0)
11103 break;
cristy2c57b742014-10-31 00:40:34 +000011104 kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011105 if (kernel == (KernelInfo *) NULL)
11106 break;
11107 if (attribute_flag[1] != 0)
11108 channel=(ChannelType) argument_list[1].integer_reference;
11109 method=UndefinedMorphology;
11110 if (attribute_flag[2] != 0)
11111 method=argument_list[2].integer_reference;
11112 iterations=1;
11113 if (attribute_flag[3] != 0)
11114 iterations=argument_list[3].integer_reference;
11115 channel_mask=SetImageChannelMask(image,channel);
11116 image=MorphologyImage(image,method,iterations,kernel,exception);
11117 if (image != (Image *) NULL)
11118 (void) SetImageChannelMask(image,channel_mask);
11119 kernel=DestroyKernelInfo(kernel);
11120 break;
11121 }
11122 case 133: /* Mode */
11123 {
11124 if (attribute_flag[0] != 0)
11125 {
11126 flags=ParseGeometry(argument_list[0].string_reference,
11127 &geometry_info);
11128 if ((flags & SigmaValue) == 0)
11129 geometry_info.sigma=1.0;
11130 }
11131 if (attribute_flag[1] != 0)
11132 geometry_info.rho=argument_list[1].real_reference;
11133 if (attribute_flag[2] != 0)
11134 geometry_info.sigma=argument_list[2].real_reference;
11135 if (attribute_flag[3] != 0)
11136 channel=(ChannelType) argument_list[3].integer_reference;
11137 channel_mask=SetImageChannelMask(image,channel);
11138 image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11139 (size_t) geometry_info.sigma,exception);
11140 if (image != (Image *) NULL)
11141 (void) SetImageChannelMask(image,channel_mask);
11142 break;
11143 }
11144 case 134: /* Statistic */
11145 {
11146 StatisticType
11147 statistic;
11148
11149 statistic=UndefinedStatistic;
11150 if (attribute_flag[0] != 0)
11151 {
11152 flags=ParseGeometry(argument_list[0].string_reference,
11153 &geometry_info);
11154 if ((flags & SigmaValue) == 0)
11155 geometry_info.sigma=1.0;
11156 }
11157 if (attribute_flag[1] != 0)
11158 geometry_info.rho=argument_list[1].real_reference;
11159 if (attribute_flag[2] != 0)
11160 geometry_info.sigma=argument_list[2].real_reference;
11161 if (attribute_flag[3] != 0)
11162 channel=(ChannelType) argument_list[3].integer_reference;
11163 if (attribute_flag[4] != 0)
11164 statistic=(StatisticType) argument_list[4].integer_reference;
11165 channel_mask=SetImageChannelMask(image,channel);
11166 image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11167 (size_t) geometry_info.sigma,exception);
11168 if (image != (Image *) NULL)
11169 (void) SetImageChannelMask(image,channel_mask);
11170 break;
11171 }
11172 case 135: /* Perceptible */
11173 {
11174 double
11175 epsilon;
11176
11177 epsilon=MagickEpsilon;
11178 if (attribute_flag[0] != 0)
11179 epsilon=argument_list[0].real_reference;
11180 if (attribute_flag[1] != 0)
11181 channel=(ChannelType) argument_list[1].integer_reference;
11182 channel_mask=SetImageChannelMask(image,channel);
11183 (void) PerceptibleImage(image,epsilon,exception);
11184 (void) SetImageChannelMask(image,channel_mask);
11185 break;
11186 }
11187 case 136: /* Poly */
11188 {
11189 AV
11190 *av;
11191
11192 double
11193 *terms;
11194
11195 size_t
11196 number_terms;
11197
11198 if (attribute_flag[0] == 0)
11199 break;
11200 if (attribute_flag[1] != 0)
11201 channel=(ChannelType) argument_list[1].integer_reference;
11202 av=(AV *) argument_list[0].array_reference;
11203 number_terms=(size_t) av_len(av);
11204 terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11205 if (terms == (double *) NULL)
11206 {
11207 ThrowPerlException(exception,ResourceLimitFatalError,
11208 "MemoryAllocationFailed",PackageName);
11209 goto PerlException;
11210 }
11211 for (j=0; j < av_len(av); j++)
11212 terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11213 image=PolynomialImage(image,number_terms >> 1,terms,exception);
11214 terms=(double *) RelinquishMagickMemory(terms);
11215 break;
11216 }
11217 case 137: /* Grayscale */
11218 {
11219 PixelIntensityMethod
11220 method;
11221
11222 method=UndefinedPixelIntensityMethod;
11223 if (attribute_flag[0] != 0)
11224 method=(PixelIntensityMethod) argument_list[0].integer_reference;
11225 (void) GrayscaleImage(image,method,exception);
11226 break;
11227 }
cristy4ceadb82014-03-29 15:30:43 +000011228 case 138: /* Canny */
11229 {
11230 if (attribute_flag[0] != 0)
11231 {
11232 flags=ParseGeometry(argument_list[0].string_reference,
11233 &geometry_info);
11234 if ((flags & SigmaValue) == 0)
11235 geometry_info.sigma=1.0;
11236 if ((flags & XiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011237 geometry_info.xi=0.10;
cristy4ceadb82014-03-29 15:30:43 +000011238 if ((flags & PsiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011239 geometry_info.psi=0.30;
cristy41814f22014-04-09 20:53:11 +000011240 if ((flags & PercentValue) != 0)
11241 {
11242 geometry_info.xi/=100.0;
11243 geometry_info.psi/=100.0;
11244 }
cristy4ceadb82014-03-29 15:30:43 +000011245 }
11246 if (attribute_flag[1] != 0)
11247 geometry_info.rho=argument_list[1].real_reference;
11248 if (attribute_flag[2] != 0)
11249 geometry_info.sigma=argument_list[2].real_reference;
11250 if (attribute_flag[3] != 0)
11251 geometry_info.xi=argument_list[3].real_reference;
11252 if (attribute_flag[4] != 0)
11253 geometry_info.psi=argument_list[4].real_reference;
11254 if (attribute_flag[5] != 0)
11255 channel=(ChannelType) argument_list[5].integer_reference;
11256 channel_mask=SetImageChannelMask(image,channel);
11257 image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11258 geometry_info.xi,geometry_info.psi,exception);
11259 if (image != (Image *) NULL)
11260 (void) SetImageChannelMask(image,channel_mask);
11261 break;
11262 }
cristy2fc10e52014-04-26 14:13:53 +000011263 case 139: /* HoughLine */
cristy4e215022014-04-19 18:02:35 +000011264 {
11265 if (attribute_flag[0] != 0)
11266 {
11267 flags=ParseGeometry(argument_list[0].string_reference,
11268 &geometry_info);
11269 if ((flags & SigmaValue) == 0)
11270 geometry_info.sigma=geometry_info.rho;
cristy20f90422014-04-27 13:34:21 +000011271 if ((flags & XiValue) == 0)
11272 geometry_info.xi=40;
cristy4e215022014-04-19 18:02:35 +000011273 }
11274 if (attribute_flag[1] != 0)
11275 geometry_info.rho=(double) argument_list[1].integer_reference;
11276 if (attribute_flag[2] != 0)
11277 geometry_info.sigma=(double) argument_list[2].integer_reference;
11278 if (attribute_flag[3] != 0)
11279 geometry_info.xi=(double) argument_list[3].integer_reference;
cristy2fc10e52014-04-26 14:13:53 +000011280 image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11281 geometry_info.sigma,(size_t) geometry_info.xi,exception);
11282 break;
11283 }
11284 case 140: /* MeanShift */
11285 {
11286 if (attribute_flag[0] != 0)
11287 {
11288 flags=ParseGeometry(argument_list[0].string_reference,
11289 &geometry_info);
11290 if ((flags & SigmaValue) == 0)
11291 geometry_info.sigma=geometry_info.rho;
cristy2fc10e52014-04-26 14:13:53 +000011292 if ((flags & XiValue) == 0)
cristy1309fc32014-04-26 18:48:37 +000011293 geometry_info.xi=0.10*QuantumRange;
11294 if ((flags & PercentValue) != 0)
11295 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
cristy2fc10e52014-04-26 14:13:53 +000011296 }
11297 if (attribute_flag[1] != 0)
11298 geometry_info.rho=(double) argument_list[1].integer_reference;
11299 if (attribute_flag[2] != 0)
11300 geometry_info.sigma=(double) argument_list[2].integer_reference;
11301 if (attribute_flag[3] != 0)
11302 geometry_info.xi=(double) argument_list[3].integer_reference;
11303 image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
cristy1309fc32014-04-26 18:48:37 +000011304 geometry_info.sigma,geometry_info.xi,exception);
cristy4e215022014-04-19 18:02:35 +000011305 break;
11306 }
cristy3b207f82014-09-27 14:21:20 +000011307 case 141: /* Kuwahara */
11308 {
11309 if (attribute_flag[0] != 0)
11310 {
11311 flags=ParseGeometry(argument_list[0].string_reference,
11312 &geometry_info);
11313 if ((flags & SigmaValue) == 0)
cristy3a9903c2014-10-04 01:14:20 +000011314 geometry_info.sigma=geometry_info.rho-0.5;
cristy3b207f82014-09-27 14:21:20 +000011315 }
11316 if (attribute_flag[1] != 0)
11317 geometry_info.rho=argument_list[1].real_reference;
11318 if (attribute_flag[2] != 0)
11319 geometry_info.sigma=argument_list[2].real_reference;
11320 if (attribute_flag[3] != 0)
11321 channel=(ChannelType) argument_list[3].integer_reference;
11322 channel_mask=SetImageChannelMask(image,channel);
11323 image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11324 exception);
11325 if (image != (Image *) NULL)
11326 (void) SetImageChannelMask(image,channel_mask);
11327 break;
11328 }
Cristy0f5df812017-07-04 18:30:05 -040011329 case 142: /* ConnectedComponents */
cristy6e0b3bc2014-10-19 17:51:42 +000011330 {
11331 size_t
11332 connectivity;
11333
11334 connectivity=4;
11335 if (attribute_flag[0] != 0)
11336 connectivity=argument_list[0].integer_reference;
Cristy2ca0e9a2016-01-01 08:36:14 -050011337 image=ConnectedComponentsImage(image,connectivity,
Cristy4f83be82015-12-31 08:40:53 -050011338 (CCObjectInfo **) NULL,exception);
cristy6e0b3bc2014-10-19 17:51:42 +000011339 break;
11340 }
cristy0b94b392015-06-22 18:56:37 +000011341 case 143: /* Copy */
11342 {
11343 Image
11344 *source_image;
11345
11346 OffsetInfo
11347 offset;
11348
cristy2ffdb092015-06-25 14:31:20 +000011349 RectangleInfo
11350 offset_geometry;
11351
cristyf3a724a2015-06-25 13:02:53 +000011352 source_image=image;
cristy0b94b392015-06-22 18:56:37 +000011353 if (attribute_flag[0] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011354 source_image=argument_list[0].image_reference;
cristy2ffdb092015-06-25 14:31:20 +000011355 SetGeometry(source_image,&geometry);
cristy0b94b392015-06-22 18:56:37 +000011356 if (attribute_flag[1] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011357 flags=ParseGravityGeometry(source_image,
11358 argument_list[1].string_reference,&geometry,exception);
cristy0b94b392015-06-22 18:56:37 +000011359 if (attribute_flag[2] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011360 geometry.width=argument_list[2].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011361 if (attribute_flag[3] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011362 geometry.height=argument_list[3].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011363 if (attribute_flag[4] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011364 geometry.x=argument_list[4].integer_reference;
11365 if (attribute_flag[5] != 0)
11366 geometry.y=argument_list[5].integer_reference;
11367 if (attribute_flag[6] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011368 image->gravity=(GravityType) argument_list[6].integer_reference;
dirk169d1642015-06-27 19:51:08 +000011369 SetGeometry(image,&offset_geometry);
cristyf3a724a2015-06-25 13:02:53 +000011370 if (attribute_flag[7] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011371 flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11372 &offset_geometry,exception);
11373 offset.x=offset_geometry.x;
11374 offset.y=offset_geometry.y;
cristyf3a724a2015-06-25 13:02:53 +000011375 if (attribute_flag[8] != 0)
11376 offset.x=argument_list[8].integer_reference;
11377 if (attribute_flag[9] != 0)
11378 offset.y=argument_list[9].integer_reference;
cristycd6d5182015-06-23 17:22:15 +000011379 (void) CopyImagePixels(image,source_image,&geometry,&offset,
11380 exception);
cristy0b94b392015-06-22 18:56:37 +000011381 break;
11382 }
Cristy5488c982016-02-13 14:07:50 -050011383 case 144: /* Color */
11384 {
11385 PixelInfo
11386 color;
11387
Cristyf20e3562016-02-14 09:08:15 -050011388 (void) QueryColorCompliance("none",AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011389 if (attribute_flag[0] != 0)
Cristyf20e3562016-02-14 09:08:15 -050011390 (void) QueryColorCompliance(argument_list[0].string_reference,
11391 AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011392 (void) SetImageColor(image,&color,exception);
11393 break;
11394 }
Cristy2d830ed2016-02-21 10:54:16 -050011395 case 145: /* WaveletDenoise */
11396 {
Cristyc1759412016-02-27 12:17:58 -050011397 if (attribute_flag[0] != 0)
Cristyee21f7f2016-02-27 15:56:49 -050011398 {
11399 flags=ParseGeometry(argument_list[0].string_reference,
11400 &geometry_info);
11401 if ((flags & PercentValue) != 0)
Cristy23446632016-02-29 09:36:34 -050011402 {
11403 geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11404 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11405 }
Cristyee21f7f2016-02-27 15:56:49 -050011406 if ((flags & SigmaValue) == 0)
11407 geometry_info.sigma=0.0;
11408 }
Cristyc1759412016-02-27 12:17:58 -050011409 if (attribute_flag[1] != 0)
11410 geometry_info.rho=argument_list[1].real_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011411 if (attribute_flag[2] != 0)
Cristyc1759412016-02-27 12:17:58 -050011412 geometry_info.sigma=argument_list[2].real_reference;
11413 if (attribute_flag[3] != 0)
11414 channel=(ChannelType) argument_list[3].integer_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011415 channel_mask=SetImageChannelMask(image,channel);
Cristyc1759412016-02-27 12:17:58 -050011416 image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11417 exception);
Cristy2d830ed2016-02-21 10:54:16 -050011418 if (image != (Image *) NULL)
11419 (void) SetImageChannelMask(image,channel_mask);
11420 break;
11421 }
Cristy99a57162016-12-05 11:47:57 -050011422 case 146: /* Colorspace */
11423 {
11424 ColorspaceType
11425 colorspace;
11426
11427 colorspace=sRGBColorspace;
11428 if (attribute_flag[0] != 0)
11429 colorspace=(ColorspaceType) argument_list[0].integer_reference;
11430 (void) TransformImageColorspace(image,colorspace,exception);
11431 break;
11432 }
Cristy53353872017-07-02 12:24:24 -040011433 case 147: /* AutoThreshold */
11434 {
11435 AutoThresholdMethod
11436 method;
11437
11438 method=UndefinedThresholdMethod;
11439 if (attribute_flag[0] != 0)
Cristyb63e7752017-07-02 13:22:01 -040011440 method=(AutoThresholdMethod) argument_list[0].integer_reference;
Cristy53353872017-07-02 12:24:24 -040011441 (void) AutoThresholdImage(image,method,exception);
11442 break;
11443 }
Cristy532b3382018-08-05 17:56:56 -040011444 case 148: /* RangeThreshold */
11445 {
11446 if (attribute_flag[0] != 0)
11447 {
11448 flags=ParseGeometry(argument_list[0].string_reference,
11449 &geometry_info);
11450 if ((flags & SigmaValue) == 0)
11451 geometry_info.sigma=geometry_info.rho;
11452 if ((flags & XiValue) == 0)
11453 geometry_info.xi=geometry_info.sigma;
11454 if ((flags & PsiValue) == 0)
11455 geometry_info.psi=geometry_info.xi;
11456 }
11457 if (attribute_flag[1] != 0)
11458 geometry_info.rho=argument_list[1].real_reference;
11459 if (attribute_flag[2] != 0)
11460 geometry_info.sigma=argument_list[2].real_reference;
11461 if (attribute_flag[3] != 0)
11462 geometry_info.xi=argument_list[3].real_reference;
11463 if (attribute_flag[4] != 0)
11464 geometry_info.psi=argument_list[4].real_reference;
11465 if (attribute_flag[5] != 0)
11466 channel=(ChannelType) argument_list[5].integer_reference;
11467 channel_mask=SetImageChannelMask(image,channel);
Cristy9b220db2018-08-05 18:02:28 -040011468 (void) RangeThresholdImage(image,geometry_info.rho,
11469 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
Cristy532b3382018-08-05 17:56:56 -040011470 if (image != (Image *) NULL)
11471 (void) SetImageChannelMask(image,channel_mask);
11472 break;
11473 }
cristy4a3ce0a2013-08-03 20:06:59 +000011474 }
11475 if (next != (Image *) NULL)
11476 (void) CatchImageException(next);
Cristy7e567962018-02-03 12:42:20 -050011477 if ((region_info.width*region_info.height) != 0)
11478 (void) SetImageRegionMask(image,WritePixelMask,
11479 (const RectangleInfo *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011480 if (image != (Image *) NULL)
11481 {
11482 number_images++;
11483 if (next && (next != image))
11484 {
11485 image->next=next->next;
11486 if (image->next != (Image *) NULL)
11487 image->next->previous=image;
11488 DeleteImageFromRegistry(*pv,next);
11489 }
11490 sv_setiv(*pv,PTR2IV(image));
11491 next=image;
11492 }
11493 if (*pv)
11494 pv++;
11495 }
11496
11497 PerlException:
11498 if (reference_vector)
11499 reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11500 InheritPerlException(exception,perl_exception);
11501 exception=DestroyExceptionInfo(exception);
11502 sv_setiv(perl_exception,(IV) number_images);
11503 SvPOK_on(perl_exception);
11504 ST(0)=sv_2mortal(perl_exception);
11505 XSRETURN(1);
11506 }
11507
11508#
11509###############################################################################
11510# #
11511# #
11512# #
11513# M o n t a g e #
11514# #
11515# #
11516# #
11517###############################################################################
11518#
11519#
11520void
11521Montage(ref,...)
11522 Image::Magick ref=NO_INIT
11523 ALIAS:
11524 MontageImage = 1
11525 montage = 2
11526 montageimage = 3
11527 PPCODE:
11528 {
11529 AV
11530 *av;
11531
11532 char
11533 *attribute;
11534
11535 ExceptionInfo
11536 *exception;
11537
11538 HV
11539 *hv;
11540
11541 Image
11542 *image,
11543 *next;
11544
11545 PixelInfo
11546 transparent_color;
11547
11548 MontageInfo
11549 *montage_info;
11550
11551 register ssize_t
11552 i;
11553
11554 ssize_t
11555 sp;
11556
11557 struct PackageInfo
11558 *info;
11559
11560 SV
11561 *av_reference,
11562 *perl_exception,
11563 *reference,
11564 *rv,
11565 *sv;
11566
11567 PERL_UNUSED_VAR(ref);
11568 PERL_UNUSED_VAR(ix);
11569 exception=AcquireExceptionInfo();
11570 perl_exception=newSVpv("",0);
11571 sv=NULL;
11572 attribute=NULL;
11573 if (sv_isobject(ST(0)) == 0)
11574 {
11575 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11576 PackageName);
11577 goto PerlException;
11578 }
11579 reference=SvRV(ST(0));
11580 hv=SvSTASH(reference);
11581 av=newAV();
11582 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11583 SvREFCNT_dec(av);
11584 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11585 if (image == (Image *) NULL)
11586 {
11587 ThrowPerlException(exception,OptionError,"NoImagesDefined",
11588 PackageName);
11589 goto PerlException;
11590 }
11591 /*
11592 Get options.
11593 */
11594 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11595 montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11596 (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11597 exception);
11598 for (i=2; i < items; i+=2)
11599 {
11600 attribute=(char *) SvPV(ST(i-1),na);
11601 switch (*attribute)
11602 {
11603 case 'B':
11604 case 'b':
11605 {
11606 if (LocaleCompare(attribute,"background") == 0)
11607 {
11608 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11609 &montage_info->background_color,exception);
11610 for (next=image; next; next=next->next)
11611 next->background_color=montage_info->background_color;
11612 break;
11613 }
11614 if (LocaleCompare(attribute,"border") == 0)
11615 {
11616 montage_info->border_width=SvIV(ST(i));
11617 break;
11618 }
11619 if (LocaleCompare(attribute,"bordercolor") == 0)
11620 {
11621 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11622 &montage_info->border_color,exception);
11623 for (next=image; next; next=next->next)
11624 next->border_color=montage_info->border_color;
11625 break;
11626 }
11627 if (LocaleCompare(attribute,"borderwidth") == 0)
11628 {
11629 montage_info->border_width=SvIV(ST(i));
11630 break;
11631 }
11632 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11633 attribute);
11634 break;
11635 }
11636 case 'C':
11637 case 'c':
11638 {
11639 if (LocaleCompare(attribute,"compose") == 0)
11640 {
11641 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11642 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11643 if (sp < 0)
11644 {
11645 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11646 SvPV(ST(i),na));
11647 break;
11648 }
11649 for (next=image; next; next=next->next)
11650 next->compose=(CompositeOperator) sp;
11651 break;
11652 }
11653 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11654 attribute);
11655 break;
11656 }
11657 case 'F':
11658 case 'f':
11659 {
11660 if (LocaleCompare(attribute,"fill") == 0)
11661 {
11662 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11663 &montage_info->fill,exception);
11664 break;
11665 }
11666 if (LocaleCompare(attribute,"font") == 0)
11667 {
11668 (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11669 break;
11670 }
11671 if (LocaleCompare(attribute,"frame") == 0)
11672 {
11673 char
11674 *p;
11675
11676 p=SvPV(ST(i),na);
11677 if (IsGeometry(p) == MagickFalse)
11678 {
11679 ThrowPerlException(exception,OptionError,"MissingGeometry",
11680 p);
11681 break;
11682 }
11683 (void) CloneString(&montage_info->frame,p);
11684 if (*p == '\0')
11685 montage_info->frame=(char *) NULL;
11686 break;
11687 }
11688 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11689 attribute);
11690 break;
11691 }
11692 case 'G':
11693 case 'g':
11694 {
11695 if (LocaleCompare(attribute,"geometry") == 0)
11696 {
11697 char
11698 *p;
11699
11700 p=SvPV(ST(i),na);
11701 if (IsGeometry(p) == MagickFalse)
11702 {
11703 ThrowPerlException(exception,OptionError,"MissingGeometry",
11704 p);
11705 break;
11706 }
11707 (void) CloneString(&montage_info->geometry,p);
11708 if (*p == '\0')
11709 montage_info->geometry=(char *) NULL;
11710 break;
11711 }
11712 if (LocaleCompare(attribute,"gravity") == 0)
11713 {
11714 ssize_t
11715 in;
11716
11717 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11718 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11719 if (in < 0)
11720 {
11721 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11722 SvPV(ST(i),na));
11723 return;
11724 }
11725 montage_info->gravity=(GravityType) in;
11726 for (next=image; next; next=next->next)
11727 next->gravity=(GravityType) in;
11728 break;
11729 }
11730 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11731 attribute);
11732 break;
11733 }
11734 case 'L':
11735 case 'l':
11736 {
11737 if (LocaleCompare(attribute,"label") == 0)
11738 {
11739 for (next=image; next; next=next->next)
Cristy935a4052017-03-31 17:45:37 -040011740 (void) SetImageProperty(next,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +000011741 info ? info->image_info : (ImageInfo *) NULL,next,
Cristy935a4052017-03-31 17:45:37 -040011742 SvPV(ST(i),na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011743 break;
11744 }
11745 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11746 attribute);
11747 break;
11748 }
11749 case 'M':
11750 case 'm':
11751 {
11752 if (LocaleCompare(attribute,"mattecolor") == 0)
11753 {
11754 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
Cristy8645e042016-02-03 16:35:29 -050011755 &montage_info->alpha_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011756 for (next=image; next; next=next->next)
Cristy8645e042016-02-03 16:35:29 -050011757 next->alpha_color=montage_info->alpha_color;
cristy4a3ce0a2013-08-03 20:06:59 +000011758 break;
11759 }
11760 if (LocaleCompare(attribute,"mode") == 0)
11761 {
11762 ssize_t
11763 in;
11764
11765 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11766 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11767 switch (in)
11768 {
11769 default:
11770 {
11771 ThrowPerlException(exception,OptionError,
11772 "UnrecognizedModeType",SvPV(ST(i),na));
11773 break;
11774 }
11775 case FrameMode:
11776 {
11777 (void) CloneString(&montage_info->frame,"15x15+3+3");
11778 montage_info->shadow=MagickTrue;
11779 break;
11780 }
11781 case UnframeMode:
11782 {
11783 montage_info->frame=(char *) NULL;
11784 montage_info->shadow=MagickFalse;
11785 montage_info->border_width=0;
11786 break;
11787 }
11788 case ConcatenateMode:
11789 {
11790 montage_info->frame=(char *) NULL;
11791 montage_info->shadow=MagickFalse;
11792 (void) CloneString(&montage_info->geometry,"+0+0");
11793 montage_info->border_width=0;
11794 }
11795 }
11796 break;
11797 }
11798 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11799 attribute);
11800 break;
11801 }
11802 case 'P':
11803 case 'p':
11804 {
11805 if (LocaleCompare(attribute,"pointsize") == 0)
11806 {
11807 montage_info->pointsize=SvIV(ST(i));
11808 break;
11809 }
11810 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11811 attribute);
11812 break;
11813 }
11814 case 'S':
11815 case 's':
11816 {
11817 if (LocaleCompare(attribute,"shadow") == 0)
11818 {
11819 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11820 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11821 if (sp < 0)
11822 {
11823 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11824 SvPV(ST(i),na));
11825 break;
11826 }
11827 montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11828 break;
11829 }
11830 if (LocaleCompare(attribute,"stroke") == 0)
11831 {
11832 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11833 &montage_info->stroke,exception);
11834 break;
11835 }
11836 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11837 attribute);
11838 break;
11839 }
11840 case 'T':
11841 case 't':
11842 {
11843 if (LocaleCompare(attribute,"texture") == 0)
11844 {
11845 (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11846 break;
11847 }
11848 if (LocaleCompare(attribute,"tile") == 0)
11849 {
11850 char *p=SvPV(ST(i),na);
11851 if (IsGeometry(p) == MagickFalse)
11852 {
11853 ThrowPerlException(exception,OptionError,"MissingGeometry",
11854 p);
11855 break;
11856 }
11857 (void) CloneString(&montage_info->tile,p);
11858 if (*p == '\0')
11859 montage_info->tile=(char *) NULL;
11860 break;
11861 }
11862 if (LocaleCompare(attribute,"title") == 0)
11863 {
11864 (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11865 break;
11866 }
11867 if (LocaleCompare(attribute,"transparent") == 0)
11868 {
11869 PixelInfo
11870 transparent_color;
11871
11872 QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11873 &transparent_color,exception);
11874 for (next=image; next; next=next->next)
11875 (void) TransparentPaintImage(next,&transparent_color,
11876 TransparentAlpha,MagickFalse,exception);
11877 break;
11878 }
11879 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11880 attribute);
11881 break;
11882 }
11883 default:
11884 {
11885 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11886 attribute);
11887 break;
11888 }
11889 }
11890 }
11891 image=MontageImageList(info->image_info,montage_info,image,exception);
11892 montage_info=DestroyMontageInfo(montage_info);
11893 if (image == (Image *) NULL)
11894 goto PerlException;
11895 if (transparent_color.alpha != TransparentAlpha)
11896 for (next=image; next; next=next->next)
11897 (void) TransparentPaintImage(next,&transparent_color,
11898 TransparentAlpha,MagickFalse,exception);
11899 for ( ; image; image=image->next)
11900 {
11901 AddImageToRegistry(sv,image);
11902 rv=newRV(sv);
11903 av_push(av,sv_bless(rv,hv));
11904 SvREFCNT_dec(sv);
11905 }
11906 exception=DestroyExceptionInfo(exception);
11907 ST(0)=av_reference;
11908 SvREFCNT_dec(perl_exception);
11909 XSRETURN(1);
11910
11911 PerlException:
11912 InheritPerlException(exception,perl_exception);
11913 exception=DestroyExceptionInfo(exception);
11914 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11915 SvPOK_on(perl_exception);
11916 ST(0)=sv_2mortal(perl_exception);
11917 XSRETURN(1);
11918 }
11919
11920#
11921###############################################################################
11922# #
11923# #
11924# #
11925# M o r p h #
11926# #
11927# #
11928# #
11929###############################################################################
11930#
11931#
11932void
11933Morph(ref,...)
11934 Image::Magick ref=NO_INIT
11935 ALIAS:
11936 MorphImage = 1
11937 morph = 2
11938 morphimage = 3
11939 PPCODE:
11940 {
11941 AV
11942 *av;
11943
11944 char
11945 *attribute;
11946
11947 ExceptionInfo
11948 *exception;
11949
11950 HV
11951 *hv;
11952
11953 Image
11954 *image;
11955
11956 register ssize_t
11957 i;
11958
11959 ssize_t
11960 number_frames;
11961
11962 struct PackageInfo
11963 *info;
11964
11965 SV
11966 *av_reference,
11967 *perl_exception,
11968 *reference,
11969 *rv,
11970 *sv;
11971
11972 PERL_UNUSED_VAR(ref);
11973 PERL_UNUSED_VAR(ix);
11974 exception=AcquireExceptionInfo();
11975 perl_exception=newSVpv("",0);
11976 sv=NULL;
11977 av=NULL;
11978 attribute=NULL;
11979 if (sv_isobject(ST(0)) == 0)
11980 {
11981 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11982 PackageName);
11983 goto PerlException;
11984 }
11985 reference=SvRV(ST(0));
11986 hv=SvSTASH(reference);
11987 av=newAV();
11988 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11989 SvREFCNT_dec(av);
11990 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11991 if (image == (Image *) NULL)
11992 {
11993 ThrowPerlException(exception,OptionError,"NoImagesDefined",
11994 PackageName);
11995 goto PerlException;
11996 }
11997 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11998 /*
11999 Get attribute.
12000 */
12001 number_frames=30;
12002 for (i=2; i < items; i+=2)
12003 {
12004 attribute=(char *) SvPV(ST(i-1),na);
12005 switch (*attribute)
12006 {
12007 case 'F':
12008 case 'f':
12009 {
12010 if (LocaleCompare(attribute,"frames") == 0)
12011 {
12012 number_frames=SvIV(ST(i));
12013 break;
12014 }
12015 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12016 attribute);
12017 break;
12018 }
12019 default:
12020 {
12021 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12022 attribute);
12023 break;
12024 }
12025 }
12026 }
12027 image=MorphImages(image,number_frames,exception);
12028 if (image == (Image *) NULL)
12029 goto PerlException;
12030 for ( ; image; image=image->next)
12031 {
12032 AddImageToRegistry(sv,image);
12033 rv=newRV(sv);
12034 av_push(av,sv_bless(rv,hv));
12035 SvREFCNT_dec(sv);
12036 }
12037 exception=DestroyExceptionInfo(exception);
12038 ST(0)=av_reference;
12039 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12040 XSRETURN(1);
12041
12042 PerlException:
12043 InheritPerlException(exception,perl_exception);
12044 exception=DestroyExceptionInfo(exception);
12045 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12046 SvPOK_on(perl_exception);
12047 ST(0)=sv_2mortal(perl_exception);
12048 XSRETURN(1);
12049 }
12050
12051#
12052###############################################################################
12053# #
12054# #
12055# #
12056# M o s a i c #
12057# #
12058# #
12059# #
12060###############################################################################
12061#
12062#
12063void
12064Mosaic(ref)
12065 Image::Magick ref=NO_INIT
12066 ALIAS:
12067 MosaicImage = 1
12068 mosaic = 2
12069 mosaicimage = 3
12070 PPCODE:
12071 {
12072 AV
12073 *av;
12074
12075 ExceptionInfo
12076 *exception;
12077
12078 HV
12079 *hv;
12080
12081 Image
12082 *image;
12083
12084 struct PackageInfo
12085 *info;
12086
12087 SV
12088 *perl_exception,
12089 *reference,
12090 *rv,
12091 *sv;
12092
12093 PERL_UNUSED_VAR(ref);
12094 PERL_UNUSED_VAR(ix);
12095 exception=AcquireExceptionInfo();
12096 perl_exception=newSVpv("",0);
12097 sv=NULL;
12098 if (sv_isobject(ST(0)) == 0)
12099 {
12100 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12101 PackageName);
12102 goto PerlException;
12103 }
12104 reference=SvRV(ST(0));
12105 hv=SvSTASH(reference);
12106 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12107 if (image == (Image *) NULL)
12108 {
12109 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12110 PackageName);
12111 goto PerlException;
12112 }
12113 image=MergeImageLayers(image,MosaicLayer,exception);
12114 /*
12115 Create blessed Perl array for the returned image.
12116 */
12117 av=newAV();
12118 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12119 SvREFCNT_dec(av);
12120 AddImageToRegistry(sv,image);
12121 rv=newRV(sv);
12122 av_push(av,sv_bless(rv,hv));
12123 SvREFCNT_dec(sv);
cristy4a3ce0a2013-08-03 20:06:59 +000012124 (void) CopyMagickString(info->image_info->filename,image->filename,
cristy151b66d2015-04-15 10:50:31 +000012125 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012126 SetImageInfo(info->image_info,0,exception);
12127 exception=DestroyExceptionInfo(exception);
12128 SvREFCNT_dec(perl_exception);
12129 XSRETURN(1);
12130
12131 PerlException:
12132 InheritPerlException(exception,perl_exception);
12133 exception=DestroyExceptionInfo(exception);
12134 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12135 SvPOK_on(perl_exception); /* return messages in string context */
12136 ST(0)=sv_2mortal(perl_exception);
12137 XSRETURN(1);
12138 }
12139
12140#
12141###############################################################################
12142# #
12143# #
12144# #
12145# P i n g #
12146# #
12147# #
12148# #
12149###############################################################################
12150#
12151#
12152void
12153Ping(ref,...)
12154 Image::Magick ref=NO_INIT
12155 ALIAS:
12156 PingImage = 1
12157 ping = 2
12158 pingimage = 3
12159 PPCODE:
12160 {
12161 AV
12162 *av;
12163
12164 char
12165 **keep,
12166 **list;
12167
12168 ExceptionInfo
12169 *exception;
12170
12171 Image
12172 *image,
12173 *next;
12174
12175 int
12176 n;
12177
12178 MagickBooleanType
12179 status;
12180
12181 register char
12182 **p;
12183
12184 register ssize_t
12185 i;
12186
12187 ssize_t
12188 ac;
12189
12190 STRLEN
12191 *length;
12192
12193 struct PackageInfo
12194 *info,
12195 *package_info;
12196
12197 SV
12198 *perl_exception,
12199 *reference;
12200
12201 size_t
12202 count;
12203
12204 PERL_UNUSED_VAR(ref);
12205 PERL_UNUSED_VAR(ix);
12206 exception=AcquireExceptionInfo();
12207 perl_exception=newSVpv("",0);
12208 package_info=(struct PackageInfo *) NULL;
12209 ac=(items < 2) ? 1 : items-1;
12210 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12211 keep=list;
12212 length=(STRLEN *) NULL;
12213 if (list == (char **) NULL)
12214 {
12215 ThrowPerlException(exception,ResourceLimitError,
12216 "MemoryAllocationFailed",PackageName);
12217 goto PerlException;
12218 }
12219 keep=list;
12220 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12221 if (length == (STRLEN *) NULL)
12222 {
12223 ThrowPerlException(exception,ResourceLimitError,
12224 "MemoryAllocationFailed",PackageName);
12225 goto PerlException;
12226 }
12227 if (sv_isobject(ST(0)) == 0)
12228 {
12229 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12230 PackageName);
12231 goto PerlException;
12232 }
12233 reference=SvRV(ST(0));
12234 if (SvTYPE(reference) != SVt_PVAV)
12235 {
12236 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12237 PackageName);
12238 goto PerlException;
12239 }
12240 av=(AV *) reference;
12241 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12242 exception);
12243 package_info=ClonePackageInfo(info,exception);
12244 n=1;
12245 if (items <= 1)
12246 *list=(char *) (*package_info->image_info->filename ?
12247 package_info->image_info->filename : "XC:black");
12248 else
12249 for (n=0, i=0; i < ac; i++)
12250 {
12251 list[n]=(char *) SvPV(ST(i+1),length[n]);
12252 if ((items >= 3) && strEQcase(list[n],"blob"))
12253 {
12254 void
12255 *blob;
12256
12257 i++;
12258 blob=(void *) (SvPV(ST(i+1),length[n]));
12259 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12260 }
12261 if ((items >= 3) && strEQcase(list[n],"filename"))
12262 continue;
12263 if ((items >= 3) && strEQcase(list[n],"file"))
12264 {
12265 FILE
12266 *file;
12267
12268 PerlIO
12269 *io_info;
12270
12271 i++;
12272 io_info=IoIFP(sv_2io(ST(i+1)));
12273 if (io_info == (PerlIO *) NULL)
12274 {
12275 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12276 PackageName);
12277 continue;
12278 }
12279 file=PerlIO_findFILE(io_info);
12280 if (file == (FILE *) NULL)
12281 {
12282 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12283 PackageName);
12284 continue;
12285 }
12286 SetImageInfoFile(package_info->image_info,file);
12287 }
12288 if ((items >= 3) && strEQcase(list[n],"magick"))
12289 continue;
12290 n++;
12291 }
12292 list[n]=(char *) NULL;
12293 keep=list;
12294 status=ExpandFilenames(&n,&list);
12295 if (status == MagickFalse)
12296 {
12297 ThrowPerlException(exception,ResourceLimitError,
12298 "MemoryAllocationFailed",PackageName);
12299 goto PerlException;
12300 }
12301 count=0;
12302 for (i=0; i < n; i++)
12303 {
12304 (void) CopyMagickString(package_info->image_info->filename,list[i],
cristy151b66d2015-04-15 10:50:31 +000012305 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012306 image=PingImage(package_info->image_info,exception);
12307 if (image == (Image *) NULL)
12308 break;
12309 if ((package_info->image_info->file != (FILE *) NULL) ||
12310 (package_info->image_info->blob != (void *) NULL))
12311 DisassociateImageStream(image);
12312 count+=GetImageListLength(image);
12313 EXTEND(sp,4*count);
12314 for (next=image; next; next=next->next)
12315 {
12316 PUSHs(sv_2mortal(newSViv(next->columns)));
12317 PUSHs(sv_2mortal(newSViv(next->rows)));
12318 PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12319 PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12320 }
12321 image=DestroyImageList(image);
12322 }
12323 /*
12324 Free resources.
12325 */
12326 for (i=0; i < n; i++)
12327 if (list[i] != (char *) NULL)
12328 for (p=keep; list[i] != *p++; )
12329 if (*p == NULL)
12330 {
12331 list[i]=(char *) RelinquishMagickMemory(list[i]);
12332 break;
12333 }
12334
12335 PerlException:
12336 if (package_info != (struct PackageInfo *) NULL)
12337 DestroyPackageInfo(package_info);
12338 if (list && (list != keep))
12339 list=(char **) RelinquishMagickMemory(list);
12340 if (keep)
12341 keep=(char **) RelinquishMagickMemory(keep);
12342 if (length)
12343 length=(STRLEN *) RelinquishMagickMemory(length);
12344 InheritPerlException(exception,perl_exception);
12345 exception=DestroyExceptionInfo(exception);
12346 SvREFCNT_dec(perl_exception); /* throw away all errors */
12347 }
12348
12349#
12350###############################################################################
12351# #
12352# #
12353# #
12354# P r e v i e w #
12355# #
12356# #
12357# #
12358###############################################################################
12359#
12360#
12361void
12362Preview(ref,...)
12363 Image::Magick ref=NO_INIT
12364 ALIAS:
12365 PreviewImage = 1
12366 preview = 2
12367 previewimage = 3
12368 PPCODE:
12369 {
12370 AV
12371 *av;
12372
12373 ExceptionInfo
12374 *exception;
12375
12376 HV
12377 *hv;
12378
12379 Image
12380 *image,
12381 *preview_image;
12382
12383 PreviewType
12384 preview_type;
12385
12386 struct PackageInfo
12387 *info;
12388
12389 SV
12390 *av_reference,
12391 *perl_exception,
12392 *reference,
12393 *rv,
12394 *sv;
12395
12396 PERL_UNUSED_VAR(ref);
12397 PERL_UNUSED_VAR(ix);
12398 exception=AcquireExceptionInfo();
12399 perl_exception=newSVpv("",0);
12400 sv=NULL;
12401 av=NULL;
12402 if (sv_isobject(ST(0)) == 0)
12403 {
12404 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12405 PackageName);
12406 goto PerlException;
12407 }
12408 reference=SvRV(ST(0));
12409 hv=SvSTASH(reference);
12410 av=newAV();
12411 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12412 SvREFCNT_dec(av);
12413 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12414 if (image == (Image *) NULL)
12415 {
12416 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12417 PackageName);
12418 goto PerlException;
12419 }
12420 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12421 preview_type=GammaPreview;
12422 if (items > 1)
12423 preview_type=(PreviewType)
12424 ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12425 for ( ; image; image=image->next)
12426 {
12427 preview_image=PreviewImage(image,preview_type,exception);
12428 if (preview_image == (Image *) NULL)
12429 goto PerlException;
12430 AddImageToRegistry(sv,preview_image);
12431 rv=newRV(sv);
12432 av_push(av,sv_bless(rv,hv));
12433 SvREFCNT_dec(sv);
12434 }
12435 exception=DestroyExceptionInfo(exception);
12436 ST(0)=av_reference;
12437 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12438 XSRETURN(1);
12439
12440 PerlException:
12441 InheritPerlException(exception,perl_exception);
12442 exception=DestroyExceptionInfo(exception);
12443 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12444 SvPOK_on(perl_exception);
12445 ST(0)=sv_2mortal(perl_exception);
12446 XSRETURN(1);
12447 }
12448
12449#
12450###############################################################################
12451# #
12452# #
12453# #
12454# Q u e r y C o l o r #
12455# #
12456# #
12457# #
12458###############################################################################
12459#
12460#
12461void
12462QueryColor(ref,...)
12463 Image::Magick ref=NO_INIT
12464 ALIAS:
12465 querycolor = 1
12466 PPCODE:
12467 {
12468 char
12469 *name;
12470
12471 ExceptionInfo
12472 *exception;
12473
12474 PixelInfo
12475 color;
12476
12477 register ssize_t
12478 i;
12479
12480 SV
12481 *perl_exception;
12482
12483 PERL_UNUSED_VAR(ref);
12484 PERL_UNUSED_VAR(ix);
12485 exception=AcquireExceptionInfo();
12486 perl_exception=newSVpv("",0);
12487 if (items == 1)
12488 {
12489 const ColorInfo
12490 **colorlist;
12491
12492 size_t
12493 colors;
12494
12495 colorlist=GetColorInfoList("*",&colors,exception);
12496 EXTEND(sp,colors);
12497 for (i=0; i < (ssize_t) colors; i++)
12498 {
12499 PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12500 }
12501 colorlist=(const ColorInfo **)
12502 RelinquishMagickMemory((ColorInfo **) colorlist);
12503 goto PerlException;
12504 }
12505 EXTEND(sp,5*items);
12506 for (i=1; i < items; i++)
12507 {
12508 name=(char *) SvPV(ST(i),na);
12509 if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12510 {
12511 PUSHs(&sv_undef);
12512 continue;
12513 }
12514 PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12515 PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12516 PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12517 if (color.colorspace == CMYKColorspace)
12518 PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
cristy17f11b02014-12-20 19:37:04 +000012519 if (color.alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +000012520 PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12521 }
12522
12523 PerlException:
12524 InheritPerlException(exception,perl_exception);
12525 exception=DestroyExceptionInfo(exception);
12526 SvREFCNT_dec(perl_exception);
12527 }
12528
12529#
12530###############################################################################
12531# #
12532# #
12533# #
12534# Q u e r y C o l o r N a m e #
12535# #
12536# #
12537# #
12538###############################################################################
12539#
12540#
12541void
12542QueryColorname(ref,...)
12543 Image::Magick ref=NO_INIT
12544 ALIAS:
12545 querycolorname = 1
12546 PPCODE:
12547 {
12548 AV
12549 *av;
12550
12551 char
cristy151b66d2015-04-15 10:50:31 +000012552 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012553
12554 ExceptionInfo
12555 *exception;
12556
12557 Image
12558 *image;
12559
12560 PixelInfo
12561 target_color;
12562
12563 register ssize_t
12564 i;
12565
12566 struct PackageInfo
12567 *info;
12568
12569 SV
12570 *perl_exception,
12571 *reference; /* reference is the SV* of ref=SvIV(reference) */
12572
12573 PERL_UNUSED_VAR(ref);
12574 PERL_UNUSED_VAR(ix);
12575 exception=AcquireExceptionInfo();
12576 perl_exception=newSVpv("",0);
12577 reference=SvRV(ST(0));
12578 av=(AV *) reference;
12579 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12580 exception);
12581 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12582 if (image == (Image *) NULL)
12583 {
12584 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12585 PackageName);
12586 goto PerlException;
12587 }
12588 EXTEND(sp,items);
12589 for (i=1; i < items; i++)
12590 {
12591 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12592 exception);
12593 (void) QueryColorname(image,&target_color,SVGCompliance,message,
12594 exception);
12595 PUSHs(sv_2mortal(newSVpv(message,0)));
12596 }
12597
12598 PerlException:
12599 InheritPerlException(exception,perl_exception);
12600 exception=DestroyExceptionInfo(exception);
12601 SvREFCNT_dec(perl_exception);
12602 }
12603
12604#
12605###############################################################################
12606# #
12607# #
12608# #
12609# Q u e r y F o n t #
12610# #
12611# #
12612# #
12613###############################################################################
12614#
12615#
12616void
12617QueryFont(ref,...)
12618 Image::Magick ref=NO_INIT
12619 ALIAS:
12620 queryfont = 1
12621 PPCODE:
12622 {
12623 char
12624 *name,
cristy151b66d2015-04-15 10:50:31 +000012625 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012626
12627 ExceptionInfo
12628 *exception;
12629
12630 register ssize_t
12631 i;
12632
12633 SV
12634 *perl_exception;
12635
12636 volatile const TypeInfo
12637 *type_info;
12638
12639 PERL_UNUSED_VAR(ref);
12640 PERL_UNUSED_VAR(ix);
12641 exception=AcquireExceptionInfo();
12642 perl_exception=newSVpv("",0);
12643 if (items == 1)
12644 {
12645 const TypeInfo
12646 **typelist;
12647
12648 size_t
12649 types;
12650
12651 typelist=GetTypeInfoList("*",&types,exception);
12652 EXTEND(sp,types);
12653 for (i=0; i < (ssize_t) types; i++)
12654 {
12655 PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12656 }
12657 typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12658 typelist);
12659 goto PerlException;
12660 }
12661 EXTEND(sp,10*items);
12662 for (i=1; i < items; i++)
12663 {
12664 name=(char *) SvPV(ST(i),na);
12665 type_info=GetTypeInfo(name,exception);
12666 if (type_info == (TypeInfo *) NULL)
12667 {
12668 PUSHs(&sv_undef);
12669 continue;
12670 }
12671 if (type_info->name == (char *) NULL)
12672 PUSHs(&sv_undef);
12673 else
12674 PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12675 if (type_info->description == (char *) NULL)
12676 PUSHs(&sv_undef);
12677 else
12678 PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12679 if (type_info->family == (char *) NULL)
12680 PUSHs(&sv_undef);
12681 else
12682 PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12683 if (type_info->style == UndefinedStyle)
12684 PUSHs(&sv_undef);
12685 else
12686 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12687 type_info->style),0)));
12688 if (type_info->stretch == UndefinedStretch)
12689 PUSHs(&sv_undef);
12690 else
12691 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12692 type_info->stretch),0)));
cristy151b66d2015-04-15 10:50:31 +000012693 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
cristy4a3ce0a2013-08-03 20:06:59 +000012694 type_info->weight);
12695 PUSHs(sv_2mortal(newSVpv(message,0)));
12696 if (type_info->encoding == (char *) NULL)
12697 PUSHs(&sv_undef);
12698 else
12699 PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12700 if (type_info->foundry == (char *) NULL)
12701 PUSHs(&sv_undef);
12702 else
12703 PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12704 if (type_info->format == (char *) NULL)
12705 PUSHs(&sv_undef);
12706 else
12707 PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12708 if (type_info->metrics == (char *) NULL)
12709 PUSHs(&sv_undef);
12710 else
12711 PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12712 if (type_info->glyphs == (char *) NULL)
12713 PUSHs(&sv_undef);
12714 else
12715 PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12716 }
12717
12718 PerlException:
12719 InheritPerlException(exception,perl_exception);
12720 exception=DestroyExceptionInfo(exception);
12721 SvREFCNT_dec(perl_exception);
12722 }
12723
12724#
12725###############################################################################
12726# #
12727# #
12728# #
12729# Q u e r y F o n t M e t r i c s #
12730# #
12731# #
12732# #
12733###############################################################################
12734#
12735#
12736void
12737QueryFontMetrics(ref,...)
12738 Image::Magick ref=NO_INIT
12739 ALIAS:
12740 queryfontmetrics = 1
12741 PPCODE:
12742 {
12743 AffineMatrix
12744 affine,
12745 current;
12746
12747 AV
12748 *av;
12749
12750 char
12751 *attribute;
12752
12753 double
12754 x,
12755 y;
12756
12757 DrawInfo
12758 *draw_info;
12759
12760 ExceptionInfo
12761 *exception;
12762
12763 GeometryInfo
12764 geometry_info;
12765
12766 Image
12767 *image;
12768
12769 MagickBooleanType
12770 status;
12771
12772 MagickStatusType
12773 flags;
12774
12775 register ssize_t
12776 i;
12777
12778 ssize_t
12779 type;
12780
12781 struct PackageInfo
12782 *info,
12783 *package_info;
12784
12785 SV
12786 *perl_exception,
12787 *reference; /* reference is the SV* of ref=SvIV(reference) */
12788
12789 TypeMetric
12790 metrics;
12791
12792 PERL_UNUSED_VAR(ref);
12793 PERL_UNUSED_VAR(ix);
12794 exception=AcquireExceptionInfo();
12795 package_info=(struct PackageInfo *) NULL;
12796 perl_exception=newSVpv("",0);
12797 reference=SvRV(ST(0));
12798 av=(AV *) reference;
12799 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12800 exception);
12801 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12802 if (image == (Image *) NULL)
12803 {
12804 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12805 PackageName);
12806 goto PerlException;
12807 }
12808 package_info=ClonePackageInfo(info,exception);
12809 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12810 CloneString(&draw_info->text,"");
12811 current=draw_info->affine;
12812 GetAffineMatrix(&affine);
12813 x=0.0;
12814 y=0.0;
12815 EXTEND(sp,7*items);
12816 for (i=2; i < items; i+=2)
12817 {
12818 attribute=(char *) SvPV(ST(i-1),na);
12819 switch (*attribute)
12820 {
12821 case 'A':
12822 case 'a':
12823 {
12824 if (LocaleCompare(attribute,"antialias") == 0)
12825 {
12826 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12827 SvPV(ST(i),na));
12828 if (type < 0)
12829 {
12830 ThrowPerlException(exception,OptionError,"UnrecognizedType",
12831 SvPV(ST(i),na));
12832 break;
12833 }
12834 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12835 break;
12836 }
12837 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12838 attribute);
12839 break;
12840 }
12841 case 'd':
12842 case 'D':
12843 {
12844 if (LocaleCompare(attribute,"density") == 0)
12845 {
12846 CloneString(&draw_info->density,SvPV(ST(i),na));
12847 break;
12848 }
12849 if (LocaleCompare(attribute,"direction") == 0)
12850 {
12851 draw_info->direction=(DirectionType) ParseCommandOption(
12852 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12853 break;
12854 }
12855 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12856 attribute);
12857 break;
12858 }
12859 case 'e':
12860 case 'E':
12861 {
12862 if (LocaleCompare(attribute,"encoding") == 0)
12863 {
12864 CloneString(&draw_info->encoding,SvPV(ST(i),na));
12865 break;
12866 }
12867 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12868 attribute);
12869 break;
12870 }
12871 case 'f':
12872 case 'F':
12873 {
12874 if (LocaleCompare(attribute,"family") == 0)
12875 {
12876 CloneString(&draw_info->family,SvPV(ST(i),na));
12877 break;
12878 }
12879 if (LocaleCompare(attribute,"fill") == 0)
12880 {
12881 if (info)
12882 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12883 &draw_info->fill,exception);
12884 break;
12885 }
12886 if (LocaleCompare(attribute,"font") == 0)
12887 {
12888 CloneString(&draw_info->font,SvPV(ST(i),na));
12889 break;
12890 }
12891 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12892 attribute);
12893 break;
12894 }
12895 case 'g':
12896 case 'G':
12897 {
12898 if (LocaleCompare(attribute,"geometry") == 0)
12899 {
12900 CloneString(&draw_info->geometry,SvPV(ST(i),na));
12901 break;
12902 }
12903 if (LocaleCompare(attribute,"gravity") == 0)
12904 {
12905 draw_info->gravity=(GravityType) ParseCommandOption(
12906 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12907 break;
12908 }
12909 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12910 attribute);
12911 break;
12912 }
12913 case 'i':
12914 case 'I':
12915 {
12916 if (LocaleCompare(attribute,"interline-spacing") == 0)
12917 {
12918 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12919 draw_info->interline_spacing=geometry_info.rho;
12920 break;
12921 }
12922 if (LocaleCompare(attribute,"interword-spacing") == 0)
12923 {
12924 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12925 draw_info->interword_spacing=geometry_info.rho;
12926 break;
12927 }
12928 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12929 attribute);
12930 break;
12931 }
12932 case 'k':
12933 case 'K':
12934 {
12935 if (LocaleCompare(attribute,"kerning") == 0)
12936 {
12937 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12938 draw_info->kerning=geometry_info.rho;
12939 break;
12940 }
12941 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12942 attribute);
12943 break;
12944 }
12945 case 'p':
12946 case 'P':
12947 {
12948 if (LocaleCompare(attribute,"pointsize") == 0)
12949 {
12950 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12951 draw_info->pointsize=geometry_info.rho;
12952 break;
12953 }
12954 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12955 attribute);
12956 break;
12957 }
12958 case 'r':
12959 case 'R':
12960 {
12961 if (LocaleCompare(attribute,"rotate") == 0)
12962 {
12963 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12964 affine.rx=geometry_info.rho;
12965 affine.ry=geometry_info.sigma;
12966 if ((flags & SigmaValue) == 0)
12967 affine.ry=affine.rx;
12968 break;
12969 }
12970 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12971 attribute);
12972 break;
12973 }
12974 case 's':
12975 case 'S':
12976 {
12977 if (LocaleCompare(attribute,"scale") == 0)
12978 {
12979 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12980 affine.sx=geometry_info.rho;
12981 affine.sy=geometry_info.sigma;
12982 if ((flags & SigmaValue) == 0)
12983 affine.sy=affine.sx;
12984 break;
12985 }
12986 if (LocaleCompare(attribute,"skew") == 0)
12987 {
12988 double
12989 x_angle,
12990 y_angle;
12991
12992 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12993 x_angle=geometry_info.rho;
12994 y_angle=geometry_info.sigma;
12995 if ((flags & SigmaValue) == 0)
12996 y_angle=x_angle;
12997 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12998 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12999 break;
13000 }
13001 if (LocaleCompare(attribute,"stroke") == 0)
13002 {
13003 if (info)
13004 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13005 &draw_info->stroke,exception);
13006 break;
13007 }
13008 if (LocaleCompare(attribute,"style") == 0)
13009 {
13010 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13011 SvPV(ST(i),na));
13012 if (type < 0)
13013 {
13014 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13015 SvPV(ST(i),na));
13016 break;
13017 }
13018 draw_info->style=(StyleType) type;
13019 break;
13020 }
13021 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13022 attribute);
13023 break;
13024 }
13025 case 't':
13026 case 'T':
13027 {
13028 if (LocaleCompare(attribute,"text") == 0)
13029 {
13030 CloneString(&draw_info->text,SvPV(ST(i),na));
13031 break;
13032 }
13033 if (LocaleCompare(attribute,"translate") == 0)
13034 {
13035 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13036 affine.tx=geometry_info.rho;
13037 affine.ty=geometry_info.sigma;
13038 if ((flags & SigmaValue) == 0)
13039 affine.ty=affine.tx;
13040 break;
13041 }
13042 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13043 attribute);
13044 break;
13045 }
13046 case 'w':
13047 case 'W':
13048 {
13049 if (LocaleCompare(attribute,"weight") == 0)
13050 {
13051 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13052 draw_info->weight=(size_t) geometry_info.rho;
13053 break;
13054 }
13055 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13056 attribute);
13057 break;
13058 }
13059 case 'x':
13060 case 'X':
13061 {
13062 if (LocaleCompare(attribute,"x") == 0)
13063 {
13064 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13065 x=geometry_info.rho;
13066 break;
13067 }
13068 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13069 attribute);
13070 break;
13071 }
13072 case 'y':
13073 case 'Y':
13074 {
13075 if (LocaleCompare(attribute,"y") == 0)
13076 {
13077 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13078 y=geometry_info.rho;
13079 break;
13080 }
13081 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13082 attribute);
13083 break;
13084 }
13085 default:
13086 {
13087 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13088 attribute);
13089 break;
13090 }
13091 }
13092 }
13093 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13094 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13095 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13096 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13097 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13098 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13099 if (draw_info->geometry == (char *) NULL)
13100 {
13101 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013102 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013103 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013104 }
13105 status=GetTypeMetrics(image,draw_info,&metrics,exception);
13106 (void) CatchImageException(image);
13107 if (status == MagickFalse)
13108 PUSHs(&sv_undef);
13109 else
13110 {
13111 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13112 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13113 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13114 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13115 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13116 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13117 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13118 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13119 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13120 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13121 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13122 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13123 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13124 }
13125 draw_info=DestroyDrawInfo(draw_info);
13126
13127 PerlException:
13128 if (package_info != (struct PackageInfo *) NULL)
13129 DestroyPackageInfo(package_info);
13130 InheritPerlException(exception,perl_exception);
13131 exception=DestroyExceptionInfo(exception);
13132 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13133 }
13134
13135#
13136###############################################################################
13137# #
13138# #
13139# #
13140# 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 #
13141# #
13142# #
13143# #
13144###############################################################################
13145#
13146#
13147void
13148QueryMultilineFontMetrics(ref,...)
13149 Image::Magick ref=NO_INIT
13150 ALIAS:
13151 querymultilinefontmetrics = 1
13152 PPCODE:
13153 {
13154 AffineMatrix
13155 affine,
13156 current;
13157
13158 AV
13159 *av;
13160
13161 char
13162 *attribute;
13163
13164 double
13165 x,
13166 y;
13167
13168 DrawInfo
13169 *draw_info;
13170
13171 ExceptionInfo
13172 *exception;
13173
13174 GeometryInfo
13175 geometry_info;
13176
13177 Image
13178 *image;
13179
13180 MagickBooleanType
13181 status;
13182
13183 MagickStatusType
13184 flags;
13185
13186 register ssize_t
13187 i;
13188
13189 ssize_t
13190 type;
13191
13192 struct PackageInfo
13193 *info,
13194 *package_info;
13195
13196 SV
13197 *perl_exception,
13198 *reference; /* reference is the SV* of ref=SvIV(reference) */
13199
13200 TypeMetric
13201 metrics;
13202
13203 PERL_UNUSED_VAR(ref);
13204 PERL_UNUSED_VAR(ix);
13205 exception=AcquireExceptionInfo();
13206 package_info=(struct PackageInfo *) NULL;
13207 perl_exception=newSVpv("",0);
13208 reference=SvRV(ST(0));
13209 av=(AV *) reference;
13210 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13211 exception);
13212 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13213 if (image == (Image *) NULL)
13214 {
13215 ThrowPerlException(exception,OptionError,"NoImagesDefined",
13216 PackageName);
13217 goto PerlException;
13218 }
13219 package_info=ClonePackageInfo(info,exception);
13220 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13221 CloneString(&draw_info->text,"");
13222 current=draw_info->affine;
13223 GetAffineMatrix(&affine);
13224 x=0.0;
13225 y=0.0;
13226 EXTEND(sp,7*items);
13227 for (i=2; i < items; i+=2)
13228 {
13229 attribute=(char *) SvPV(ST(i-1),na);
13230 switch (*attribute)
13231 {
13232 case 'A':
13233 case 'a':
13234 {
13235 if (LocaleCompare(attribute,"antialias") == 0)
13236 {
13237 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13238 SvPV(ST(i),na));
13239 if (type < 0)
13240 {
13241 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13242 SvPV(ST(i),na));
13243 break;
13244 }
13245 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13246 break;
13247 }
13248 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13249 attribute);
13250 break;
13251 }
13252 case 'd':
13253 case 'D':
13254 {
13255 if (LocaleCompare(attribute,"density") == 0)
13256 {
13257 CloneString(&draw_info->density,SvPV(ST(i),na));
13258 break;
13259 }
13260 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13261 attribute);
13262 break;
13263 }
13264 case 'e':
13265 case 'E':
13266 {
13267 if (LocaleCompare(attribute,"encoding") == 0)
13268 {
13269 CloneString(&draw_info->encoding,SvPV(ST(i),na));
13270 break;
13271 }
13272 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13273 attribute);
13274 break;
13275 }
13276 case 'f':
13277 case 'F':
13278 {
13279 if (LocaleCompare(attribute,"family") == 0)
13280 {
13281 CloneString(&draw_info->family,SvPV(ST(i),na));
13282 break;
13283 }
13284 if (LocaleCompare(attribute,"fill") == 0)
13285 {
13286 if (info)
13287 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13288 &draw_info->fill,exception);
13289 break;
13290 }
13291 if (LocaleCompare(attribute,"font") == 0)
13292 {
13293 CloneString(&draw_info->font,SvPV(ST(i),na));
13294 break;
13295 }
13296 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13297 attribute);
13298 break;
13299 }
13300 case 'g':
13301 case 'G':
13302 {
13303 if (LocaleCompare(attribute,"geometry") == 0)
13304 {
13305 CloneString(&draw_info->geometry,SvPV(ST(i),na));
13306 break;
13307 }
13308 if (LocaleCompare(attribute,"gravity") == 0)
13309 {
13310 draw_info->gravity=(GravityType) ParseCommandOption(
13311 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13312 break;
13313 }
13314 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13315 attribute);
13316 break;
13317 }
13318 case 'p':
13319 case 'P':
13320 {
13321 if (LocaleCompare(attribute,"pointsize") == 0)
13322 {
13323 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13324 draw_info->pointsize=geometry_info.rho;
13325 break;
13326 }
13327 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13328 attribute);
13329 break;
13330 }
13331 case 'r':
13332 case 'R':
13333 {
13334 if (LocaleCompare(attribute,"rotate") == 0)
13335 {
13336 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13337 affine.rx=geometry_info.rho;
13338 affine.ry=geometry_info.sigma;
13339 if ((flags & SigmaValue) == 0)
13340 affine.ry=affine.rx;
13341 break;
13342 }
13343 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13344 attribute);
13345 break;
13346 }
13347 case 's':
13348 case 'S':
13349 {
13350 if (LocaleCompare(attribute,"scale") == 0)
13351 {
13352 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13353 affine.sx=geometry_info.rho;
13354 affine.sy=geometry_info.sigma;
13355 if ((flags & SigmaValue) == 0)
13356 affine.sy=affine.sx;
13357 break;
13358 }
13359 if (LocaleCompare(attribute,"skew") == 0)
13360 {
13361 double
13362 x_angle,
13363 y_angle;
13364
13365 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13366 x_angle=geometry_info.rho;
13367 y_angle=geometry_info.sigma;
13368 if ((flags & SigmaValue) == 0)
13369 y_angle=x_angle;
13370 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13371 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13372 break;
13373 }
13374 if (LocaleCompare(attribute,"stroke") == 0)
13375 {
13376 if (info)
13377 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13378 &draw_info->stroke,exception);
13379 break;
13380 }
13381 if (LocaleCompare(attribute,"style") == 0)
13382 {
13383 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13384 SvPV(ST(i),na));
13385 if (type < 0)
13386 {
13387 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13388 SvPV(ST(i),na));
13389 break;
13390 }
13391 draw_info->style=(StyleType) type;
13392 break;
13393 }
13394 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13395 attribute);
13396 break;
13397 }
13398 case 't':
13399 case 'T':
13400 {
13401 if (LocaleCompare(attribute,"text") == 0)
13402 {
13403 CloneString(&draw_info->text,SvPV(ST(i),na));
13404 break;
13405 }
13406 if (LocaleCompare(attribute,"translate") == 0)
13407 {
13408 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13409 affine.tx=geometry_info.rho;
13410 affine.ty=geometry_info.sigma;
13411 if ((flags & SigmaValue) == 0)
13412 affine.ty=affine.tx;
13413 break;
13414 }
13415 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13416 attribute);
13417 break;
13418 }
13419 case 'w':
13420 case 'W':
13421 {
13422 if (LocaleCompare(attribute,"weight") == 0)
13423 {
13424 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13425 draw_info->weight=(size_t) geometry_info.rho;
13426 break;
13427 }
13428 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13429 attribute);
13430 break;
13431 }
13432 case 'x':
13433 case 'X':
13434 {
13435 if (LocaleCompare(attribute,"x") == 0)
13436 {
13437 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13438 x=geometry_info.rho;
13439 break;
13440 }
13441 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13442 attribute);
13443 break;
13444 }
13445 case 'y':
13446 case 'Y':
13447 {
13448 if (LocaleCompare(attribute,"y") == 0)
13449 {
13450 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13451 y=geometry_info.rho;
13452 break;
13453 }
13454 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13455 attribute);
13456 break;
13457 }
13458 default:
13459 {
13460 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13461 attribute);
13462 break;
13463 }
13464 }
13465 }
13466 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13467 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13468 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13469 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13470 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13471 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13472 if (draw_info->geometry == (char *) NULL)
13473 {
13474 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013475 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013476 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013477 }
13478 status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13479 (void) CatchException(exception);
13480 if (status == MagickFalse)
13481 PUSHs(&sv_undef);
13482 else
13483 {
13484 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13485 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13486 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13487 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13488 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13489 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13490 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13491 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13492 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13493 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13494 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13495 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13496 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13497 }
13498 draw_info=DestroyDrawInfo(draw_info);
13499
13500 PerlException:
13501 if (package_info != (struct PackageInfo *) NULL)
13502 DestroyPackageInfo(package_info);
13503 InheritPerlException(exception,perl_exception);
13504 exception=DestroyExceptionInfo(exception);
13505 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13506 }
13507
13508#
13509###############################################################################
13510# #
13511# #
13512# #
13513# Q u e r y F o r m a t #
13514# #
13515# #
13516# #
13517###############################################################################
13518#
13519#
13520void
13521QueryFormat(ref,...)
13522 Image::Magick ref=NO_INIT
13523 ALIAS:
13524 queryformat = 1
13525 PPCODE:
13526 {
13527 char
13528 *name;
13529
13530 ExceptionInfo
13531 *exception;
13532
13533 register ssize_t
13534 i;
13535
13536 SV
13537 *perl_exception;
13538
13539 volatile const MagickInfo
13540 *magick_info;
13541
13542 PERL_UNUSED_VAR(ref);
13543 PERL_UNUSED_VAR(ix);
13544 exception=AcquireExceptionInfo();
13545 perl_exception=newSVpv("",0);
13546 if (items == 1)
13547 {
13548 char
cristy151b66d2015-04-15 10:50:31 +000013549 format[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000013550
13551 const MagickInfo
13552 **format_list;
13553
13554 size_t
13555 types;
13556
13557 format_list=GetMagickInfoList("*",&types,exception);
13558 EXTEND(sp,types);
13559 for (i=0; i < (ssize_t) types; i++)
13560 {
cristy151b66d2015-04-15 10:50:31 +000013561 (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000013562 LocaleLower(format);
13563 PUSHs(sv_2mortal(newSVpv(format,0)));
13564 }
13565 format_list=(const MagickInfo **)
13566 RelinquishMagickMemory((MagickInfo *) format_list);
13567 goto PerlException;
13568 }
13569 EXTEND(sp,8*items);
13570 for (i=1; i < items; i++)
13571 {
13572 name=(char *) SvPV(ST(i),na);
13573 magick_info=GetMagickInfo(name,exception);
13574 if (magick_info == (const MagickInfo *) NULL)
13575 {
13576 PUSHs(&sv_undef);
13577 continue;
13578 }
cristy4a3ce0a2013-08-03 20:06:59 +000013579 if (magick_info->description == (char *) NULL)
13580 PUSHs(&sv_undef);
13581 else
13582 PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13583 if (magick_info->module == (char *) NULL)
13584 PUSHs(&sv_undef);
13585 else
13586 PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13587 }
13588
13589 PerlException:
13590 InheritPerlException(exception,perl_exception);
13591 exception=DestroyExceptionInfo(exception);
13592 SvREFCNT_dec(perl_exception);
13593 }
13594
13595#
13596###############################################################################
13597# #
13598# #
13599# #
13600# Q u e r y O p t i o n #
13601# #
13602# #
13603# #
13604###############################################################################
13605#
13606#
13607void
13608QueryOption(ref,...)
13609 Image::Magick ref=NO_INIT
13610 ALIAS:
13611 queryoption = 1
13612 PPCODE:
13613 {
13614 char
13615 **options;
13616
13617 ExceptionInfo
13618 *exception;
13619
13620 register ssize_t
13621 i;
13622
13623 ssize_t
13624 j,
13625 option;
13626
13627 SV
13628 *perl_exception;
13629
13630 PERL_UNUSED_VAR(ref);
13631 PERL_UNUSED_VAR(ix);
13632 exception=AcquireExceptionInfo();
13633 perl_exception=newSVpv("",0);
13634 EXTEND(sp,8*items);
13635 for (i=1; i < items; i++)
13636 {
13637 option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13638 SvPV(ST(i),na));
13639 options=GetCommandOptions((CommandOption) option);
13640 if (options == (char **) NULL)
13641 PUSHs(&sv_undef);
13642 else
13643 {
13644 for (j=0; options[j] != (char *) NULL; j++)
13645 PUSHs(sv_2mortal(newSVpv(options[j],0)));
13646 options=DestroyStringList(options);
13647 }
13648 }
13649
13650 InheritPerlException(exception,perl_exception);
13651 exception=DestroyExceptionInfo(exception);
13652 SvREFCNT_dec(perl_exception);
13653 }
13654
13655#
13656###############################################################################
13657# #
13658# #
13659# #
13660# R e a d #
13661# #
13662# #
13663# #
13664###############################################################################
13665#
13666#
13667void
13668Read(ref,...)
13669 Image::Magick ref=NO_INIT
13670 ALIAS:
13671 ReadImage = 1
13672 read = 2
13673 readimage = 3
13674 PPCODE:
13675 {
13676 AV
13677 *av;
13678
13679 char
13680 **keep,
13681 **list;
13682
13683 ExceptionInfo
13684 *exception;
13685
13686 HV
13687 *hv;
13688
13689 Image
13690 *image;
13691
13692 int
13693 n;
13694
13695 MagickBooleanType
13696 status;
13697
13698 register char
13699 **p;
13700
13701 register ssize_t
13702 i;
13703
13704 ssize_t
13705 ac,
13706 number_images;
13707
13708 STRLEN
13709 *length;
13710
13711 struct PackageInfo
13712 *info,
13713 *package_info;
13714
13715 SV
13716 *perl_exception, /* Perl variable for storing messages */
13717 *reference,
13718 *rv,
13719 *sv;
13720
13721 PERL_UNUSED_VAR(ref);
13722 PERL_UNUSED_VAR(ix);
13723 exception=AcquireExceptionInfo();
13724 perl_exception=newSVpv("",0);
13725 sv=NULL;
13726 package_info=(struct PackageInfo *) NULL;
13727 number_images=0;
13728 ac=(items < 2) ? 1 : items-1;
13729 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13730 keep=list;
13731 length=(STRLEN *) NULL;
13732 if (list == (char **) NULL)
13733 {
13734 ThrowPerlException(exception,ResourceLimitError,
13735 "MemoryAllocationFailed",PackageName);
13736 goto PerlException;
13737 }
13738 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13739 if (length == (STRLEN *) NULL)
13740 {
13741 ThrowPerlException(exception,ResourceLimitError,
13742 "MemoryAllocationFailed",PackageName);
13743 goto PerlException;
13744 }
13745 if (sv_isobject(ST(0)) == 0)
13746 {
13747 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13748 PackageName);
13749 goto PerlException;
13750 }
13751 reference=SvRV(ST(0));
13752 hv=SvSTASH(reference);
13753 if (SvTYPE(reference) != SVt_PVAV)
13754 {
13755 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13756 PackageName);
13757 goto PerlException;
13758 }
13759 av=(AV *) reference;
13760 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13761 exception);
13762 package_info=ClonePackageInfo(info,exception);
13763 n=1;
13764 if (items <= 1)
13765 *list=(char *) (*package_info->image_info->filename ?
13766 package_info->image_info->filename : "XC:black");
13767 else
13768 for (n=0, i=0; i < ac; i++)
13769 {
13770 list[n]=(char *) SvPV(ST(i+1),length[n]);
13771 if ((items >= 3) && strEQcase(list[n],"blob"))
13772 {
13773 void
13774 *blob;
13775
13776 i++;
13777 blob=(void *) (SvPV(ST(i+1),length[n]));
13778 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13779 }
13780 if ((items >= 3) && strEQcase(list[n],"filename"))
13781 continue;
13782 if ((items >= 3) && strEQcase(list[n],"file"))
13783 {
13784 FILE
13785 *file;
13786
13787 PerlIO
13788 *io_info;
13789
13790 i++;
13791 io_info=IoIFP(sv_2io(ST(i+1)));
13792 if (io_info == (PerlIO *) NULL)
13793 {
13794 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13795 PackageName);
13796 continue;
13797 }
13798 file=PerlIO_findFILE(io_info);
13799 if (file == (FILE *) NULL)
13800 {
13801 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13802 PackageName);
13803 continue;
13804 }
13805 SetImageInfoFile(package_info->image_info,file);
13806 }
13807 if ((items >= 3) && strEQcase(list[n],"magick"))
13808 continue;
13809 n++;
13810 }
13811 list[n]=(char *) NULL;
13812 keep=list;
13813 status=ExpandFilenames(&n,&list);
13814 if (status == MagickFalse)
13815 {
13816 ThrowPerlException(exception,ResourceLimitError,
13817 "MemoryAllocationFailed",PackageName);
13818 goto PerlException;
13819 }
13820 number_images=0;
13821 for (i=0; i < n; i++)
13822 {
13823 if ((package_info->image_info->file == (FILE *) NULL) &&
13824 (package_info->image_info->blob == (void *) NULL))
13825 image=ReadImages(package_info->image_info,list[i],exception);
13826 else
13827 {
13828 image=ReadImages(package_info->image_info,
13829 package_info->image_info->filename,exception);
13830 if (image != (Image *) NULL)
13831 DisassociateImageStream(image);
13832 }
13833 if (image == (Image *) NULL)
13834 break;
13835 for ( ; image; image=image->next)
13836 {
13837 AddImageToRegistry(sv,image);
13838 rv=newRV(sv);
13839 av_push(av,sv_bless(rv,hv));
13840 SvREFCNT_dec(sv);
13841 number_images++;
13842 }
13843 }
13844 /*
13845 Free resources.
13846 */
13847 for (i=0; i < n; i++)
13848 if (list[i] != (char *) NULL)
13849 for (p=keep; list[i] != *p++; )
13850 if (*p == (char *) NULL)
13851 {
13852 list[i]=(char *) RelinquishMagickMemory(list[i]);
13853 break;
13854 }
13855
13856 PerlException:
13857 if (package_info != (struct PackageInfo *) NULL)
13858 DestroyPackageInfo(package_info);
13859 if (list && (list != keep))
13860 list=(char **) RelinquishMagickMemory(list);
13861 if (keep)
13862 keep=(char **) RelinquishMagickMemory(keep);
13863 if (length)
13864 length=(STRLEN *) RelinquishMagickMemory(length);
13865 InheritPerlException(exception,perl_exception);
13866 exception=DestroyExceptionInfo(exception);
13867 sv_setiv(perl_exception,(IV) number_images);
13868 SvPOK_on(perl_exception);
13869 ST(0)=sv_2mortal(perl_exception);
13870 XSRETURN(1);
13871 }
13872
13873#
13874###############################################################################
13875# #
13876# #
13877# #
13878# R e m o t e #
13879# #
13880# #
13881# #
13882###############################################################################
13883#
13884#
13885void
13886Remote(ref,...)
13887 Image::Magick ref=NO_INIT
13888 ALIAS:
13889 RemoteCommand = 1
13890 remote = 2
13891 remoteCommand = 3
13892 PPCODE:
13893 {
13894 AV
13895 *av;
13896
13897 ExceptionInfo
13898 *exception;
13899
13900 register ssize_t
13901 i;
13902
13903 SV
13904 *perl_exception,
13905 *reference;
13906
13907 struct PackageInfo
13908 *info;
13909
13910 PERL_UNUSED_VAR(ref);
13911 PERL_UNUSED_VAR(ix);
13912 exception=AcquireExceptionInfo();
13913 perl_exception=newSVpv("",0);
13914 reference=SvRV(ST(0));
13915 av=(AV *) reference;
13916 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13917 exception);
13918 for (i=1; i < items; i++)
13919 (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13920 SvPV(ST(i),na),exception);
13921 InheritPerlException(exception,perl_exception);
13922 exception=DestroyExceptionInfo(exception);
13923 SvREFCNT_dec(perl_exception); /* throw away all errors */
13924 }
13925
13926#
13927###############################################################################
13928# #
13929# #
13930# #
13931# S e t #
13932# #
13933# #
13934# #
13935###############################################################################
13936#
13937#
13938void
13939Set(ref,...)
13940 Image::Magick ref=NO_INIT
13941 ALIAS:
13942 SetAttributes = 1
13943 SetAttribute = 2
13944 set = 3
13945 setattributes = 4
13946 setattribute = 5
13947 PPCODE:
13948 {
13949 ExceptionInfo
13950 *exception;
13951
13952 Image
13953 *image;
13954
13955 register ssize_t
13956 i;
13957
13958 struct PackageInfo
13959 *info;
13960
13961 SV
13962 *perl_exception,
13963 *reference; /* reference is the SV* of ref=SvIV(reference) */
13964
13965 PERL_UNUSED_VAR(ref);
13966 PERL_UNUSED_VAR(ix);
13967 exception=AcquireExceptionInfo();
13968 perl_exception=newSVpv("",0);
13969 if (sv_isobject(ST(0)) == 0)
13970 {
13971 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13972 PackageName);
13973 goto PerlException;
13974 }
13975 reference=SvRV(ST(0));
13976 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13977 if (items == 2)
13978 SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13979 else
13980 for (i=2; i < items; i+=2)
13981 SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13982
13983 PerlException:
13984 InheritPerlException(exception,perl_exception);
13985 exception=DestroyExceptionInfo(exception);
13986 sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13987 SvPOK_on(perl_exception);
13988 ST(0)=sv_2mortal(perl_exception);
13989 XSRETURN(1);
13990 }
13991
13992#
13993###############################################################################
13994# #
13995# #
13996# #
13997# S e t P i x e l #
13998# #
13999# #
14000# #
14001###############################################################################
14002#
14003#
14004void
14005SetPixel(ref,...)
14006 Image::Magick ref=NO_INIT
14007 ALIAS:
14008 setpixel = 1
14009 setPixel = 2
14010 PPCODE:
14011 {
14012 AV
14013 *av;
14014
14015 char
14016 *attribute;
14017
14018 ChannelType
14019 channel,
14020 channel_mask;
14021
14022 ExceptionInfo
14023 *exception;
14024
14025 Image
14026 *image;
14027
14028 MagickBooleanType
14029 normalize;
14030
14031 RectangleInfo
14032 region;
14033
14034 register ssize_t
14035 i;
14036
14037 register Quantum
14038 *q;
14039
14040 ssize_t
14041 option;
14042
14043 struct PackageInfo
14044 *info;
14045
14046 SV
14047 *perl_exception,
14048 *reference; /* reference is the SV* of ref=SvIV(reference) */
14049
14050 PERL_UNUSED_VAR(ref);
14051 PERL_UNUSED_VAR(ix);
14052 exception=AcquireExceptionInfo();
14053 perl_exception=newSVpv("",0);
14054 reference=SvRV(ST(0));
14055 av=(AV *) reference;
14056 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14057 exception);
14058 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14059 if (image == (Image *) NULL)
14060 {
14061 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14062 PackageName);
14063 goto PerlException;
14064 }
14065 av=(AV *) NULL;
14066 normalize=MagickTrue;
14067 region.x=0;
14068 region.y=0;
14069 region.width=image->columns;
14070 region.height=1;
14071 if (items == 1)
14072 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14073 channel=DefaultChannels;
14074 for (i=2; i < items; i+=2)
14075 {
14076 attribute=(char *) SvPV(ST(i-1),na);
14077 switch (*attribute)
14078 {
14079 case 'C':
14080 case 'c':
14081 {
14082 if (LocaleCompare(attribute,"channel") == 0)
14083 {
14084 ssize_t
14085 option;
14086
14087 option=ParseChannelOption(SvPV(ST(i),na));
14088 if (option < 0)
14089 {
14090 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14091 SvPV(ST(i),na));
14092 return;
14093 }
14094 channel=(ChannelType) option;
14095 break;
14096 }
14097 if (LocaleCompare(attribute,"color") == 0)
14098 {
14099 if (SvTYPE(ST(i)) != SVt_RV)
14100 {
14101 char
cristy151b66d2015-04-15 10:50:31 +000014102 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014103
cristy151b66d2015-04-15 10:50:31 +000014104 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +000014105 "invalid %.60s value",attribute);
14106 ThrowPerlException(exception,OptionError,message,
14107 SvPV(ST(i),na));
14108 }
14109 av=(AV *) SvRV(ST(i));
14110 break;
14111 }
14112 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14113 attribute);
14114 break;
14115 }
14116 case 'g':
14117 case 'G':
14118 {
14119 if (LocaleCompare(attribute,"geometry") == 0)
14120 {
14121 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14122 break;
14123 }
14124 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14125 attribute);
14126 break;
14127 }
14128 case 'N':
14129 case 'n':
14130 {
14131 if (LocaleCompare(attribute,"normalize") == 0)
14132 {
14133 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14134 SvPV(ST(i),na));
14135 if (option < 0)
14136 {
14137 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14138 SvPV(ST(i),na));
14139 break;
14140 }
14141 normalize=option != 0 ? MagickTrue : MagickFalse;
14142 break;
14143 }
14144 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14145 attribute);
14146 break;
14147 }
14148 case 'x':
14149 case 'X':
14150 {
14151 if (LocaleCompare(attribute,"x") == 0)
14152 {
14153 region.x=SvIV(ST(i));
14154 break;
14155 }
14156 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14157 attribute);
14158 break;
14159 }
14160 case 'y':
14161 case 'Y':
14162 {
14163 if (LocaleCompare(attribute,"y") == 0)
14164 {
14165 region.y=SvIV(ST(i));
14166 break;
14167 }
14168 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14169 attribute);
14170 break;
14171 }
14172 default:
14173 {
14174 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14175 attribute);
14176 break;
14177 }
14178 }
14179 }
14180 (void) SetImageStorageClass(image,DirectClass,exception);
14181 channel_mask=SetImageChannelMask(image,channel);
14182 q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14183 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14184 (SvTYPE(av) != SVt_PVAV))
14185 PUSHs(&sv_undef);
14186 else
14187 {
14188 double
14189 scale;
14190
14191 register ssize_t
14192 i;
14193
14194 i=0;
14195 scale=1.0;
14196 if (normalize != MagickFalse)
14197 scale=QuantumRange;
14198 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14199 (i <= av_len(av)))
14200 {
14201 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14202 av_fetch(av,i,0)))),q);
14203 i++;
14204 }
14205 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14206 (i <= av_len(av)))
14207 {
14208 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14209 av_fetch(av,i,0)))),q);
14210 i++;
14211 }
14212 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14213 (i <= av_len(av)))
14214 {
14215 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14216 av_fetch(av,i,0)))),q);
14217 i++;
14218 }
14219 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14220 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14221 {
14222 SetPixelBlack(image,ClampToQuantum(scale*
14223 SvNV(*(av_fetch(av,i,0)))),q);
14224 i++;
14225 }
14226 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14227 (i <= av_len(av)))
14228 {
14229 SetPixelAlpha(image,ClampToQuantum(scale*
14230 SvNV(*(av_fetch(av,i,0)))),q);
14231 i++;
14232 }
14233 (void) SyncAuthenticPixels(image,exception);
14234 }
14235 (void) SetImageChannelMask(image,channel_mask);
14236
14237 PerlException:
14238 InheritPerlException(exception,perl_exception);
14239 exception=DestroyExceptionInfo(exception);
14240 SvREFCNT_dec(perl_exception);
14241 }
14242
14243#
14244###############################################################################
14245# #
14246# #
14247# #
Cristybba545b2018-07-04 15:00:12 -040014248# S e t P i x e l s #
14249# #
14250# #
14251# #
14252###############################################################################
14253#
14254#
14255void
14256SetPixels(ref,...)
14257 Image::Magick ref=NO_INIT
14258 ALIAS:
14259 setpixels = 1
14260 setPixels = 2
14261 PPCODE:
14262 {
14263 AV
14264 *av;
14265
14266 char
14267 *attribute;
14268
14269 ChannelType
14270 channel,
14271 channel_mask;
14272
14273 ExceptionInfo
14274 *exception;
14275
14276 Image
14277 *image;
14278
14279 RectangleInfo
14280 region;
14281
14282 register ssize_t
14283 i;
14284
14285 register Quantum
14286 *q;
14287
14288 struct PackageInfo
14289 *info;
14290
14291 SV
14292 *perl_exception,
14293 *reference; /* reference is the SV* of ref=SvIV(reference) */
14294
14295 PERL_UNUSED_VAR(ref);
14296 PERL_UNUSED_VAR(ix);
14297 exception=AcquireExceptionInfo();
14298 perl_exception=newSVpv("",0);
14299 reference=SvRV(ST(0));
14300 av=(AV *) reference;
14301 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14302 exception);
14303 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14304 if (image == (Image *) NULL)
14305 {
14306 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14307 PackageName);
14308 goto PerlException;
14309 }
14310 av=(AV *) NULL;
14311 region.x=0;
14312 region.y=0;
14313 region.width=image->columns;
14314 region.height=1;
14315 if (items == 1)
14316 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14317 channel=DefaultChannels;
14318 for (i=2; i < items; i+=2)
14319 {
14320 attribute=(char *) SvPV(ST(i-1),na);
14321 switch (*attribute)
14322 {
14323 case 'C':
14324 case 'c':
14325 {
14326 if (LocaleCompare(attribute,"channel") == 0)
14327 {
14328 ssize_t
14329 option;
14330
14331 option=ParseChannelOption(SvPV(ST(i),na));
14332 if (option < 0)
14333 {
14334 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14335 SvPV(ST(i),na));
14336 return;
14337 }
14338 channel=(ChannelType) option;
14339 break;
14340 }
14341 if (LocaleCompare(attribute,"color") == 0)
14342 {
14343 if (SvTYPE(ST(i)) != SVt_RV)
14344 {
14345 char
14346 message[MagickPathExtent];
14347
14348 (void) FormatLocaleString(message,MagickPathExtent,
14349 "invalid %.60s value",attribute);
14350 ThrowPerlException(exception,OptionError,message,
14351 SvPV(ST(i),na));
14352 }
14353 av=(AV *) SvRV(ST(i));
14354 break;
14355 }
14356 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14357 attribute);
14358 break;
14359 }
14360 case 'g':
14361 case 'G':
14362 {
14363 if (LocaleCompare(attribute,"geometry") == 0)
14364 {
14365 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14366 break;
14367 }
14368 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14369 attribute);
14370 break;
14371 }
14372 case 'h':
14373 case 'H':
14374 {
14375 if (LocaleCompare(attribute,"height") == 0)
14376 {
14377 region.height=SvIV(ST(i));
14378 break;
14379 }
14380 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14381 attribute);
14382 break;
14383 }
14384 case 'w':
14385 case 'W':
14386 {
14387 if (LocaleCompare(attribute,"width") == 0)
14388 {
14389 region.width=SvIV(ST(i));
14390 break;
14391 }
14392 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14393 attribute);
14394 break;
14395 }
14396 case 'x':
14397 case 'X':
14398 {
14399 if (LocaleCompare(attribute,"x") == 0)
14400 {
14401 region.x=SvIV(ST(i));
14402 break;
14403 }
14404 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14405 attribute);
14406 break;
14407 }
14408 case 'y':
14409 case 'Y':
14410 {
14411 if (LocaleCompare(attribute,"y") == 0)
14412 {
14413 region.y=SvIV(ST(i));
14414 break;
14415 }
14416 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14417 attribute);
14418 break;
14419 }
14420 default:
14421 {
14422 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14423 attribute);
14424 break;
14425 }
14426 }
14427 }
14428 (void) SetImageStorageClass(image,DirectClass,exception);
14429 channel_mask=SetImageChannelMask(image,channel);
14430 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
14431 exception);
14432 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14433 (SvTYPE(av) != SVt_PVAV))
14434 PUSHs(&sv_undef);
14435 else
14436 {
14437 double
14438 scale;
14439
14440 register ssize_t
14441 i,
14442 n,
14443 number_pixels;
14444
14445 i=0;
14446 n=0;
14447 scale=(double) QuantumRange;
14448 number_pixels=region.width*region.height;
14449 while ((n < number_pixels) && (i < av_len(av)))
14450 {
14451 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14452 (i <= av_len(av)))
14453 {
14454 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14455 av_fetch(av,i,0)))),q);
14456 i++;
14457 }
14458 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14459 (i <= av_len(av)))
14460 {
14461 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14462 av_fetch(av,i,0)))),q);
14463 i++;
14464 }
14465 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14466 (i <= av_len(av)))
14467 {
14468 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14469 av_fetch(av,i,0)))),q);
14470 i++;
14471 }
14472 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14473 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14474 {
14475 SetPixelBlack(image,ClampToQuantum(scale*
14476 SvNV(*(av_fetch(av,i,0)))),q);
14477 i++;
14478 }
14479 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14480 (i <= av_len(av)))
14481 {
14482 SetPixelAlpha(image,ClampToQuantum(scale*
14483 SvNV(*(av_fetch(av,i,0)))),q);
14484 i++;
14485 }
14486 n++;
14487 q+=image->number_channels;
14488 }
14489 (void) SyncAuthenticPixels(image,exception);
14490 }
14491 (void) SetImageChannelMask(image,channel_mask);
14492
14493 PerlException:
14494 InheritPerlException(exception,perl_exception);
14495 exception=DestroyExceptionInfo(exception);
14496 SvREFCNT_dec(perl_exception);
14497 }
14498
14499#
14500###############################################################################
14501# #
14502# #
14503# #
cristy4a3ce0a2013-08-03 20:06:59 +000014504# S m u s h #
14505# #
14506# #
14507# #
14508###############################################################################
14509#
14510#
14511void
14512Smush(ref,...)
14513 Image::Magick ref=NO_INIT
14514 ALIAS:
14515 SmushImage = 1
14516 smush = 2
14517 smushimage = 3
14518 PPCODE:
14519 {
14520 AV
14521 *av;
14522
14523 char
14524 *attribute;
14525
14526 ExceptionInfo
14527 *exception;
14528
14529 HV
14530 *hv;
14531
14532 Image
14533 *image;
14534
14535 register ssize_t
14536 i;
14537
14538 ssize_t
14539 offset,
14540 stack;
14541
14542 struct PackageInfo
14543 *info;
14544
14545 SV
14546 *av_reference,
14547 *perl_exception,
14548 *reference,
14549 *rv,
14550 *sv;
14551
14552 PERL_UNUSED_VAR(ref);
14553 PERL_UNUSED_VAR(ix);
14554 exception=AcquireExceptionInfo();
14555 perl_exception=newSVpv("",0);
14556 sv=NULL;
14557 attribute=NULL;
14558 av=NULL;
14559 if (sv_isobject(ST(0)) == 0)
14560 {
14561 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14562 PackageName);
14563 goto PerlException;
14564 }
14565 reference=SvRV(ST(0));
14566 hv=SvSTASH(reference);
14567 av=newAV();
14568 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14569 SvREFCNT_dec(av);
14570 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14571 if (image == (Image *) NULL)
14572 {
14573 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14574 PackageName);
14575 goto PerlException;
14576 }
14577 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14578 /*
14579 Get options.
14580 */
14581 offset=0;
14582 stack=MagickTrue;
14583 for (i=2; i < items; i+=2)
14584 {
14585 attribute=(char *) SvPV(ST(i-1),na);
14586 switch (*attribute)
14587 {
14588 case 'O':
14589 case 'o':
14590 {
14591 if (LocaleCompare(attribute,"offset") == 0)
14592 {
14593 offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14594 break;
14595 }
14596 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14597 attribute);
14598 break;
14599 }
14600 case 'S':
14601 case 's':
14602 {
14603 if (LocaleCompare(attribute,"stack") == 0)
14604 {
14605 stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14606 SvPV(ST(i),na));
14607 if (stack < 0)
14608 {
14609 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14610 SvPV(ST(i),na));
14611 return;
14612 }
14613 break;
14614 }
14615 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14616 attribute);
14617 break;
14618 }
14619 default:
14620 {
14621 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14622 attribute);
14623 break;
14624 }
14625 }
14626 }
14627 image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14628 exception);
14629 if (image == (Image *) NULL)
14630 goto PerlException;
14631 for ( ; image; image=image->next)
14632 {
14633 AddImageToRegistry(sv,image);
14634 rv=newRV(sv);
14635 av_push(av,sv_bless(rv,hv));
14636 SvREFCNT_dec(sv);
14637 }
14638 exception=DestroyExceptionInfo(exception);
14639 ST(0)=av_reference;
14640 SvREFCNT_dec(perl_exception);
14641 XSRETURN(1);
14642
14643 PerlException:
14644 InheritPerlException(exception,perl_exception);
14645 exception=DestroyExceptionInfo(exception);
14646 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14647 SvPOK_on(perl_exception);
14648 ST(0)=sv_2mortal(perl_exception);
14649 XSRETURN(1);
14650 }
14651
14652#
14653###############################################################################
14654# #
14655# #
14656# #
14657# S t a t i s t i c s #
14658# #
14659# #
14660# #
14661###############################################################################
14662#
14663#
14664void
14665Statistics(ref,...)
14666 Image::Magick ref=NO_INIT
14667 ALIAS:
14668 StatisticsImage = 1
14669 statistics = 2
14670 statisticsimage = 3
14671 PPCODE:
14672 {
14673#define ChannelStatistics(channel) \
14674{ \
cristy151b66d2015-04-15 10:50:31 +000014675 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014676 (double) channel_statistics[channel].depth); \
14677 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014678 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014679 channel_statistics[channel].minima/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014680 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].maxima/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].mean/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].standard_deviation/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", \
cristy4a3ce0a2013-08-03 20:06:59 +000014691 channel_statistics[channel].kurtosis); \
14692 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].skewness); \
14695 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014696 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy275bdd92014-11-08 23:45:03 +000014697 channel_statistics[channel].entropy); \
14698 PUSHs(sv_2mortal(newSVpv(message,0))); \
cristy4a3ce0a2013-08-03 20:06:59 +000014699}
14700
14701 AV
14702 *av;
14703
14704 char
cristy151b66d2015-04-15 10:50:31 +000014705 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014706
14707 ChannelStatistics
14708 *channel_statistics;
14709
cristy4a3ce0a2013-08-03 20:06:59 +000014710 ExceptionInfo
14711 *exception;
14712
14713 Image
14714 *image;
14715
14716 ssize_t
14717 count;
14718
14719 struct PackageInfo
14720 *info;
14721
14722 SV
14723 *perl_exception,
14724 *reference;
14725
14726 PERL_UNUSED_VAR(ref);
14727 PERL_UNUSED_VAR(ix);
14728 exception=AcquireExceptionInfo();
14729 perl_exception=newSVpv("",0);
14730 av=NULL;
14731 if (sv_isobject(ST(0)) == 0)
14732 {
14733 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14734 PackageName);
14735 goto PerlException;
14736 }
14737 reference=SvRV(ST(0));
14738 av=newAV();
14739 SvREFCNT_dec(av);
14740 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14741 if (image == (Image *) NULL)
14742 {
14743 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14744 PackageName);
14745 goto PerlException;
14746 }
cristy4a3ce0a2013-08-03 20:06:59 +000014747 count=0;
14748 for ( ; image; image=image->next)
14749 {
Cristyb1710fe2017-02-11 13:51:48 -050014750 register size_t
14751 i;
14752
cristy4a3ce0a2013-08-03 20:06:59 +000014753 channel_statistics=GetImageStatistics(image,exception);
14754 if (channel_statistics == (ChannelStatistics *) NULL)
14755 continue;
14756 count++;
Cristyb1710fe2017-02-11 13:51:48 -050014757 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
14758 {
14759 PixelChannel channel=GetPixelChannelChannel(image,i);
14760 PixelTrait traits=GetPixelChannelTraits(image,channel);
Cristy5a854dc2017-02-11 15:43:46 -050014761 if (traits == UndefinedPixelTrait)
Cristyb1710fe2017-02-11 13:51:48 -050014762 continue;
Cristy5a854dc2017-02-11 15:43:46 -050014763 EXTEND(sp,8*(i+1)*count);
Cristyb1710fe2017-02-11 13:51:48 -050014764 ChannelStatistics(channel);
14765 }
Cristy25813902017-02-11 15:47:52 -050014766 EXTEND(sp,8*(i+1)*count);
14767 ChannelStatistics(CompositePixelChannel);
cristy4a3ce0a2013-08-03 20:06:59 +000014768 channel_statistics=(ChannelStatistics *)
14769 RelinquishMagickMemory(channel_statistics);
14770 }
14771
14772 PerlException:
14773 InheritPerlException(exception,perl_exception);
14774 exception=DestroyExceptionInfo(exception);
14775 SvREFCNT_dec(perl_exception);
14776 }
14777
14778#
14779###############################################################################
14780# #
14781# #
14782# #
14783# S y n c A u t h e n t i c P i x e l s #
14784# #
14785# #
14786# #
14787###############################################################################
14788#
14789#
14790void
14791SyncAuthenticPixels(ref,...)
14792 Image::Magick ref = NO_INIT
14793 ALIAS:
14794 Syncauthenticpixels = 1
14795 SyncImagePixels = 2
14796 syncimagepixels = 3
14797 CODE:
14798 {
14799 ExceptionInfo
14800 *exception;
14801
14802 Image
14803 *image;
14804
14805 MagickBooleanType
14806 status;
14807
14808 struct PackageInfo
14809 *info;
14810
14811 SV
14812 *perl_exception,
14813 *reference;
14814
14815 PERL_UNUSED_VAR(ref);
14816 PERL_UNUSED_VAR(ix);
14817 exception=AcquireExceptionInfo();
14818 perl_exception=newSVpv("",0);
14819 if (sv_isobject(ST(0)) == 0)
14820 {
14821 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14822 PackageName);
14823 goto PerlException;
14824 }
14825
14826 reference=SvRV(ST(0));
14827 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14828 if (image == (Image *) NULL)
14829 {
14830 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14831 PackageName);
14832 goto PerlException;
14833 }
14834
14835 status=SyncAuthenticPixels(image,exception);
14836 if (status != MagickFalse)
14837 return;
14838
14839 PerlException:
14840 InheritPerlException(exception,perl_exception);
14841 exception=DestroyExceptionInfo(exception);
14842 SvREFCNT_dec(perl_exception); /* throw away all errors */
14843 }
14844
14845#
14846###############################################################################
14847# #
14848# #
14849# #
cristy4a3ce0a2013-08-03 20:06:59 +000014850# W r i t e #
14851# #
14852# #
14853# #
14854###############################################################################
14855#
14856#
14857void
14858Write(ref,...)
14859 Image::Magick ref=NO_INIT
14860 ALIAS:
14861 WriteImage = 1
14862 write = 2
14863 writeimage = 3
14864 PPCODE:
14865 {
14866 char
cristy151b66d2015-04-15 10:50:31 +000014867 filename[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014868
14869 ExceptionInfo
14870 *exception;
14871
14872 Image
14873 *image,
14874 *next;
14875
14876 register ssize_t
14877 i;
14878
14879 ssize_t
14880 number_images,
14881 scene;
14882
14883 struct PackageInfo
14884 *info,
14885 *package_info;
14886
14887 SV
14888 *perl_exception,
14889 *reference;
14890
14891 PERL_UNUSED_VAR(ref);
14892 PERL_UNUSED_VAR(ix);
14893 exception=AcquireExceptionInfo();
14894 perl_exception=newSVpv("",0);
14895 number_images=0;
14896 package_info=(struct PackageInfo *) NULL;
14897 if (sv_isobject(ST(0)) == 0)
14898 {
14899 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14900 PackageName);
14901 goto PerlException;
14902 }
14903 reference=SvRV(ST(0));
14904 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14905 if (image == (Image *) NULL)
14906 {
14907 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14908 PackageName);
14909 goto PerlException;
14910 }
Cristyb4ee45c2017-09-27 17:58:55 -040014911 scene=0;
14912 for (next=image; next; next=next->next)
14913 next->scene=scene++;
cristy4a3ce0a2013-08-03 20:06:59 +000014914 package_info=ClonePackageInfo(info,exception);
14915 if (items == 2)
14916 SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14917 else
14918 if (items > 2)
14919 for (i=2; i < items; i+=2)
14920 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14921 exception);
14922 (void) CopyMagickString(filename,package_info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +000014923 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000014924 for (next=image; next; next=next->next)
cristy151b66d2015-04-15 10:50:31 +000014925 (void) CopyMagickString(next->filename,filename,MagickPathExtent);
cristy68bd79a2015-02-25 12:23:36 +000014926 *package_info->image_info->magick='\0';
cristy4a3ce0a2013-08-03 20:06:59 +000014927 SetImageInfo(package_info->image_info,(unsigned int)
14928 GetImageListLength(image),exception);
14929 for (next=image; next; next=next->next)
14930 {
14931 (void) WriteImage(package_info->image_info,next,exception);
14932 number_images++;
14933 if (package_info->image_info->adjoin)
14934 break;
14935 }
14936
14937 PerlException:
14938 if (package_info != (struct PackageInfo *) NULL)
14939 DestroyPackageInfo(package_info);
14940 InheritPerlException(exception,perl_exception);
14941 exception=DestroyExceptionInfo(exception);
14942 sv_setiv(perl_exception,(IV) number_images);
14943 SvPOK_on(perl_exception);
14944 ST(0)=sv_2mortal(perl_exception);
14945 XSRETURN(1);
14946 }