blob: fdb10a5fe909441fce7d6eb5e390e5c287507975 [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% %
Cristy0a176e12018-10-13 10:28:43 -040032% https://imagemagick.org/script/license.php %
cristy4a3ce0a2013-08-03 20:06:59 +000033% %
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},
Cristy9f252542018-11-21 19:13:46 -0500415 {"width", IntegerReference}, {"height", IntegerReference},
416 {"bias", RealReference} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000417 { "Resample", { {"density", StringReference}, {"x", RealReference},
418 {"y", RealReference}, {"filter", MagickFilterOptions},
419 {"support", RealReference } } },
420 { "Describe", { {"file", FileReference} } },
421 { "BlackThreshold", { {"threshold", StringReference},
422 {"channel", MagickChannelOptions} } },
423 { "WhiteThreshold", { {"threshold", StringReference},
424 {"channel", MagickChannelOptions} } },
cristy60c73c02014-03-25 12:09:58 +0000425 { "RotationalBlur", { {"geometry", StringReference},
426 {"angle", RealReference}, {"channel", MagickChannelOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000427 { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
428 {"height", IntegerReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500429 { "Strip", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000430 { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
431 { "Channel", { {"channel", MagickChannelOptions} } },
432 { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
433 {"height", IntegerReference}, {"x", IntegerReference},
434 {"y", IntegerReference}, {"fuzz", StringReference},
435 {"background", StringReference}, {"gravity", MagickGravityOptions} } },
436 { "Posterize", { {"levels", IntegerReference},
437 {"dither", MagickBooleanOptions} } },
438 { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
439 {"sigma", RealReference}, {"x", IntegerReference},
440 {"y", IntegerReference} } },
441 { "Identify", { {"file", FileReference}, {"features", StringReference},
442 {"unique", MagickBooleanOptions} } },
443 { "SepiaTone", { {"threshold", RealReference} } },
444 { "SigmoidalContrast", { {"geometry", StringReference},
445 {"contrast", RealReference}, {"mid-point", RealReference},
446 {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
447 { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
448 {"height", IntegerReference}, {"x", IntegerReference},
449 {"y", IntegerReference}, {"fuzz", StringReference},
450 {"background", StringReference}, {"gravity", MagickGravityOptions} } },
451 { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
452 {"sigma", RealReference}, {"x", IntegerReference},
453 {"y", IntegerReference}, {"background", StringReference} } },
454 { "ContrastStretch", { {"levels", StringReference},
455 {"black-point", RealReference},{"white-point", RealReference},
456 {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500457 { "Sans0", { { (const char *) NULL, NullReference } } },
458 { "Sans1", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000459 { "AdaptiveSharpen", { {"geometry", StringReference},
460 {"radius", RealReference}, {"sigma", RealReference},
461 {"bias", RealReference}, {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500462 { "Transpose", { { (const char *) NULL, NullReference } } },
463 { "Transverse", { { (const char *) NULL, NullReference } } },
464 { "AutoOrient", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000465 { "AdaptiveBlur", { {"geometry", StringReference},
466 {"radius", RealReference}, {"sigma", RealReference},
467 {"channel", MagickChannelOptions} } },
468 { "Sketch", { {"geometry", StringReference},
469 {"radius", RealReference}, {"sigma", RealReference},
470 {"angle", RealReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500471 { "UniqueColors", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000472 { "AdaptiveResize", { {"geometry", StringReference},
473 {"width", IntegerReference}, {"height", IntegerReference},
474 {"filter", MagickFilterOptions}, {"support", StringReference },
475 {"blur", RealReference } } },
476 { "ClipMask", { {"mask", ImageReference} } },
477 { "LinearStretch", { {"levels", StringReference},
478 {"black-point", RealReference},{"white-point", RealReference} } },
479 { "ColorMatrix", { {"matrix", ArrayReference} } },
480 { "Mask", { {"mask", ImageReference} } },
481 { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
482 {"font", StringReference}, {"stroke", StringReference},
483 {"fill", StringReference}, {"strokewidth", RealReference},
484 {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
485 {"background", StringReference},
486 {"interpolate", MagickInterpolateOptions} } },
487 { "FloodfillPaint", { {"geometry", StringReference},
488 {"x", IntegerReference}, {"y", IntegerReference},
489 {"fill", StringReference}, {"bordercolor", StringReference},
490 {"fuzz", StringReference}, {"channel", MagickChannelOptions},
491 {"invert", MagickBooleanOptions} } },
492 { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
493 {"virtual-pixel", MagickVirtualPixelOptions},
494 {"best-fit", MagickBooleanOptions} } },
495 { "Clut", { {"image", ImageReference},
496 {"interpolate", MagickInterpolateOptions},
497 {"channel", MagickChannelOptions} } },
498 { "LiquidRescale", { {"geometry", StringReference},
499 {"width", IntegerReference}, {"height", IntegerReference},
500 {"delta-x", RealReference}, {"rigidity", RealReference } } },
501 { "Encipher", { {"passphrase", StringReference} } },
502 { "Decipher", { {"passphrase", StringReference} } },
503 { "Deskew", { {"geometry", StringReference},
504 {"threshold", StringReference} } },
505 { "Remap", { {"image", ImageReference},
506 {"dither-method", MagickDitherOptions} } },
507 { "SparseColor", { {"points", ArrayReference},
508 {"method", MagickSparseColorOptions},
509 {"virtual-pixel", MagickVirtualPixelOptions},
510 {"channel", MagickChannelOptions} } },
511 { "Function", { {"parameters", ArrayReference},
512 {"function", MagickFunctionOptions},
513 {"virtual-pixel", MagickVirtualPixelOptions} } },
514 { "SelectiveBlur", { {"geometry", StringReference},
515 {"radius", RealReference}, {"sigma", RealReference},
516 {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
517 { "HaldClut", { {"image", ImageReference},
518 {"channel", MagickChannelOptions} } },
519 { "BlueShift", { {"factor", StringReference} } },
520 { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
521 { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
522 { "ColorDecisionList", {
523 {"color-correction-collection", StringReference} } },
524 { "AutoGamma", { {"channel", MagickChannelOptions} } },
525 { "AutoLevel", { {"channel", MagickChannelOptions} } },
526 { "LevelColors", { {"invert", MagickBooleanOptions},
527 {"black-point", StringReference}, {"white-point", StringReference},
528 {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
529 { "Clamp", { {"channel", MagickChannelOptions} } },
530 { "BrightnessContrast", { {"levels", StringReference},
531 {"brightness", RealReference},{"contrast", RealReference},
532 {"channel", MagickChannelOptions} } },
533 { "Morphology", { {"kernel", StringReference},
534 {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
535 {"iterations", IntegerReference} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000536 { "Mode", { {"geometry", StringReference},
537 {"width", IntegerReference},{"height", IntegerReference},
538 {"channel", MagickChannelOptions} } },
539 { "Statistic", { {"geometry", StringReference},
540 {"width", IntegerReference},{"height", IntegerReference},
541 {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
542 { "Perceptible", { {"epsilon", RealReference},
543 {"channel", MagickChannelOptions} } },
544 { "Poly", { {"terms", ArrayReference},
545 {"channel", MagickChannelOptions} } },
546 { "Grayscale", { {"method", MagickNoiseOptions} } },
cristy4ceadb82014-03-29 15:30:43 +0000547 { "CannyEdge", { {"geometry", StringReference},
548 {"radius", RealReference}, {"sigma", RealReference},
cristycfe7bf02014-04-04 15:31:52 +0000549 {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
cristy2fc10e52014-04-26 14:13:53 +0000550 { "HoughLine", { {"geometry", StringReference},
cristy4e215022014-04-19 18:02:35 +0000551 {"width", IntegerReference}, {"height", IntegerReference},
552 {"threshold", IntegerReference} } },
cristy2fc10e52014-04-26 14:13:53 +0000553 { "MeanShift", { {"geometry", StringReference},
554 {"width", IntegerReference}, {"height", IntegerReference},
cristy1309fc32014-04-26 18:48:37 +0000555 {"distance", RealReference} } },
cristy3b207f82014-09-27 14:21:20 +0000556 { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
557 {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
Cristy2ca0e9a2016-01-01 08:36:14 -0500558 { "ConnectedComponents", { {"connectivity", IntegerReference} } },
cristyf3a724a2015-06-25 13:02:53 +0000559 { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
560 {"width", IntegerReference}, {"height", IntegerReference},
561 {"x", IntegerReference}, {"y", IntegerReference},
Cristy532b3382018-08-05 17:56:56 -0400562 {"gravity", MagickGravityOptions}, {"offset", StringReference},
cristyf3a724a2015-06-25 13:02:53 +0000563 {"dx", IntegerReference}, {"dy", IntegerReference} } },
Cristy5488c982016-02-13 14:07:50 -0500564 { "Color", { {"color", StringReference} } },
Cristyc1759412016-02-27 12:17:58 -0500565 { "WaveletDenoise", { {"geometry", StringReference},
566 {"threshold", RealReference}, {"softness", RealReference},
Cristy2d830ed2016-02-21 10:54:16 -0500567 {"channel", MagickChannelOptions} } },
Cristy99a57162016-12-05 11:47:57 -0500568 { "Colorspace", { {"colorspace", MagickColorspaceOptions} } },
Cristy53353872017-07-02 12:24:24 -0400569 { "AutoThreshold", { {"method", MagickAutoThresholdOptions} } },
Cristy532b3382018-08-05 17:56:56 -0400570 { "RangeThreshold", { {"geometry", StringReference},
Cristy72f24752018-08-14 20:17:26 -0400571 {"low-black", RealReference}, {"low-white", RealReference},
572 {"high-white", RealReference}, {"high-black", RealReference},
Cristy532b3382018-08-05 17:56:56 -0400573 {"channel", MagickChannelOptions} } },
Cristy9f252542018-11-21 19:13:46 -0500574 { "CLAHE", { {"geometry", StringReference},
575 {"width", IntegerReference}, {"height", IntegerReference},
576 {"bias", RealReference}, {"sans", RealReference} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000577 };
578
579static SplayTreeInfo
580 *magick_registry = (SplayTreeInfo *) NULL;
581
582/*
583 Forward declarations.
584*/
585static Image
586 *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
587
588static ssize_t
589 strEQcase(const char *,const char *);
590
591/*
592%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593% %
594% %
595% %
596% C l o n e P a c k a g e I n f o %
597% %
598% %
599% %
600%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601%
602% ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
603% a new one.
604%
605% The format of the ClonePackageInfo routine is:
606%
607% struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
608% exception)
609%
610% A description of each parameter follows:
611%
612% o info: a structure of type info.
613%
614% o exception: Return any errors or warnings in this structure.
615%
616*/
617static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
618 ExceptionInfo *exception)
619{
620 struct PackageInfo
621 *clone_info;
622
623 clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
624 if (clone_info == (struct PackageInfo *) NULL)
625 {
626 ThrowPerlException(exception,ResourceLimitError,
627 "UnableToClonePackageInfo",PackageName);
628 return((struct PackageInfo *) NULL);
629 }
630 if (info == (struct PackageInfo *) NULL)
631 {
632 clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
633 return(clone_info);
634 }
635 *clone_info=(*info);
636 clone_info->image_info=CloneImageInfo(info->image_info);
637 return(clone_info);
638}
639
640/*
641%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
642% %
643% %
644% %
645% c o n s t a n t %
646% %
647% %
648% %
649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
650%
651% constant() returns a double value for the specified name.
652%
653% The format of the constant routine is:
654%
655% double constant(char *name,ssize_t sans)
656%
657% A description of each parameter follows:
658%
659% o value: Method constant returns a double value for the specified name.
660%
661% o name: The name of the constant.
662%
663% o sans: This integer value is not used.
664%
665*/
666static double constant(char *name,ssize_t sans)
667{
668 (void) sans;
669 errno=0;
670 switch (*name)
671 {
672 case 'B':
673 {
674 if (strEQ(name,"BlobError"))
675 return(BlobError);
676 if (strEQ(name,"BlobWarning"))
677 return(BlobWarning);
678 break;
679 }
680 case 'C':
681 {
682 if (strEQ(name,"CacheError"))
683 return(CacheError);
684 if (strEQ(name,"CacheWarning"))
685 return(CacheWarning);
686 if (strEQ(name,"CoderError"))
687 return(CoderError);
688 if (strEQ(name,"CoderWarning"))
689 return(CoderWarning);
690 if (strEQ(name,"ConfigureError"))
691 return(ConfigureError);
692 if (strEQ(name,"ConfigureWarning"))
693 return(ConfigureWarning);
694 if (strEQ(name,"CorruptImageError"))
695 return(CorruptImageError);
696 if (strEQ(name,"CorruptImageWarning"))
697 return(CorruptImageWarning);
698 break;
699 }
700 case 'D':
701 {
702 if (strEQ(name,"DelegateError"))
703 return(DelegateError);
704 if (strEQ(name,"DelegateWarning"))
705 return(DelegateWarning);
706 if (strEQ(name,"DrawError"))
707 return(DrawError);
708 if (strEQ(name,"DrawWarning"))
709 return(DrawWarning);
710 break;
711 }
712 case 'E':
713 {
714 if (strEQ(name,"ErrorException"))
715 return(ErrorException);
716 if (strEQ(name,"ExceptionError"))
717 return(CoderError);
718 if (strEQ(name,"ExceptionWarning"))
719 return(CoderWarning);
720 break;
721 }
722 case 'F':
723 {
724 if (strEQ(name,"FatalErrorException"))
725 return(FatalErrorException);
726 if (strEQ(name,"FileOpenError"))
727 return(FileOpenError);
728 if (strEQ(name,"FileOpenWarning"))
729 return(FileOpenWarning);
730 break;
731 }
732 case 'I':
733 {
734 if (strEQ(name,"ImageError"))
735 return(ImageError);
736 if (strEQ(name,"ImageWarning"))
737 return(ImageWarning);
738 break;
739 }
740 case 'M':
741 {
742 if (strEQ(name,"MaxRGB"))
743 return(QuantumRange);
744 if (strEQ(name,"MissingDelegateError"))
745 return(MissingDelegateError);
746 if (strEQ(name,"MissingDelegateWarning"))
747 return(MissingDelegateWarning);
748 if (strEQ(name,"ModuleError"))
749 return(ModuleError);
750 if (strEQ(name,"ModuleWarning"))
751 return(ModuleWarning);
752 break;
753 }
754 case 'O':
755 {
756 if (strEQ(name,"Opaque"))
757 return(OpaqueAlpha);
758 if (strEQ(name,"OptionError"))
759 return(OptionError);
760 if (strEQ(name,"OptionWarning"))
761 return(OptionWarning);
762 break;
763 }
764 case 'Q':
765 {
766 if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
767 return(MAGICKCORE_QUANTUM_DEPTH);
768 if (strEQ(name,"QuantumDepth"))
769 return(MAGICKCORE_QUANTUM_DEPTH);
770 if (strEQ(name,"QuantumRange"))
771 return(QuantumRange);
772 break;
773 }
774 case 'R':
775 {
776 if (strEQ(name,"ResourceLimitError"))
777 return(ResourceLimitError);
778 if (strEQ(name,"ResourceLimitWarning"))
779 return(ResourceLimitWarning);
780 if (strEQ(name,"RegistryError"))
781 return(RegistryError);
782 if (strEQ(name,"RegistryWarning"))
783 return(RegistryWarning);
784 break;
785 }
786 case 'S':
787 {
788 if (strEQ(name,"StreamError"))
789 return(StreamError);
790 if (strEQ(name,"StreamWarning"))
791 return(StreamWarning);
792 if (strEQ(name,"Success"))
793 return(0);
794 break;
795 }
796 case 'T':
797 {
798 if (strEQ(name,"Transparent"))
799 return(TransparentAlpha);
800 if (strEQ(name,"TypeError"))
801 return(TypeError);
802 if (strEQ(name,"TypeWarning"))
803 return(TypeWarning);
804 break;
805 }
806 case 'W':
807 {
808 if (strEQ(name,"WarningException"))
809 return(WarningException);
810 break;
811 }
812 case 'X':
813 {
814 if (strEQ(name,"XServerError"))
815 return(XServerError);
816 if (strEQ(name,"XServerWarning"))
817 return(XServerWarning);
818 break;
819 }
820 }
821 errno=EINVAL;
822 return(0);
823}
824
825/*
826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827% %
828% %
829% %
830% D e s t r o y P a c k a g e I n f o %
831% %
832% %
833% %
834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835%
836% Method DestroyPackageInfo frees a previously created info structure.
837%
838% The format of the DestroyPackageInfo routine is:
839%
840% DestroyPackageInfo(struct PackageInfo *info)
841%
842% A description of each parameter follows:
843%
844% o info: a structure of type info.
845%
846*/
847static void DestroyPackageInfo(struct PackageInfo *info)
848{
849 info->image_info=DestroyImageInfo(info->image_info);
850 info=(struct PackageInfo *) RelinquishMagickMemory(info);
851}
852
853/*
854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
855% %
856% %
857% %
858% G e t L i s t %
859% %
860% %
861% %
862%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
863%
864% Method GetList is recursively called by SetupList to traverse the
865% Image__Magick reference. If building an reference_vector (see SetupList),
866% *current is the current position in *reference_vector and *last is the final
867% entry in *reference_vector.
868%
869% The format of the GetList routine is:
870%
871% GetList(info)
872%
873% A description of each parameter follows:
874%
875% o info: a structure of type info.
876%
877*/
878static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
879 ssize_t *current,ssize_t *last,ExceptionInfo *exception)
880{
881 Image
882 *image;
883
884 if (reference == (SV *) NULL)
885 return(NULL);
886 switch (SvTYPE(reference))
887 {
888 case SVt_PVAV:
889 {
890 AV
891 *av;
892
893 Image
894 *head,
895 *previous;
896
897 register ssize_t
898 i;
899
900 ssize_t
901 n;
902
903 /*
904 Array of images.
905 */
906 previous=(Image *) NULL;
907 head=(Image *) NULL;
908 av=(AV *) reference;
909 n=av_len(av);
910 for (i=0; i <= n; i++)
911 {
912 SV
913 **rv;
914
915 rv=av_fetch(av,i,0);
916 if (rv && *rv && sv_isobject(*rv))
917 {
918 image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
919 exception);
920 if (image == (Image *) NULL)
921 continue;
922 if (image == previous)
923 {
924 image=CloneImage(image,0,0,MagickTrue,exception);
925 if (image == (Image *) NULL)
926 return(NULL);
927 }
928 image->previous=previous;
929 *(previous ? &previous->next : &head)=image;
930 for (previous=image; previous->next; previous=previous->next) ;
931 }
932 }
933 return(head);
934 }
935 case SVt_PVMG:
936 {
937 /*
938 Blessed scalar, one image.
939 */
940 image=INT2PTR(Image *,SvIV(reference));
941 if (image == (Image *) NULL)
942 return(NULL);
943 image->previous=(Image *) NULL;
944 image->next=(Image *) NULL;
945 if (reference_vector)
946 {
947 if (*current == *last)
948 {
949 *last+=256;
950 if (*reference_vector == (SV **) NULL)
951 *reference_vector=(SV **) AcquireQuantumMemory(*last,
952 sizeof(*reference_vector));
953 else
954 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
955 *last,sizeof(*reference_vector));
956 }
957 if (*reference_vector == (SV **) NULL)
958 {
959 ThrowPerlException(exception,ResourceLimitError,
960 "MemoryAllocationFailed",PackageName);
961 return((Image *) NULL);
962 }
963 (*reference_vector)[*current]=reference;
964 (*reference_vector)[++(*current)]=NULL;
965 }
966 return(image);
967 }
968 default:
969 break;
970 }
971 (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
972 (double) SvTYPE(reference));
973 return((Image *) NULL);
974}
975
976/*
977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978% %
979% %
980% %
981% G e t P a c k a g e I n f o %
982% %
983% %
984% %
985%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
986%
987% Method GetPackageInfo looks up or creates an info structure for the given
988% Image__Magick reference. If it does create a new one, the information in
989% package_info is used to initialize it.
990%
991% The format of the GetPackageInfo routine is:
992%
993% struct PackageInfo *GetPackageInfo(void *reference,
994% struct PackageInfo *package_info,ExceptionInfo *exception)
995%
996% A description of each parameter follows:
997%
998% o info: a structure of type info.
999%
1000% o exception: Return any errors or warnings in this structure.
1001%
1002*/
1003static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
1004 struct PackageInfo *package_info,ExceptionInfo *exception)
1005{
1006 char
cristy151b66d2015-04-15 10:50:31 +00001007 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00001008
1009 struct PackageInfo
1010 *clone_info;
1011
1012 SV
1013 *sv;
1014
cristy151b66d2015-04-15 10:50:31 +00001015 (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
cristy4a3ce0a2013-08-03 20:06:59 +00001016 PackageName,XS_VERSION,reference);
1017 sv=perl_get_sv(message,(TRUE | 0x02));
1018 if (sv == (SV *) NULL)
1019 {
1020 ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1021 message);
1022 return(package_info);
1023 }
1024 if (SvREFCNT(sv) == 0)
1025 (void) SvREFCNT_inc(sv);
1026 if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1027 return(clone_info);
1028 clone_info=ClonePackageInfo(package_info,exception);
1029 sv_setiv(sv,PTR2IV(clone_info));
1030 return(clone_info);
1031}
1032
1033/*
1034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1035% %
1036% %
1037% %
1038% S e t A t t r i b u t e %
1039% %
1040% %
1041% %
1042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1043%
1044% SetAttribute() sets the attribute to the value in sval. This can change
1045% either or both of image or info.
1046%
1047% The format of the SetAttribute routine is:
1048%
1049% SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1050% SV *sval,ExceptionInfo *exception)
1051%
1052% A description of each parameter follows:
1053%
1054% o list: a list of strings.
1055%
1056% o string: a character string.
1057%
1058*/
1059
1060static double SiPrefixToDoubleInterval(const char *string,const double interval)
1061{
1062 char
1063 *q;
1064
1065 double
1066 value;
1067
1068 value=InterpretSiPrefixValue(string,&q);
1069 if (*q == '%')
1070 value*=interval/100.0;
1071 return(value);
1072}
1073
1074static inline double StringToDouble(const char *string,char **sentinal)
1075{
1076 return(InterpretLocaleValue(string,sentinal));
1077}
1078
1079static double StringToDoubleInterval(const char *string,const double interval)
1080{
1081 char
1082 *q;
1083
1084 double
1085 value;
1086
1087 value=InterpretLocaleValue(string,&q);
1088 if (*q == '%')
1089 value*=interval/100.0;
1090 return(value);
1091}
1092
1093static inline ssize_t StringToLong(const char *value)
1094{
1095 return(strtol(value,(char **) NULL,10));
1096}
1097
1098static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1099 const char *attribute,SV *sval,ExceptionInfo *exception)
1100{
1101 GeometryInfo
1102 geometry_info;
1103
1104 long
1105 x,
1106 y;
1107
1108 PixelInfo
1109 pixel;
1110
1111 MagickStatusType
1112 flags;
1113
1114 PixelInfo
1115 *color,
1116 target_color;
1117
1118 ssize_t
1119 sp;
1120
1121 switch (*attribute)
1122 {
1123 case 'A':
1124 case 'a':
1125 {
1126 if (LocaleCompare(attribute,"adjoin") == 0)
1127 {
1128 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1129 SvPV(sval,na)) : SvIV(sval);
1130 if (sp < 0)
1131 {
1132 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1133 SvPV(sval,na));
1134 break;
1135 }
1136 if (info)
1137 info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1138 break;
1139 }
1140 if (LocaleCompare(attribute,"alpha") == 0)
1141 {
1142 sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1143 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1144 if (sp < 0)
1145 {
1146 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1147 SvPV(sval,na));
1148 break;
1149 }
1150 for ( ; image; image=image->next)
1151 (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1152 exception);
1153 break;
1154 }
1155 if (LocaleCompare(attribute,"antialias") == 0)
1156 {
1157 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1158 SvPV(sval,na)) : SvIV(sval);
1159 if (sp < 0)
1160 {
1161 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1162 SvPV(sval,na));
1163 break;
1164 }
1165 if (info)
1166 info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1167 break;
1168 }
1169 if (LocaleCompare(attribute,"area-limit") == 0)
1170 {
1171 MagickSizeType
1172 limit;
1173
1174 limit=MagickResourceInfinity;
1175 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1176 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1177 100.0);
1178 (void) SetMagickResourceLimit(AreaResource,limit);
1179 break;
1180 }
1181 if (LocaleCompare(attribute,"attenuate") == 0)
1182 {
1183 if (info)
1184 (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1185 break;
1186 }
1187 if (LocaleCompare(attribute,"authenticate") == 0)
1188 {
1189 if (info)
1190 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1191 break;
1192 }
1193 if (info)
1194 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1195 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001196 {
1197 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstra337c9bc2017-04-03 16:04:21 +02001198 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001199 }
cristy4a3ce0a2013-08-03 20:06:59 +00001200 break;
1201 }
1202 case 'B':
1203 case 'b':
1204 {
1205 if (LocaleCompare(attribute,"background") == 0)
1206 {
1207 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1208 exception);
1209 if (info)
1210 info->image_info->background_color=target_color;
1211 for ( ; image; image=image->next)
1212 image->background_color=target_color;
1213 break;
1214 }
1215 if (LocaleCompare(attribute,"blue-primary") == 0)
1216 {
1217 for ( ; image; image=image->next)
1218 {
1219 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1220 image->chromaticity.blue_primary.x=geometry_info.rho;
1221 image->chromaticity.blue_primary.y=geometry_info.sigma;
1222 if ((flags & SigmaValue) == 0)
1223 image->chromaticity.blue_primary.y=
1224 image->chromaticity.blue_primary.x;
1225 }
1226 break;
1227 }
1228 if (LocaleCompare(attribute,"bordercolor") == 0)
1229 {
1230 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1231 exception);
1232 if (info)
1233 info->image_info->border_color=target_color;
1234 for ( ; image; image=image->next)
1235 image->border_color=target_color;
1236 break;
1237 }
1238 if (info)
1239 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1240 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001241 {
1242 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001243 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001244 }
cristy4a3ce0a2013-08-03 20:06:59 +00001245 break;
1246 }
1247 case 'C':
1248 case 'c':
1249 {
1250 if (LocaleCompare(attribute,"cache-threshold") == 0)
1251 {
1252 (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1253 SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1254 (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1255 (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1256 break;
1257 }
1258 if (LocaleCompare(attribute,"clip-mask") == 0)
1259 {
1260 Image
1261 *clip_mask;
1262
1263 clip_mask=(Image *) NULL;
1264 if (SvPOK(sval))
1265 clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1266 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001267 SetImageMask(image,ReadPixelMask,clip_mask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001268 break;
1269 }
1270 if (LocaleNCompare(attribute,"colormap",8) == 0)
1271 {
1272 for ( ; image; image=image->next)
1273 {
1274 int
1275 items;
1276
1277 long
1278 i;
1279
1280 if (image->storage_class == DirectClass)
1281 continue;
1282 i=0;
1283 items=sscanf(attribute,"%*[^[][%ld",&i);
1284 (void) items;
1285 if (i > (ssize_t) image->colors)
1286 i%=image->colors;
1287 if ((strchr(SvPV(sval,na),',') == 0) ||
1288 (strchr(SvPV(sval,na),')') != 0))
1289 QueryColorCompliance(SvPV(sval,na),AllCompliance,
1290 image->colormap+i,exception);
1291 else
1292 {
1293 color=image->colormap+i;
1294 pixel.red=color->red;
1295 pixel.green=color->green;
1296 pixel.blue=color->blue;
1297 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1298 pixel.red=geometry_info.rho;
1299 pixel.green=geometry_info.sigma;
1300 pixel.blue=geometry_info.xi;
1301 color->red=ClampToQuantum(pixel.red);
1302 color->green=ClampToQuantum(pixel.green);
1303 color->blue=ClampToQuantum(pixel.blue);
1304 }
1305 }
1306 break;
1307 }
1308 if (LocaleCompare(attribute,"colorspace") == 0)
1309 {
1310 sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1311 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1312 if (sp < 0)
1313 {
1314 ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1315 SvPV(sval,na));
1316 break;
1317 }
1318 for ( ; image; image=image->next)
Cristy59262d92016-12-05 15:21:50 -05001319 (void) SetImageColorspace(image,(ColorspaceType) sp,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001320 break;
1321 }
1322 if (LocaleCompare(attribute,"comment") == 0)
1323 {
1324 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001325 (void) SetImageProperty(image,"Comment",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00001326 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04001327 SvPV(sval,na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001328 break;
1329 }
1330 if (LocaleCompare(attribute,"compression") == 0)
1331 {
1332 sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1333 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1334 if (sp < 0)
1335 {
1336 ThrowPerlException(exception,OptionError,
1337 "UnrecognizedImageCompression",SvPV(sval,na));
1338 break;
1339 }
1340 if (info)
1341 info->image_info->compression=(CompressionType) sp;
1342 for ( ; image; image=image->next)
1343 image->compression=(CompressionType) sp;
1344 break;
1345 }
1346 if (info)
1347 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1348 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001349 {
1350 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001351 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001352 }
cristy4a3ce0a2013-08-03 20:06:59 +00001353 break;
1354 }
1355 case 'D':
1356 case 'd':
1357 {
1358 if (LocaleCompare(attribute,"debug") == 0)
1359 {
1360 SetLogEventMask(SvPV(sval,na));
1361 break;
1362 }
1363 if (LocaleCompare(attribute,"delay") == 0)
1364 {
1365 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1366 for ( ; image; image=image->next)
1367 {
1368 image->delay=(size_t) floor(geometry_info.rho+0.5);
1369 if ((flags & SigmaValue) != 0)
1370 image->ticks_per_second=(ssize_t)
1371 floor(geometry_info.sigma+0.5);
1372 }
1373 break;
1374 }
1375 if (LocaleCompare(attribute,"disk-limit") == 0)
1376 {
1377 MagickSizeType
1378 limit;
1379
1380 limit=MagickResourceInfinity;
1381 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1382 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1383 100.0);
1384 (void) SetMagickResourceLimit(DiskResource,limit);
1385 break;
1386 }
1387 if (LocaleCompare(attribute,"density") == 0)
1388 {
1389 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1390 {
1391 ThrowPerlException(exception,OptionError,"MissingGeometry",
1392 SvPV(sval,na));
1393 break;
1394 }
1395 if (info)
1396 (void) CloneString(&info->image_info->density,SvPV(sval,na));
1397 for ( ; image; image=image->next)
1398 {
1399 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1400 image->resolution.x=geometry_info.rho;
1401 image->resolution.y=geometry_info.sigma;
1402 if ((flags & SigmaValue) == 0)
1403 image->resolution.y=image->resolution.x;
1404 }
1405 break;
1406 }
1407 if (LocaleCompare(attribute,"depth") == 0)
1408 {
1409 if (info)
1410 info->image_info->depth=SvIV(sval);
1411 for ( ; image; image=image->next)
1412 (void) SetImageDepth(image,SvIV(sval),exception);
1413 break;
1414 }
1415 if (LocaleCompare(attribute,"dispose") == 0)
1416 {
1417 sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1418 SvPV(sval,na)) : SvIV(sval);
1419 if (sp < 0)
1420 {
1421 ThrowPerlException(exception,OptionError,
1422 "UnrecognizedDisposeMethod",SvPV(sval,na));
1423 break;
1424 }
1425 for ( ; image; image=image->next)
1426 image->dispose=(DisposeType) sp;
1427 break;
1428 }
1429 if (LocaleCompare(attribute,"dither") == 0)
1430 {
1431 if (info)
1432 {
1433 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1434 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1435 if (sp < 0)
1436 {
1437 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1438 SvPV(sval,na));
1439 break;
1440 }
1441 info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1442 }
1443 break;
1444 }
1445 if (LocaleCompare(attribute,"display") == 0)
1446 {
1447 display:
1448 if (info)
1449 (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1450 break;
1451 }
1452 if (info)
1453 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1454 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001455 {
1456 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001457 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001458 }
cristy4a3ce0a2013-08-03 20:06:59 +00001459 break;
1460 }
1461 case 'E':
1462 case 'e':
1463 {
1464 if (LocaleCompare(attribute,"endian") == 0)
1465 {
1466 sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1467 SvPV(sval,na)) : SvIV(sval);
1468 if (sp < 0)
1469 {
1470 ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1471 SvPV(sval,na));
1472 break;
1473 }
1474 if (info)
1475 info->image_info->endian=(EndianType) sp;
1476 for ( ; image; image=image->next)
1477 image->endian=(EndianType) sp;
1478 break;
1479 }
1480 if (LocaleCompare(attribute,"extract") == 0)
1481 {
1482 /*
1483 Set image extract geometry.
1484 */
1485 (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1486 break;
1487 }
1488 if (info)
1489 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1490 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001491 {
1492 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001493 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001494 }
cristy4a3ce0a2013-08-03 20:06:59 +00001495 break;
1496 }
1497 case 'F':
1498 case 'f':
1499 {
1500 if (LocaleCompare(attribute,"filename") == 0)
1501 {
1502 if (info)
1503 (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
cristy151b66d2015-04-15 10:50:31 +00001504 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001505 for ( ; image; image=image->next)
1506 (void) CopyMagickString(image->filename,SvPV(sval,na),
cristy151b66d2015-04-15 10:50:31 +00001507 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001508 break;
1509 }
1510 if (LocaleCompare(attribute,"file") == 0)
1511 {
1512 FILE
1513 *file;
1514
1515 PerlIO
1516 *io_info;
1517
1518 if (info == (struct PackageInfo *) NULL)
1519 break;
1520 io_info=IoIFP(sv_2io(sval));
1521 if (io_info == (PerlIO *) NULL)
1522 {
1523 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1524 PackageName);
1525 break;
1526 }
1527 file=PerlIO_findFILE(io_info);
1528 if (file == (FILE *) NULL)
1529 {
1530 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1531 PackageName);
1532 break;
1533 }
1534 SetImageInfoFile(info->image_info,file);
1535 break;
1536 }
1537 if (LocaleCompare(attribute,"fill") == 0)
1538 {
1539 if (info)
1540 (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1541 break;
1542 }
1543 if (LocaleCompare(attribute,"font") == 0)
1544 {
1545 if (info)
1546 (void) CloneString(&info->image_info->font,SvPV(sval,na));
1547 break;
1548 }
1549 if (LocaleCompare(attribute,"foreground") == 0)
1550 break;
1551 if (LocaleCompare(attribute,"fuzz") == 0)
1552 {
1553 if (info)
1554 info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1555 QuantumRange+1.0);
1556 for ( ; image; image=image->next)
1557 image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1558 QuantumRange+1.0);
1559 break;
1560 }
1561 if (info)
1562 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1563 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001564 {
1565 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001566 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001567 }
cristy4a3ce0a2013-08-03 20:06:59 +00001568 break;
1569 }
1570 case 'G':
1571 case 'g':
1572 {
1573 if (LocaleCompare(attribute,"gamma") == 0)
1574 {
1575 for ( ; image; image=image->next)
1576 image->gamma=SvNV(sval);
1577 break;
1578 }
1579 if (LocaleCompare(attribute,"gravity") == 0)
1580 {
1581 sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1582 SvPV(sval,na)) : SvIV(sval);
1583 if (sp < 0)
1584 {
1585 ThrowPerlException(exception,OptionError,
1586 "UnrecognizedGravityType",SvPV(sval,na));
1587 break;
1588 }
1589 if (info)
1590 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1591 for ( ; image; image=image->next)
1592 image->gravity=(GravityType) sp;
1593 break;
1594 }
1595 if (LocaleCompare(attribute,"green-primary") == 0)
1596 {
1597 for ( ; image; image=image->next)
1598 {
1599 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1600 image->chromaticity.green_primary.x=geometry_info.rho;
1601 image->chromaticity.green_primary.y=geometry_info.sigma;
1602 if ((flags & SigmaValue) == 0)
1603 image->chromaticity.green_primary.y=
1604 image->chromaticity.green_primary.x;
1605 }
1606 break;
1607 }
1608 if (info)
1609 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1610 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001611 {
1612 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001613 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001614 }
cristy4a3ce0a2013-08-03 20:06:59 +00001615 break;
1616 }
1617 case 'I':
1618 case 'i':
1619 {
1620 if (LocaleNCompare(attribute,"index",5) == 0)
1621 {
1622 int
1623 items;
1624
1625 long
1626 index;
1627
1628 register Quantum
1629 *q;
1630
1631 CacheView
1632 *image_view;
1633
1634 for ( ; image; image=image->next)
1635 {
1636 if (image->storage_class != PseudoClass)
1637 continue;
1638 x=0;
1639 y=0;
1640 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1641 (void) items;
1642 image_view=AcquireAuthenticCacheView(image,exception);
1643 q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1644 if (q != (Quantum *) NULL)
1645 {
1646 items=sscanf(SvPV(sval,na),"%ld",&index);
1647 if ((index >= 0) && (index < (ssize_t) image->colors))
1648 SetPixelIndex(image,index,q);
1649 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1650 }
1651 image_view=DestroyCacheView(image_view);
1652 }
1653 break;
1654 }
1655 if (LocaleCompare(attribute,"iterations") == 0)
1656 {
1657 iterations:
1658 for ( ; image; image=image->next)
1659 image->iterations=SvIV(sval);
1660 break;
1661 }
1662 if (LocaleCompare(attribute,"interlace") == 0)
1663 {
1664 sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1665 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1666 if (sp < 0)
1667 {
1668 ThrowPerlException(exception,OptionError,
1669 "UnrecognizedInterlaceType",SvPV(sval,na));
1670 break;
1671 }
1672 if (info)
1673 info->image_info->interlace=(InterlaceType) sp;
1674 for ( ; image; image=image->next)
1675 image->interlace=(InterlaceType) sp;
1676 break;
1677 }
1678 if (info)
1679 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1680 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001681 {
1682 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001683 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001684 }
cristy4a3ce0a2013-08-03 20:06:59 +00001685 break;
1686 }
1687 case 'L':
1688 case 'l':
1689 {
1690 if (LocaleCompare(attribute,"label") == 0)
1691 {
1692 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001693 (void) SetImageProperty(image,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00001694 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04001695 SvPV(sval,na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001696 break;
1697 }
1698 if (LocaleCompare(attribute,"loop") == 0)
1699 goto iterations;
1700 if (info)
1701 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1702 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001703 {
1704 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001705 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001706 }
cristy4a3ce0a2013-08-03 20:06:59 +00001707 break;
1708 }
1709 case 'M':
1710 case 'm':
1711 {
1712 if (LocaleCompare(attribute,"magick") == 0)
1713 {
1714 if (info)
Cristyb5b1f5d2017-03-31 16:42:35 -04001715 (void) FormatLocaleString(info->image_info->filename,
1716 MagickPathExtent,"%s:",SvPV(sval,na));
cristy4a3ce0a2013-08-03 20:06:59 +00001717 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001718 (void) CopyMagickString(image->magick,SvPV(sval,na),
1719 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001720 break;
1721 }
1722 if (LocaleCompare(attribute,"map-limit") == 0)
1723 {
1724 MagickSizeType
1725 limit;
1726
1727 limit=MagickResourceInfinity;
1728 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1729 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1730 100.0);
1731 (void) SetMagickResourceLimit(MapResource,limit);
1732 break;
1733 }
1734 if (LocaleCompare(attribute,"mask") == 0)
1735 {
1736 Image
1737 *mask;
1738
1739 mask=(Image *) NULL;
1740 if (SvPOK(sval))
1741 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1742 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001743 SetImageMask(image,ReadPixelMask,mask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001744 break;
1745 }
1746 if (LocaleCompare(attribute,"mattecolor") == 0)
1747 {
1748 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1749 exception);
1750 if (info)
Cristy8645e042016-02-03 16:35:29 -05001751 info->image_info->alpha_color=target_color;
cristy4a3ce0a2013-08-03 20:06:59 +00001752 for ( ; image; image=image->next)
Cristy8645e042016-02-03 16:35:29 -05001753 image->alpha_color=target_color;
cristy4a3ce0a2013-08-03 20:06:59 +00001754 break;
1755 }
1756 if (LocaleCompare(attribute,"matte") == 0)
1757 {
1758 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1759 SvPV(sval,na)) : SvIV(sval);
1760 if (sp < 0)
1761 {
1762 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1763 SvPV(sval,na));
1764 break;
1765 }
1766 for ( ; image; image=image->next)
1767 image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1768 break;
1769 }
1770 if (LocaleCompare(attribute,"memory-limit") == 0)
1771 {
1772 MagickSizeType
1773 limit;
1774
1775 limit=MagickResourceInfinity;
1776 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1777 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1778 100.0);
1779 (void) SetMagickResourceLimit(MemoryResource,limit);
1780 break;
1781 }
1782 if (LocaleCompare(attribute,"monochrome") == 0)
1783 {
1784 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1785 SvPV(sval,na)) : SvIV(sval);
1786 if (sp < 0)
1787 {
1788 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1789 SvPV(sval,na));
1790 break;
1791 }
1792 if (info)
1793 info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1794 for ( ; image; image=image->next)
1795 (void) SetImageType(image,BilevelType,exception);
1796 break;
1797 }
1798 if (info)
1799 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1800 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001801 {
1802 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001803 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001804 }
cristy4a3ce0a2013-08-03 20:06:59 +00001805 break;
1806 }
1807 case 'O':
1808 case 'o':
1809 {
1810 if (LocaleCompare(attribute,"option") == 0)
1811 {
1812 if (info)
1813 DefineImageOption(info->image_info,SvPV(sval,na));
1814 break;
1815 }
1816 if (LocaleCompare(attribute,"orientation") == 0)
1817 {
1818 sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1819 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1820 if (sp < 0)
1821 {
1822 ThrowPerlException(exception,OptionError,
1823 "UnrecognizedOrientationType",SvPV(sval,na));
1824 break;
1825 }
1826 if (info)
1827 info->image_info->orientation=(OrientationType) sp;
1828 for ( ; image; image=image->next)
1829 image->orientation=(OrientationType) sp;
1830 break;
1831 }
1832 if (info)
1833 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1834 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001835 {
1836 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001837 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001838 }
cristy4a3ce0a2013-08-03 20:06:59 +00001839 break;
1840 }
1841 case 'P':
1842 case 'p':
1843 {
1844 if (LocaleCompare(attribute,"page") == 0)
1845 {
1846 char
1847 *geometry;
1848
1849 geometry=GetPageGeometry(SvPV(sval,na));
1850 if (info)
1851 (void) CloneString(&info->image_info->page,geometry);
1852 for ( ; image; image=image->next)
1853 (void) ParsePageGeometry(image,geometry,&image->page,exception);
1854 geometry=(char *) RelinquishMagickMemory(geometry);
1855 break;
1856 }
1857 if (LocaleNCompare(attribute,"pixel",5) == 0)
1858 {
1859 int
1860 items;
1861
1862 PixelInfo
1863 pixel;
1864
1865 register Quantum
1866 *q;
1867
1868 CacheView
1869 *image_view;
1870
1871 for ( ; image; image=image->next)
1872 {
1873 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1874 break;
1875 x=0;
1876 y=0;
1877 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1878 (void) items;
1879 image_view=AcquireVirtualCacheView(image,exception);
1880 q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1881 if (q != (Quantum *) NULL)
1882 {
1883 if ((strchr(SvPV(sval,na),',') == 0) ||
1884 (strchr(SvPV(sval,na),')') != 0))
1885 QueryColorCompliance(SvPV(sval,na),AllCompliance,
1886 &pixel,exception);
1887 else
1888 {
1889 GetPixelInfo(image,&pixel);
1890 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1891 pixel.red=geometry_info.rho;
1892 if ((flags & SigmaValue) != 0)
1893 pixel.green=geometry_info.sigma;
1894 if ((flags & XiValue) != 0)
1895 pixel.blue=geometry_info.xi;
1896 if ((flags & PsiValue) != 0)
1897 pixel.alpha=geometry_info.psi;
1898 if ((flags & ChiValue) != 0)
1899 pixel.black=geometry_info.chi;
1900 }
1901 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1902 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1903 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1904 if (image->colorspace == CMYKColorspace)
1905 SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1906 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1907 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1908 }
1909 image_view=DestroyCacheView(image_view);
1910 }
1911 break;
1912 }
1913 if (LocaleCompare(attribute,"pointsize") == 0)
1914 {
1915 if (info)
1916 {
1917 (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1918 info->image_info->pointsize=geometry_info.rho;
1919 }
1920 break;
1921 }
cristy4a3ce0a2013-08-03 20:06:59 +00001922 if (info)
1923 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1924 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001925 {
1926 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001927 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001928 }
cristy4a3ce0a2013-08-03 20:06:59 +00001929 break;
1930 }
1931 case 'Q':
1932 case 'q':
1933 {
1934 if (LocaleCompare(attribute,"quality") == 0)
1935 {
1936 if (info)
1937 info->image_info->quality=SvIV(sval);
1938 for ( ; image; image=image->next)
1939 image->quality=SvIV(sval);
1940 break;
1941 }
1942 if (info)
1943 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1944 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001945 {
1946 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001947 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001948 }
cristy4a3ce0a2013-08-03 20:06:59 +00001949 break;
1950 }
1951 case 'R':
1952 case 'r':
1953 {
cristyc0fe4752015-07-27 18:02:39 +00001954 if (LocaleCompare(attribute,"read-mask") == 0)
1955 {
1956 Image
1957 *mask;
1958
1959 mask=(Image *) NULL;
1960 if (SvPOK(sval))
1961 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1962 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001963 SetImageMask(image,ReadPixelMask,mask,exception);
cristyc0fe4752015-07-27 18:02:39 +00001964 break;
1965 }
cristy4a3ce0a2013-08-03 20:06:59 +00001966 if (LocaleCompare(attribute,"red-primary") == 0)
1967 {
1968 for ( ; image; image=image->next)
1969 {
1970 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1971 image->chromaticity.red_primary.x=geometry_info.rho;
1972 image->chromaticity.red_primary.y=geometry_info.sigma;
1973 if ((flags & SigmaValue) == 0)
1974 image->chromaticity.red_primary.y=
1975 image->chromaticity.red_primary.x;
1976 }
1977 break;
1978 }
1979 if (LocaleCompare(attribute,"render") == 0)
1980 {
1981 sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1982 SvPV(sval,na)) : SvIV(sval);
1983 if (sp < 0)
1984 {
1985 ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1986 SvPV(sval,na));
1987 break;
1988 }
1989 for ( ; image; image=image->next)
1990 image->rendering_intent=(RenderingIntent) sp;
1991 break;
1992 }
1993 if (LocaleCompare(attribute,"repage") == 0)
1994 {
1995 RectangleInfo
1996 geometry;
1997
1998 for ( ; image; image=image->next)
1999 {
2000 flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
2001 if ((flags & WidthValue) != 0)
2002 {
2003 if ((flags & HeightValue) == 0)
2004 geometry.height=geometry.width;
2005 image->page.width=geometry.width;
2006 image->page.height=geometry.height;
2007 }
2008 if ((flags & AspectValue) != 0)
2009 {
2010 if ((flags & XValue) != 0)
2011 image->page.x+=geometry.x;
2012 if ((flags & YValue) != 0)
2013 image->page.y+=geometry.y;
2014 }
2015 else
2016 {
2017 if ((flags & XValue) != 0)
2018 {
2019 image->page.x=geometry.x;
2020 if (((flags & WidthValue) != 0) && (geometry.x > 0))
2021 image->page.width=image->columns+geometry.x;
2022 }
2023 if ((flags & YValue) != 0)
2024 {
2025 image->page.y=geometry.y;
2026 if (((flags & HeightValue) != 0) && (geometry.y > 0))
2027 image->page.height=image->rows+geometry.y;
2028 }
2029 }
2030 }
2031 break;
2032 }
2033 if (info)
2034 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2035 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002036 {
2037 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002038 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002039 }
cristy4a3ce0a2013-08-03 20:06:59 +00002040 break;
2041 }
2042 case 'S':
2043 case 's':
2044 {
2045 if (LocaleCompare(attribute,"sampling-factor") == 0)
2046 {
2047 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2048 {
2049 ThrowPerlException(exception,OptionError,"MissingGeometry",
2050 SvPV(sval,na));
2051 break;
2052 }
2053 if (info)
2054 (void) CloneString(&info->image_info->sampling_factor,
2055 SvPV(sval,na));
2056 break;
2057 }
2058 if (LocaleCompare(attribute,"scene") == 0)
2059 {
2060 for ( ; image; image=image->next)
2061 image->scene=SvIV(sval);
2062 break;
2063 }
2064 if (LocaleCompare(attribute,"server") == 0)
2065 goto display;
2066 if (LocaleCompare(attribute,"size") == 0)
2067 {
2068 if (info)
2069 {
2070 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2071 {
2072 ThrowPerlException(exception,OptionError,"MissingGeometry",
2073 SvPV(sval,na));
2074 break;
2075 }
2076 (void) CloneString(&info->image_info->size,SvPV(sval,na));
2077 }
2078 break;
2079 }
2080 if (LocaleCompare(attribute,"stroke") == 0)
2081 {
2082 if (info)
2083 (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2084 break;
2085 }
2086 if (info)
2087 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2088 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002089 {
2090 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002091 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002092 }
cristy4a3ce0a2013-08-03 20:06:59 +00002093 break;
2094 }
2095 case 'T':
2096 case 't':
2097 {
2098 if (LocaleCompare(attribute,"texture") == 0)
2099 {
2100 if (info)
2101 (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2102 break;
2103 }
2104 if (LocaleCompare(attribute,"thread-limit") == 0)
2105 {
2106 MagickSizeType
2107 limit;
2108
2109 limit=MagickResourceInfinity;
2110 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2111 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2112 100.0);
2113 (void) SetMagickResourceLimit(ThreadResource,limit);
2114 break;
2115 }
2116 if (LocaleCompare(attribute,"tile-offset") == 0)
2117 {
2118 char
2119 *geometry;
2120
2121 geometry=GetPageGeometry(SvPV(sval,na));
2122 if (info)
2123 (void) CloneString(&info->image_info->page,geometry);
2124 for ( ; image; image=image->next)
2125 (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2126 exception);
2127 geometry=(char *) RelinquishMagickMemory(geometry);
2128 break;
2129 }
2130 if (LocaleCompare(attribute,"time-limit") == 0)
2131 {
2132 MagickSizeType
2133 limit;
2134
2135 limit=MagickResourceInfinity;
2136 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2137 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2138 100.0);
2139 (void) SetMagickResourceLimit(TimeResource,limit);
2140 break;
2141 }
2142 if (LocaleCompare(attribute,"transparent-color") == 0)
2143 {
2144 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2145 exception);
2146 if (info)
2147 info->image_info->transparent_color=target_color;
2148 for ( ; image; image=image->next)
2149 image->transparent_color=target_color;
2150 break;
2151 }
2152 if (LocaleCompare(attribute,"type") == 0)
2153 {
2154 sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2155 SvPV(sval,na)) : SvIV(sval);
2156 if (sp < 0)
2157 {
2158 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2159 SvPV(sval,na));
2160 break;
2161 }
2162 if (info)
2163 info->image_info->type=(ImageType) sp;
2164 for ( ; image; image=image->next)
2165 SetImageType(image,(ImageType) sp,exception);
2166 break;
2167 }
2168 if (info)
2169 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2170 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002171 {
2172 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002173 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002174 }
cristy4a3ce0a2013-08-03 20:06:59 +00002175 break;
2176 }
2177 case 'U':
2178 case 'u':
2179 {
2180 if (LocaleCompare(attribute,"units") == 0)
2181 {
2182 sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2183 MagickFalse,SvPV(sval,na)) : SvIV(sval);
2184 if (sp < 0)
2185 {
2186 ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2187 SvPV(sval,na));
2188 break;
2189 }
2190 if (info)
2191 info->image_info->units=(ResolutionType) sp;
2192 for ( ; image; image=image->next)
2193 {
2194 ResolutionType
2195 units;
2196
2197 units=(ResolutionType) sp;
2198 if (image->units != units)
2199 switch (image->units)
2200 {
2201 case UndefinedResolution:
2202 case PixelsPerInchResolution:
2203 {
2204 if (units == PixelsPerCentimeterResolution)
2205 {
2206 image->resolution.x*=2.54;
2207 image->resolution.y*=2.54;
2208 }
2209 break;
2210 }
2211 case PixelsPerCentimeterResolution:
2212 {
2213 if (units == PixelsPerInchResolution)
2214 {
2215 image->resolution.x/=2.54;
2216 image->resolution.y/=2.54;
2217 }
2218 break;
2219 }
2220 }
2221 image->units=units;
2222 }
2223 break;
2224 }
2225 if (info)
2226 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2227 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002228 {
2229 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002230 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002231 }
cristy4a3ce0a2013-08-03 20:06:59 +00002232 break;
2233 }
2234 case 'V':
2235 case 'v':
2236 {
2237 if (LocaleCompare(attribute,"verbose") == 0)
2238 {
2239 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2240 SvPV(sval,na)) : SvIV(sval);
2241 if (sp < 0)
2242 {
2243 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2244 SvPV(sval,na));
2245 break;
2246 }
2247 if (info)
2248 info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2249 break;
2250 }
cristy4a3ce0a2013-08-03 20:06:59 +00002251 if (LocaleCompare(attribute,"virtual-pixel") == 0)
2252 {
2253 sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2254 MagickFalse,SvPV(sval,na)) : SvIV(sval);
2255 if (sp < 0)
2256 {
2257 ThrowPerlException(exception,OptionError,
2258 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2259 break;
2260 }
2261 for ( ; image; image=image->next)
2262 SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2263 break;
2264 }
2265 if (info)
2266 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2267 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002268 {
2269 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002270 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002271 }
cristy4a3ce0a2013-08-03 20:06:59 +00002272 break;
2273 }
2274 case 'W':
2275 case 'w':
2276 {
2277 if (LocaleCompare(attribute,"white-point") == 0)
2278 {
2279 for ( ; image; image=image->next)
2280 {
2281 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2282 image->chromaticity.white_point.x=geometry_info.rho;
2283 image->chromaticity.white_point.y=geometry_info.sigma;
2284 if ((flags & SigmaValue) == 0)
2285 image->chromaticity.white_point.y=
2286 image->chromaticity.white_point.x;
2287 }
2288 break;
2289 }
cristyc0fe4752015-07-27 18:02:39 +00002290 if (LocaleCompare(attribute,"write-mask") == 0)
2291 {
2292 Image
2293 *mask;
2294
2295 mask=(Image *) NULL;
2296 if (SvPOK(sval))
2297 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2298 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00002299 SetImageMask(image,WritePixelMask,mask,exception);
cristyc0fe4752015-07-27 18:02:39 +00002300 break;
2301 }
cristy4a3ce0a2013-08-03 20:06:59 +00002302 if (info)
2303 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2304 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002305 {
2306 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002307 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002308 }
cristy4a3ce0a2013-08-03 20:06:59 +00002309 break;
2310 }
2311 default:
2312 {
2313 if (info)
2314 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2315 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002316 {
2317 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002318 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002319 }
cristy4a3ce0a2013-08-03 20:06:59 +00002320 break;
2321 }
2322 }
2323}
2324
2325/*
2326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2327% %
2328% %
2329% %
2330% S e t u p L i s t %
2331% %
2332% %
2333% %
2334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2335%
2336% Method SetupList returns the list of all the images linked by their
2337% image->next and image->previous link lists for use with ImageMagick. If
2338% info is non-NULL, an info structure is returned in *info. If
2339% reference_vector is non-NULL,an array of SV* are returned in
2340% *reference_vector. Reference_vector is used when the images are going to be
2341% replaced with new Image*'s.
2342%
2343% The format of the SetupList routine is:
2344%
2345% Image *SetupList(SV *reference,struct PackageInfo **info,
2346% SV ***reference_vector,ExceptionInfo *exception)
2347%
2348% A description of each parameter follows:
2349%
2350% o list: a list of strings.
2351%
2352% o string: a character string.
2353%
2354% o exception: Return any errors or warnings in this structure.
2355%
2356*/
2357static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2358 SV ***reference_vector,ExceptionInfo *exception)
2359{
2360 Image
2361 *image;
2362
2363 ssize_t
2364 current,
2365 last;
2366
2367 if (reference_vector)
2368 *reference_vector=NULL;
2369 if (info)
2370 *info=NULL;
2371 current=0;
2372 last=0;
2373 image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2374 if (info && (SvTYPE(reference) == SVt_PVAV))
2375 *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2376 exception);
2377 return(image);
2378}
2379
2380/*
2381%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2382% %
2383% %
2384% %
2385% s t r E Q c a s e %
2386% %
2387% %
2388% %
2389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2390%
2391% strEQcase() compares two strings and returns 0 if they are the
2392% same or if the second string runs out first. The comparison is case
2393% insensitive.
2394%
2395% The format of the strEQcase routine is:
2396%
2397% ssize_t strEQcase(const char *p,const char *q)
2398%
2399% A description of each parameter follows:
2400%
2401% o p: a character string.
2402%
2403% o q: a character string.
2404%
2405%
2406*/
2407static ssize_t strEQcase(const char *p,const char *q)
2408{
2409 char
2410 c;
2411
2412 register ssize_t
2413 i;
2414
2415 for (i=0 ; (c=(*q)) != 0; i++)
2416 {
2417 if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2418 (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2419 return(0);
2420 p++;
2421 q++;
2422 }
2423 return(((*q == 0) && (*p == 0)) ? i : 0);
2424}
2425
2426/*
2427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2428% %
2429% %
2430% %
2431% I m a g e : : M a g i c k %
2432% %
2433% %
2434% %
2435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2436%
2437%
2438*/
2439MODULE = Image::Magick PACKAGE = Image::Magick
2440
2441PROTOTYPES: ENABLE
2442
2443BOOT:
2444 MagickCoreGenesis("PerlMagick",MagickFalse);
2445 SetWarningHandler(NULL);
2446 SetErrorHandler(NULL);
2447 magick_registry=NewSplayTree((int (*)(const void *,const void *))
2448 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2449
2450void
2451UNLOAD()
2452 PPCODE:
2453 {
2454 if (magick_registry != (SplayTreeInfo *) NULL)
2455 magick_registry=DestroySplayTree(magick_registry);
2456 MagickCoreTerminus();
2457 }
2458
2459double
2460constant(name,argument)
2461 char *name
2462 ssize_t argument
2463
2464#
2465###############################################################################
2466# #
2467# #
2468# #
2469# A n i m a t e #
2470# #
2471# #
2472# #
2473###############################################################################
2474#
2475#
2476void
2477Animate(ref,...)
2478 Image::Magick ref=NO_INIT
2479 ALIAS:
2480 AnimateImage = 1
2481 animate = 2
2482 animateimage = 3
2483 PPCODE:
2484 {
2485 ExceptionInfo
2486 *exception;
2487
2488 Image
2489 *image;
2490
2491 register ssize_t
2492 i;
2493
2494 struct PackageInfo
2495 *info,
2496 *package_info;
2497
2498 SV
2499 *perl_exception,
2500 *reference;
2501
2502 PERL_UNUSED_VAR(ref);
2503 PERL_UNUSED_VAR(ix);
2504 exception=AcquireExceptionInfo();
2505 perl_exception=newSVpv("",0);
2506 package_info=(struct PackageInfo *) NULL;
2507 if (sv_isobject(ST(0)) == 0)
2508 {
2509 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2510 PackageName);
2511 goto PerlException;
2512 }
2513 reference=SvRV(ST(0));
2514 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2515 if (image == (Image *) NULL)
2516 {
2517 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2518 PackageName);
2519 goto PerlException;
2520 }
2521 package_info=ClonePackageInfo(info,exception);
2522 if (items == 2)
2523 SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2524 else
2525 if (items > 2)
2526 for (i=2; i < items; i+=2)
2527 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2528 exception);
2529 (void) AnimateImages(package_info->image_info,image,exception);
2530 (void) CatchImageException(image);
2531
2532 PerlException:
2533 if (package_info != (struct PackageInfo *) NULL)
2534 DestroyPackageInfo(package_info);
2535 InheritPerlException(exception,perl_exception);
2536 exception=DestroyExceptionInfo(exception);
2537 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2538 SvPOK_on(perl_exception);
2539 ST(0)=sv_2mortal(perl_exception);
2540 XSRETURN(1);
2541 }
2542
2543#
2544###############################################################################
2545# #
2546# #
2547# #
2548# A p p e n d #
2549# #
2550# #
2551# #
2552###############################################################################
2553#
2554#
2555void
2556Append(ref,...)
2557 Image::Magick ref=NO_INIT
2558 ALIAS:
2559 AppendImage = 1
2560 append = 2
2561 appendimage = 3
2562 PPCODE:
2563 {
2564 AV
2565 *av;
2566
2567 char
2568 *attribute;
2569
2570 ExceptionInfo
2571 *exception;
2572
2573 HV
2574 *hv;
2575
2576 Image
2577 *image;
2578
2579 register ssize_t
2580 i;
2581
2582 ssize_t
2583 stack;
2584
2585 struct PackageInfo
2586 *info;
2587
2588 SV
2589 *av_reference,
2590 *perl_exception,
2591 *reference,
2592 *rv,
2593 *sv;
2594
2595 PERL_UNUSED_VAR(ref);
2596 PERL_UNUSED_VAR(ix);
2597 exception=AcquireExceptionInfo();
2598 perl_exception=newSVpv("",0);
2599 sv=NULL;
2600 attribute=NULL;
2601 av=NULL;
2602 if (sv_isobject(ST(0)) == 0)
2603 {
2604 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2605 PackageName);
2606 goto PerlException;
2607 }
2608 reference=SvRV(ST(0));
2609 hv=SvSTASH(reference);
2610 av=newAV();
2611 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2612 SvREFCNT_dec(av);
2613 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2614 if (image == (Image *) NULL)
2615 {
2616 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2617 PackageName);
2618 goto PerlException;
2619 }
2620 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2621 /*
2622 Get options.
2623 */
2624 stack=MagickTrue;
2625 for (i=2; i < items; i+=2)
2626 {
2627 attribute=(char *) SvPV(ST(i-1),na);
2628 switch (*attribute)
2629 {
2630 case 'S':
2631 case 's':
2632 {
2633 if (LocaleCompare(attribute,"stack") == 0)
2634 {
2635 stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2636 SvPV(ST(i),na));
2637 if (stack < 0)
2638 {
2639 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2640 SvPV(ST(i),na));
2641 return;
2642 }
2643 break;
2644 }
2645 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2646 attribute);
2647 break;
2648 }
2649 default:
2650 {
2651 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2652 attribute);
2653 break;
2654 }
2655 }
2656 }
2657 image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2658 if (image == (Image *) NULL)
2659 goto PerlException;
2660 for ( ; image; image=image->next)
2661 {
2662 AddImageToRegistry(sv,image);
2663 rv=newRV(sv);
2664 av_push(av,sv_bless(rv,hv));
2665 SvREFCNT_dec(sv);
2666 }
2667 exception=DestroyExceptionInfo(exception);
2668 ST(0)=av_reference;
2669 SvREFCNT_dec(perl_exception);
2670 XSRETURN(1);
2671
2672 PerlException:
2673 InheritPerlException(exception,perl_exception);
2674 exception=DestroyExceptionInfo(exception);
2675 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2676 SvPOK_on(perl_exception);
2677 ST(0)=sv_2mortal(perl_exception);
2678 XSRETURN(1);
2679 }
2680
2681#
2682###############################################################################
2683# #
2684# #
2685# #
2686# A v e r a g e #
2687# #
2688# #
2689# #
2690###############################################################################
2691#
2692#
2693void
2694Average(ref)
2695 Image::Magick ref=NO_INIT
2696 ALIAS:
2697 AverageImage = 1
2698 average = 2
2699 averageimage = 3
2700 PPCODE:
2701 {
2702 AV
2703 *av;
2704
2705 char
2706 *p;
2707
2708 ExceptionInfo
2709 *exception;
2710
2711 HV
2712 *hv;
2713
2714 Image
2715 *image;
2716
2717 struct PackageInfo
2718 *info;
2719
2720 SV
2721 *perl_exception,
2722 *reference,
2723 *rv,
2724 *sv;
2725
2726 PERL_UNUSED_VAR(ref);
2727 PERL_UNUSED_VAR(ix);
2728 exception=AcquireExceptionInfo();
2729 perl_exception=newSVpv("",0);
2730 sv=NULL;
2731 if (sv_isobject(ST(0)) == 0)
2732 {
2733 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2734 PackageName);
2735 goto PerlException;
2736 }
2737 reference=SvRV(ST(0));
2738 hv=SvSTASH(reference);
2739 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2740 if (image == (Image *) NULL)
2741 {
2742 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2743 PackageName);
2744 goto PerlException;
2745 }
2746 image=EvaluateImages(image,MeanEvaluateOperator,exception);
2747 if (image == (Image *) NULL)
2748 goto PerlException;
2749 /*
2750 Create blessed Perl array for the returned image.
2751 */
2752 av=newAV();
2753 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2754 SvREFCNT_dec(av);
2755 AddImageToRegistry(sv,image);
2756 rv=newRV(sv);
2757 av_push(av,sv_bless(rv,hv));
2758 SvREFCNT_dec(sv);
2759 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00002760 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2761 "average-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00002762 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2763 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00002764 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00002765 SetImageInfo(info->image_info,0,exception);
2766 exception=DestroyExceptionInfo(exception);
2767 SvREFCNT_dec(perl_exception);
2768 XSRETURN(1);
2769
2770 PerlException:
2771 InheritPerlException(exception,perl_exception);
2772 exception=DestroyExceptionInfo(exception);
2773 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2774 SvPOK_on(perl_exception);
2775 ST(0)=sv_2mortal(perl_exception);
2776 XSRETURN(1);
2777 }
2778
2779#
2780###############################################################################
2781# #
2782# #
2783# #
2784# B l o b T o I m a g e #
2785# #
2786# #
2787# #
2788###############################################################################
2789#
2790#
2791void
2792BlobToImage(ref,...)
2793 Image::Magick ref=NO_INIT
2794 ALIAS:
2795 BlobToImage = 1
2796 blobtoimage = 2
2797 blobto = 3
2798 PPCODE:
2799 {
2800 AV
2801 *av;
2802
2803 char
2804 **keep,
2805 **list;
2806
2807 ExceptionInfo
2808 *exception;
2809
2810 HV
2811 *hv;
2812
2813 Image
2814 *image;
2815
2816 register char
2817 **p;
2818
2819 register ssize_t
2820 i;
2821
2822 ssize_t
2823 ac,
2824 n,
2825 number_images;
2826
2827 STRLEN
2828 *length;
2829
2830 struct PackageInfo
2831 *info;
2832
2833 SV
2834 *perl_exception,
2835 *reference,
2836 *rv,
2837 *sv;
2838
2839 PERL_UNUSED_VAR(ref);
2840 PERL_UNUSED_VAR(ix);
2841 exception=AcquireExceptionInfo();
2842 perl_exception=newSVpv("",0);
2843 sv=NULL;
2844 number_images=0;
2845 ac=(items < 2) ? 1 : items-1;
2846 length=(STRLEN *) NULL;
2847 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2848 if (list == (char **) NULL)
2849 {
2850 ThrowPerlException(exception,ResourceLimitError,
2851 "MemoryAllocationFailed",PackageName);
2852 goto PerlException;
2853 }
2854 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2855 if (length == (STRLEN *) NULL)
2856 {
2857 ThrowPerlException(exception,ResourceLimitError,
2858 "MemoryAllocationFailed",PackageName);
2859 goto PerlException;
2860 }
2861 if (sv_isobject(ST(0)) == 0)
2862 {
2863 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2864 PackageName);
2865 goto PerlException;
2866 }
2867 reference=SvRV(ST(0));
2868 hv=SvSTASH(reference);
2869 if (SvTYPE(reference) != SVt_PVAV)
2870 {
2871 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2872 PackageName);
2873 goto PerlException;
2874 }
2875 av=(AV *) reference;
2876 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2877 exception);
2878 n=1;
2879 if (items <= 1)
2880 {
2881 ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2882 goto PerlException;
2883 }
2884 for (n=0, i=0; i < ac; i++)
2885 {
2886 list[n]=(char *) (SvPV(ST(i+1),length[n]));
2887 if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2888 {
2889 list[n]=(char *) (SvPV(ST(i+2),length[n]));
2890 continue;
2891 }
2892 n++;
2893 }
2894 list[n]=(char *) NULL;
2895 keep=list;
2896 for (i=number_images=0; i < n; i++)
2897 {
2898 image=BlobToImage(info->image_info,list[i],length[i],exception);
2899 if (image == (Image *) NULL)
2900 break;
2901 for ( ; image; image=image->next)
2902 {
2903 AddImageToRegistry(sv,image);
2904 rv=newRV(sv);
2905 av_push(av,sv_bless(rv,hv));
2906 SvREFCNT_dec(sv);
2907 number_images++;
2908 }
2909 }
2910 /*
2911 Free resources.
2912 */
2913 for (i=0; i < n; i++)
2914 if (list[i] != (char *) NULL)
2915 for (p=keep; list[i] != *p++; )
2916 if (*p == (char *) NULL)
2917 {
2918 list[i]=(char *) RelinquishMagickMemory(list[i]);
2919 break;
2920 }
2921
2922 PerlException:
2923 if (list)
2924 list=(char **) RelinquishMagickMemory(list);
2925 if (length)
2926 length=(STRLEN *) RelinquishMagickMemory(length);
2927 InheritPerlException(exception,perl_exception);
2928 exception=DestroyExceptionInfo(exception);
2929 sv_setiv(perl_exception,(IV) number_images);
2930 SvPOK_on(perl_exception);
2931 ST(0)=sv_2mortal(perl_exception);
2932 XSRETURN(1);
2933 }
2934
2935#
2936###############################################################################
2937# #
2938# #
2939# #
2940# C h a n n e l F x #
2941# #
2942# #
2943# #
2944###############################################################################
2945#
2946#
2947void
2948ChannelFx(ref,...)
2949 Image::Magick ref=NO_INIT
2950 ALIAS:
2951 ChannelFxImage = 1
2952 channelfx = 2
2953 channelfximage = 3
2954 PPCODE:
2955 {
2956 AV
2957 *av;
2958
2959 char
2960 *attribute,
cristy151b66d2015-04-15 10:50:31 +00002961 expression[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00002962
2963 ChannelType
2964 channel,
2965 channel_mask;
2966
2967 ExceptionInfo
2968 *exception;
2969
2970 HV
2971 *hv;
2972
2973 Image
2974 *image;
2975
2976 register ssize_t
2977 i;
2978
2979 struct PackageInfo
2980 *info;
2981
2982 SV
2983 *av_reference,
2984 *perl_exception,
2985 *reference,
2986 *rv,
2987 *sv;
2988
2989 PERL_UNUSED_VAR(ref);
2990 PERL_UNUSED_VAR(ix);
2991 exception=AcquireExceptionInfo();
2992 perl_exception=newSVpv("",0);
2993 sv=NULL;
2994 attribute=NULL;
2995 av=NULL;
2996 if (sv_isobject(ST(0)) == 0)
2997 {
2998 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2999 PackageName);
3000 goto PerlException;
3001 }
3002 reference=SvRV(ST(0));
3003 hv=SvSTASH(reference);
3004 av=newAV();
3005 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3006 SvREFCNT_dec(av);
3007 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3008 if (image == (Image *) NULL)
3009 {
3010 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3011 PackageName);
3012 goto PerlException;
3013 }
3014 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3015 /*
3016 Get options.
3017 */
3018 channel=DefaultChannels;
cristy151b66d2015-04-15 10:50:31 +00003019 (void) CopyMagickString(expression,"u",MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003020 if (items == 2)
cristy151b66d2015-04-15 10:50:31 +00003021 (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003022 else
3023 for (i=2; i < items; i+=2)
3024 {
3025 attribute=(char *) SvPV(ST(i-1),na);
3026 switch (*attribute)
3027 {
3028 case 'C':
3029 case 'c':
3030 {
3031 if (LocaleCompare(attribute,"channel") == 0)
3032 {
3033 ssize_t
3034 option;
3035
3036 option=ParseChannelOption(SvPV(ST(i),na));
3037 if (option < 0)
3038 {
3039 ThrowPerlException(exception,OptionError,
3040 "UnrecognizedType",SvPV(ST(i),na));
3041 return;
3042 }
3043 channel=(ChannelType) option;
3044 break;
3045 }
3046 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3047 attribute);
3048 break;
3049 }
3050 case 'E':
3051 case 'e':
3052 {
3053 if (LocaleCompare(attribute,"expression") == 0)
3054 {
3055 (void) CopyMagickString(expression,SvPV(ST(i),na),
cristy151b66d2015-04-15 10:50:31 +00003056 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003057 break;
3058 }
3059 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3060 attribute);
3061 break;
3062 }
3063 default:
3064 {
3065 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3066 attribute);
3067 break;
3068 }
3069 }
3070 }
3071 channel_mask=SetImageChannelMask(image,channel);
3072 image=ChannelFxImage(image,expression,exception);
3073 if (image != (Image *) NULL)
3074 (void) SetImageChannelMask(image,channel_mask);
3075 if (image == (Image *) NULL)
3076 goto PerlException;
3077 for ( ; image; image=image->next)
3078 {
3079 AddImageToRegistry(sv,image);
3080 rv=newRV(sv);
3081 av_push(av,sv_bless(rv,hv));
3082 SvREFCNT_dec(sv);
3083 }
3084 exception=DestroyExceptionInfo(exception);
3085 ST(0)=av_reference;
3086 SvREFCNT_dec(perl_exception); /* can't return warning messages */
3087 XSRETURN(1);
3088
3089 PerlException:
3090 InheritPerlException(exception,perl_exception);
3091 exception=DestroyExceptionInfo(exception);
3092 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3093 SvPOK_on(perl_exception);
3094 ST(0)=sv_2mortal(perl_exception);
3095 XSRETURN(1);
3096 }
3097
3098#
3099###############################################################################
3100# #
3101# #
3102# #
3103# C l o n e #
3104# #
3105# #
3106# #
3107###############################################################################
3108#
3109#
3110void
3111Clone(ref)
3112 Image::Magick ref=NO_INIT
3113 ALIAS:
3114 CopyImage = 1
3115 copy = 2
3116 copyimage = 3
3117 CloneImage = 4
3118 clone = 5
3119 cloneimage = 6
3120 Clone = 7
3121 PPCODE:
3122 {
3123 AV
3124 *av;
3125
3126 ExceptionInfo
3127 *exception;
3128
3129 HV
3130 *hv;
3131
3132 Image
3133 *clone,
3134 *image;
3135
3136 struct PackageInfo
3137 *info;
3138
3139 SV
3140 *perl_exception,
3141 *reference,
3142 *rv,
3143 *sv;
3144
3145 PERL_UNUSED_VAR(ref);
3146 PERL_UNUSED_VAR(ix);
3147 exception=AcquireExceptionInfo();
3148 perl_exception=newSVpv("",0);
3149 sv=NULL;
3150 if (sv_isobject(ST(0)) == 0)
3151 {
3152 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3153 PackageName);
3154 goto PerlException;
3155 }
3156 reference=SvRV(ST(0));
3157 hv=SvSTASH(reference);
3158 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3159 if (image == (Image *) NULL)
3160 {
3161 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3162 PackageName);
3163 goto PerlException;
3164 }
3165 /*
3166 Create blessed Perl array for the returned image.
3167 */
3168 av=newAV();
3169 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3170 SvREFCNT_dec(av);
3171 for ( ; image; image=image->next)
3172 {
3173 clone=CloneImage(image,0,0,MagickTrue,exception);
3174 if (clone == (Image *) NULL)
3175 break;
3176 AddImageToRegistry(sv,clone);
3177 rv=newRV(sv);
3178 av_push(av,sv_bless(rv,hv));
3179 SvREFCNT_dec(sv);
3180 }
3181 exception=DestroyExceptionInfo(exception);
3182 SvREFCNT_dec(perl_exception);
3183 XSRETURN(1);
3184
3185 PerlException:
3186 InheritPerlException(exception,perl_exception);
3187 exception=DestroyExceptionInfo(exception);
3188 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3189 SvPOK_on(perl_exception);
3190 ST(0)=sv_2mortal(perl_exception);
3191 XSRETURN(1);
3192 }
3193
3194#
3195###############################################################################
3196# #
3197# #
3198# #
3199# C L O N E #
3200# #
3201# #
3202# #
3203###############################################################################
3204#
3205#
3206void
3207CLONE(ref,...)
3208 SV *ref;
3209 CODE:
3210 {
3211 PERL_UNUSED_VAR(ref);
3212 if (magick_registry != (SplayTreeInfo *) NULL)
3213 {
3214 register Image
3215 *p;
3216
3217 ResetSplayTreeIterator(magick_registry);
3218 p=(Image *) GetNextKeyInSplayTree(magick_registry);
3219 while (p != (Image *) NULL)
3220 {
3221 ReferenceImage(p);
3222 p=(Image *) GetNextKeyInSplayTree(magick_registry);
3223 }
3224 }
3225 }
3226
3227#
3228###############################################################################
3229# #
3230# #
3231# #
3232# C o a l e s c e #
3233# #
3234# #
3235# #
3236###############################################################################
3237#
3238#
3239void
3240Coalesce(ref)
3241 Image::Magick ref=NO_INIT
3242 ALIAS:
3243 CoalesceImage = 1
3244 coalesce = 2
3245 coalesceimage = 3
3246 PPCODE:
3247 {
3248 AV
3249 *av;
3250
3251 ExceptionInfo
3252 *exception;
3253
3254 HV
3255 *hv;
3256
3257 Image
3258 *image;
3259
3260 struct PackageInfo
3261 *info;
3262
3263 SV
3264 *av_reference,
3265 *perl_exception,
3266 *reference,
3267 *rv,
3268 *sv;
3269
3270 PERL_UNUSED_VAR(ref);
3271 PERL_UNUSED_VAR(ix);
3272 exception=AcquireExceptionInfo();
3273 perl_exception=newSVpv("",0);
3274 sv=NULL;
3275 if (sv_isobject(ST(0)) == 0)
3276 {
3277 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3278 PackageName);
3279 goto PerlException;
3280 }
3281 reference=SvRV(ST(0));
3282 hv=SvSTASH(reference);
3283 av=newAV();
3284 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3285 SvREFCNT_dec(av);
3286 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3287 if (image == (Image *) NULL)
3288 {
3289 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3290 PackageName);
3291 goto PerlException;
3292 }
3293 image=CoalesceImages(image,exception);
3294 if (image == (Image *) NULL)
3295 goto PerlException;
3296 for ( ; image; image=image->next)
3297 {
3298 AddImageToRegistry(sv,image);
3299 rv=newRV(sv);
3300 av_push(av,sv_bless(rv,hv));
3301 SvREFCNT_dec(sv);
3302 }
3303 exception=DestroyExceptionInfo(exception);
3304 ST(0)=av_reference;
3305 SvREFCNT_dec(perl_exception);
3306 XSRETURN(1);
3307
3308 PerlException:
3309 InheritPerlException(exception,perl_exception);
3310 exception=DestroyExceptionInfo(exception);
3311 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3312 SvPOK_on(perl_exception);
3313 ST(0)=sv_2mortal(perl_exception);
3314 XSRETURN(1);
3315 }
3316
3317#
3318###############################################################################
3319# #
3320# #
3321# #
3322# C o m p a r e #
3323# #
3324# #
3325# #
3326###############################################################################
3327#
3328#
3329void
3330Compare(ref,...)
3331 Image::Magick ref=NO_INIT
3332 ALIAS:
3333 CompareImages = 1
3334 compare = 2
3335 compareimage = 3
3336 PPCODE:
3337 {
3338 AV
3339 *av;
3340
3341 char
3342 *attribute;
3343
3344 double
3345 distortion;
3346
3347 ExceptionInfo
3348 *exception;
3349
3350 HV
3351 *hv;
3352
3353 Image
3354 *difference_image,
3355 *image,
3356 *reconstruct_image;
3357
3358 MetricType
3359 metric;
3360
3361 register ssize_t
3362 i;
3363
3364 ssize_t
3365 option;
3366
3367 struct PackageInfo
3368 *info;
3369
3370 SV
3371 *av_reference,
3372 *perl_exception,
3373 *reference,
3374 *rv,
3375 *sv;
3376
3377 PERL_UNUSED_VAR(ref);
3378 PERL_UNUSED_VAR(ix);
3379 exception=AcquireExceptionInfo();
3380 perl_exception=newSVpv("",0);
3381 sv=NULL;
3382 av=NULL;
3383 attribute=NULL;
3384 if (sv_isobject(ST(0)) == 0)
3385 {
3386 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3387 PackageName);
3388 goto PerlException;
3389 }
3390 reference=SvRV(ST(0));
3391 hv=SvSTASH(reference);
3392 av=newAV();
3393 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3394 SvREFCNT_dec(av);
3395 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3396 if (image == (Image *) NULL)
3397 {
3398 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3399 PackageName);
3400 goto PerlException;
3401 }
3402 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3403 /*
3404 Get attribute.
3405 */
3406 reconstruct_image=image;
3407 metric=RootMeanSquaredErrorMetric;
3408 for (i=2; i < items; i+=2)
3409 {
3410 attribute=(char *) SvPV(ST(i-1),na);
3411 switch (*attribute)
3412 {
3413 case 'C':
3414 case 'c':
3415 {
3416 if (LocaleCompare(attribute,"channel") == 0)
3417 {
3418 ssize_t
3419 option;
3420
3421 option=ParseChannelOption(SvPV(ST(i),na));
3422 if (option < 0)
3423 {
3424 ThrowPerlException(exception,OptionError,
3425 "UnrecognizedType",SvPV(ST(i),na));
3426 return;
3427 }
cristybcd59342015-06-07 14:07:19 +00003428 (void) SetPixelChannelMask(image,(ChannelType) option);
cristy4a3ce0a2013-08-03 20:06:59 +00003429 break;
3430 }
3431 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3432 attribute);
3433 break;
3434 }
3435 case 'F':
3436 case 'f':
3437 {
3438 if (LocaleCompare(attribute,"fuzz") == 0)
3439 {
3440 image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3441 break;
3442 }
3443 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3444 attribute);
3445 break;
3446 }
3447 case 'I':
3448 case 'i':
3449 {
3450 if (LocaleCompare(attribute,"image") == 0)
3451 {
3452 reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3453 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3454 break;
3455 }
3456 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3457 attribute);
3458 break;
3459 }
3460 case 'M':
3461 case 'm':
3462 {
3463 if (LocaleCompare(attribute,"metric") == 0)
3464 {
3465 option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3466 SvPV(ST(i),na));
3467 if (option < 0)
3468 {
3469 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3470 SvPV(ST(i),na));
3471 break;
3472 }
3473 metric=(MetricType) option;
3474 break;
3475 }
3476 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3477 attribute);
3478 break;
3479 }
3480 default:
3481 {
3482 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3483 attribute);
3484 break;
3485 }
3486 }
3487 }
3488 difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3489 exception);
3490 if (difference_image != (Image *) NULL)
3491 {
3492 difference_image->error.mean_error_per_pixel=distortion;
3493 AddImageToRegistry(sv,difference_image);
3494 rv=newRV(sv);
3495 av_push(av,sv_bless(rv,hv));
3496 SvREFCNT_dec(sv);
3497 }
3498 exception=DestroyExceptionInfo(exception);
3499 ST(0)=av_reference;
3500 SvREFCNT_dec(perl_exception); /* can't return warning messages */
3501 XSRETURN(1);
3502
3503 PerlException:
3504 InheritPerlException(exception,perl_exception);
3505 exception=DestroyExceptionInfo(exception);
3506 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3507 SvPOK_on(perl_exception);
3508 ST(0)=sv_2mortal(perl_exception);
3509 XSRETURN(1);
3510 }
3511
3512#
3513###############################################################################
3514# #
3515# #
3516# #
cristy15655332013-10-06 00:27:33 +00003517# C o m p l e x I m a g e s #
3518# #
3519# #
3520# #
3521###############################################################################
3522#
3523#
3524void
3525ComplexImages(ref)
3526 Image::Magick ref=NO_INIT
3527 ALIAS:
3528 ComplexImages = 1
3529 compleximages = 2
3530 PPCODE:
3531 {
3532 AV
3533 *av;
3534
3535 char
3536 *attribute,
3537 *p;
3538
cristyfa21e9e2013-10-07 10:37:38 +00003539 ComplexOperator
3540 op;
3541
cristy15655332013-10-06 00:27:33 +00003542 ExceptionInfo
3543 *exception;
3544
3545 HV
3546 *hv;
3547
3548 Image
3549 *image;
3550
cristy15655332013-10-06 00:27:33 +00003551 register ssize_t
3552 i;
3553
3554 struct PackageInfo
3555 *info;
3556
3557 SV
3558 *perl_exception,
3559 *reference,
3560 *rv,
3561 *sv;
3562
3563 PERL_UNUSED_VAR(ref);
3564 PERL_UNUSED_VAR(ix);
3565 exception=AcquireExceptionInfo();
3566 perl_exception=newSVpv("",0);
3567 sv=NULL;
3568 if (sv_isobject(ST(0)) == 0)
3569 {
3570 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3571 PackageName);
3572 goto PerlException;
3573 }
3574 reference=SvRV(ST(0));
3575 hv=SvSTASH(reference);
3576 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3577 if (image == (Image *) NULL)
3578 {
3579 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3580 PackageName);
3581 goto PerlException;
3582 }
cristyfd168722013-10-07 15:59:31 +00003583 op=UndefinedComplexOperator;
cristy15655332013-10-06 00:27:33 +00003584 if (items == 2)
3585 {
3586 ssize_t
3587 in;
3588
3589 in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3590 SvPV(ST(1),na));
3591 if (in < 0)
3592 {
3593 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3594 SvPV(ST(1),na));
3595 return;
3596 }
cristyfa21e9e2013-10-07 10:37:38 +00003597 op=(ComplexOperator) in;
cristy15655332013-10-06 00:27:33 +00003598 }
3599 else
3600 for (i=2; i < items; i+=2)
3601 {
3602 attribute=(char *) SvPV(ST(i-1),na);
3603 switch (*attribute)
3604 {
3605 case 'O':
3606 case 'o':
3607 {
3608 if (LocaleCompare(attribute,"operator") == 0)
3609 {
3610 ssize_t
3611 in;
3612
3613 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3614 MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3615 if (in < 0)
3616 {
3617 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3618 SvPV(ST(i),na));
3619 return;
3620 }
cristyfa21e9e2013-10-07 10:37:38 +00003621 op=(ComplexOperator) in;
cristy15655332013-10-06 00:27:33 +00003622 break;
3623 }
3624 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3625 attribute);
3626 break;
3627 }
3628 default:
3629 {
3630 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3631 attribute);
3632 break;
3633 }
3634 }
3635 }
3636 image=ComplexImages(image,op,exception);
3637 if (image == (Image *) NULL)
3638 goto PerlException;
3639 /*
3640 Create blessed Perl array for the returned image.
3641 */
3642 av=newAV();
3643 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3644 SvREFCNT_dec(av);
3645 AddImageToRegistry(sv,image);
3646 rv=newRV(sv);
3647 av_push(av,sv_bless(rv,hv));
3648 SvREFCNT_dec(sv);
3649 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00003650 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3651 "complex-%.*s",(int) (MagickPathExtent-9),
cristy15655332013-10-06 00:27:33 +00003652 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3653 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00003654 MagickPathExtent);
cristy15655332013-10-06 00:27:33 +00003655 SetImageInfo(info->image_info,0,exception);
3656 exception=DestroyExceptionInfo(exception);
3657 SvREFCNT_dec(perl_exception);
3658 XSRETURN(1);
3659
3660 PerlException:
3661 InheritPerlException(exception,perl_exception);
3662 exception=DestroyExceptionInfo(exception);
3663 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3664 SvPOK_on(perl_exception);
3665 ST(0)=sv_2mortal(perl_exception);
3666 XSRETURN(1);
3667 }
3668
3669#
3670###############################################################################
3671# #
3672# #
3673# #
cristy4a3ce0a2013-08-03 20:06:59 +00003674# C o m p a r e L a y e r s #
3675# #
3676# #
3677# #
3678###############################################################################
3679#
3680#
3681void
3682CompareLayers(ref)
3683 Image::Magick ref=NO_INIT
3684 ALIAS:
3685 CompareImagesLayers = 1
3686 comparelayers = 2
3687 compareimagelayers = 3
3688 PPCODE:
3689 {
3690 AV
3691 *av;
3692
3693 char
3694 *attribute;
3695
3696 ExceptionInfo
3697 *exception;
3698
3699 HV
3700 *hv;
3701
3702 Image
3703 *image;
3704
3705 LayerMethod
3706 method;
3707
3708 register ssize_t
3709 i;
3710
3711 ssize_t
3712 option;
3713
3714 struct PackageInfo
3715 *info;
3716
3717 SV
3718 *av_reference,
3719 *perl_exception,
3720 *reference,
3721 *rv,
3722 *sv;
3723
3724 PERL_UNUSED_VAR(ref);
3725 PERL_UNUSED_VAR(ix);
3726 exception=AcquireExceptionInfo();
3727 perl_exception=newSVpv("",0);
3728 sv=NULL;
3729 if (sv_isobject(ST(0)) == 0)
3730 {
3731 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3732 PackageName);
3733 goto PerlException;
3734 }
3735 reference=SvRV(ST(0));
3736 hv=SvSTASH(reference);
3737 av=newAV();
3738 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3739 SvREFCNT_dec(av);
3740 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3741 if (image == (Image *) NULL)
3742 {
3743 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3744 PackageName);
3745 goto PerlException;
3746 }
3747 method=CompareAnyLayer;
3748 for (i=2; i < items; i+=2)
3749 {
3750 attribute=(char *) SvPV(ST(i-1),na);
3751 switch (*attribute)
3752 {
3753 case 'M':
3754 case 'm':
3755 {
3756 if (LocaleCompare(attribute,"method") == 0)
3757 {
3758 option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3759 SvPV(ST(i),na));
3760 if (option < 0)
3761 {
3762 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3763 SvPV(ST(i),na));
3764 break;
3765 }
3766 method=(LayerMethod) option;
3767 break;
3768 }
3769 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3770 attribute);
3771 break;
3772 }
3773 default:
3774 {
3775 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3776 attribute);
3777 break;
3778 }
3779 }
3780 }
3781 image=CompareImagesLayers(image,method,exception);
3782 if (image == (Image *) NULL)
3783 goto PerlException;
3784 for ( ; image; image=image->next)
3785 {
3786 AddImageToRegistry(sv,image);
3787 rv=newRV(sv);
3788 av_push(av,sv_bless(rv,hv));
3789 SvREFCNT_dec(sv);
3790 }
3791 exception=DestroyExceptionInfo(exception);
3792 ST(0)=av_reference;
3793 SvREFCNT_dec(perl_exception);
3794 XSRETURN(1);
3795
3796 PerlException:
3797 InheritPerlException(exception,perl_exception);
3798 exception=DestroyExceptionInfo(exception);
3799 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3800 SvPOK_on(perl_exception);
3801 ST(0)=sv_2mortal(perl_exception);
3802 XSRETURN(1);
3803 }
3804
3805#
3806###############################################################################
3807# #
3808# #
3809# #
3810# D e s t r o y #
3811# #
3812# #
3813# #
3814###############################################################################
3815#
3816#
3817void
3818DESTROY(ref)
3819 Image::Magick ref=NO_INIT
3820 PPCODE:
3821 {
3822 SV
3823 *reference;
3824
3825 PERL_UNUSED_VAR(ref);
3826 if (sv_isobject(ST(0)) == 0)
3827 croak("ReferenceIsNotMyType");
3828 reference=SvRV(ST(0));
3829 switch (SvTYPE(reference))
3830 {
3831 case SVt_PVAV:
3832 {
3833 char
cristy151b66d2015-04-15 10:50:31 +00003834 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00003835
3836 const SV
3837 *key;
3838
3839 HV
3840 *hv;
3841
3842 GV
3843 **gvp;
3844
3845 struct PackageInfo
3846 *info;
3847
3848 SV
3849 *sv;
3850
3851 /*
3852 Array (AV *) reference
3853 */
cristy151b66d2015-04-15 10:50:31 +00003854 (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
cristy4a3ce0a2013-08-03 20:06:59 +00003855 XS_VERSION,reference);
3856 hv=gv_stashpv(PackageName, FALSE);
3857 if (!hv)
3858 break;
3859 gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3860 if (!gvp)
3861 break;
3862 sv=GvSV(*gvp);
3863 if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3864 {
3865 info=INT2PTR(struct PackageInfo *,SvIV(sv));
3866 DestroyPackageInfo(info);
3867 }
3868 key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3869 (void) key;
3870 break;
3871 }
3872 case SVt_PVMG:
3873 {
3874 Image
3875 *image;
3876
3877 /*
3878 Blessed scalar = (Image *) SvIV(reference)
3879 */
3880 image=INT2PTR(Image *,SvIV(reference));
3881 if (image != (Image *) NULL)
3882 DeleteImageFromRegistry(reference,image);
3883 break;
3884 }
3885 default:
3886 break;
3887 }
3888 }
3889
3890#
3891###############################################################################
3892# #
3893# #
3894# #
3895# D i s p l a y #
3896# #
3897# #
3898# #
3899###############################################################################
3900#
3901#
3902void
3903Display(ref,...)
3904 Image::Magick ref=NO_INIT
3905 ALIAS:
3906 DisplayImage = 1
3907 display = 2
3908 displayimage = 3
3909 PPCODE:
3910 {
3911 ExceptionInfo
3912 *exception;
3913
3914 Image
3915 *image;
3916
3917 register ssize_t
3918 i;
3919
3920 struct PackageInfo
3921 *info,
3922 *package_info;
3923
3924 SV
3925 *perl_exception,
3926 *reference;
3927
3928 PERL_UNUSED_VAR(ref);
3929 PERL_UNUSED_VAR(ix);
3930 exception=AcquireExceptionInfo();
3931 perl_exception=newSVpv("",0);
3932 package_info=(struct PackageInfo *) NULL;
3933 if (sv_isobject(ST(0)) == 0)
3934 {
3935 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3936 PackageName);
3937 goto PerlException;
3938 }
3939 reference=SvRV(ST(0));
3940 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3941 if (image == (Image *) NULL)
3942 {
3943 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3944 PackageName);
3945 goto PerlException;
3946 }
3947 package_info=ClonePackageInfo(info,exception);
3948 if (items == 2)
3949 SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3950 else
3951 if (items > 2)
3952 for (i=2; i < items; i+=2)
3953 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3954 exception);
3955 (void) DisplayImages(package_info->image_info,image,exception);
3956 (void) CatchImageException(image);
3957
3958 PerlException:
3959 if (package_info != (struct PackageInfo *) NULL)
3960 DestroyPackageInfo(package_info);
3961 InheritPerlException(exception,perl_exception);
3962 exception=DestroyExceptionInfo(exception);
3963 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3964 SvPOK_on(perl_exception);
3965 ST(0)=sv_2mortal(perl_exception);
3966 XSRETURN(1);
3967 }
3968
3969#
3970###############################################################################
3971# #
3972# #
3973# #
3974# E v a l u a t e I m a g e s #
3975# #
3976# #
3977# #
3978###############################################################################
3979#
3980#
3981void
3982EvaluateImages(ref)
3983 Image::Magick ref=NO_INIT
3984 ALIAS:
3985 EvaluateImages = 1
3986 evaluateimages = 2
3987 PPCODE:
3988 {
3989 AV
3990 *av;
3991
3992 char
3993 *attribute,
3994 *p;
3995
3996 ExceptionInfo
3997 *exception;
3998
3999 HV
4000 *hv;
4001
4002 Image
4003 *image;
4004
4005 MagickEvaluateOperator
4006 op;
4007
4008 register ssize_t
4009 i;
4010
4011 struct PackageInfo
4012 *info;
4013
4014 SV
4015 *perl_exception,
4016 *reference,
4017 *rv,
4018 *sv;
4019
4020 PERL_UNUSED_VAR(ref);
4021 PERL_UNUSED_VAR(ix);
4022 exception=AcquireExceptionInfo();
4023 perl_exception=newSVpv("",0);
4024 sv=NULL;
4025 if (sv_isobject(ST(0)) == 0)
4026 {
4027 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4028 PackageName);
4029 goto PerlException;
4030 }
4031 reference=SvRV(ST(0));
4032 hv=SvSTASH(reference);
4033 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4034 if (image == (Image *) NULL)
4035 {
4036 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4037 PackageName);
4038 goto PerlException;
4039 }
4040 op=MeanEvaluateOperator;
4041 if (items == 2)
4042 {
4043 ssize_t
4044 in;
4045
4046 in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
4047 SvPV(ST(1),na));
4048 if (in < 0)
4049 {
4050 ThrowPerlException(exception,OptionError,"UnrecognizedType",
4051 SvPV(ST(1),na));
4052 return;
4053 }
4054 op=(MagickEvaluateOperator) in;
4055 }
4056 else
4057 for (i=2; i < items; i+=2)
4058 {
4059 attribute=(char *) SvPV(ST(i-1),na);
4060 switch (*attribute)
4061 {
4062 case 'O':
4063 case 'o':
4064 {
4065 if (LocaleCompare(attribute,"operator") == 0)
4066 {
4067 ssize_t
4068 in;
4069
4070 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4071 MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4072 if (in < 0)
4073 {
4074 ThrowPerlException(exception,OptionError,"UnrecognizedType",
4075 SvPV(ST(i),na));
4076 return;
4077 }
4078 op=(MagickEvaluateOperator) in;
4079 break;
4080 }
4081 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4082 attribute);
4083 break;
4084 }
4085 default:
4086 {
4087 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4088 attribute);
4089 break;
4090 }
4091 }
4092 }
4093 image=EvaluateImages(image,op,exception);
4094 if (image == (Image *) NULL)
4095 goto PerlException;
4096 /*
4097 Create blessed Perl array for the returned image.
4098 */
4099 av=newAV();
4100 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4101 SvREFCNT_dec(av);
4102 AddImageToRegistry(sv,image);
4103 rv=newRV(sv);
4104 av_push(av,sv_bless(rv,hv));
4105 SvREFCNT_dec(sv);
4106 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00004107 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4108 "evaluate-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00004109 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4110 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00004111 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004112 SetImageInfo(info->image_info,0,exception);
4113 exception=DestroyExceptionInfo(exception);
4114 SvREFCNT_dec(perl_exception);
4115 XSRETURN(1);
4116
4117 PerlException:
4118 InheritPerlException(exception,perl_exception);
4119 exception=DestroyExceptionInfo(exception);
4120 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4121 SvPOK_on(perl_exception);
4122 ST(0)=sv_2mortal(perl_exception);
4123 XSRETURN(1);
4124 }
4125
4126#
4127###############################################################################
4128# #
4129# #
4130# #
4131# F e a t u r e s #
4132# #
4133# #
4134# #
4135###############################################################################
4136#
4137#
4138void
4139Features(ref,...)
4140 Image::Magick ref=NO_INIT
4141 ALIAS:
4142 FeaturesImage = 1
4143 features = 2
4144 featuresimage = 3
4145 PPCODE:
4146 {
4147#define ChannelFeatures(channel,direction) \
4148{ \
Cristyb1710fe2017-02-11 13:51:48 -05004149 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004150 channel_features[channel].angular_second_moment[direction]); \
4151 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004152 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004153 channel_features[channel].contrast[direction]); \
4154 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004155 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004156 channel_features[channel].contrast[direction]); \
4157 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004158 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004159 channel_features[channel].variance_sum_of_squares[direction]); \
4160 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004161 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004162 channel_features[channel].inverse_difference_moment[direction]); \
4163 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004164 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004165 channel_features[channel].sum_average[direction]); \
4166 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004167 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004168 channel_features[channel].sum_variance[direction]); \
4169 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004170 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004171 channel_features[channel].sum_entropy[direction]); \
4172 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004173 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004174 channel_features[channel].entropy[direction]); \
4175 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004176 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004177 channel_features[channel].difference_variance[direction]); \
4178 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004179 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004180 channel_features[channel].difference_entropy[direction]); \
4181 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004182 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004183 channel_features[channel].measure_of_correlation_1[direction]); \
4184 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004185 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004186 channel_features[channel].measure_of_correlation_2[direction]); \
4187 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004188 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004189 channel_features[channel].maximum_correlation_coefficient[direction]); \
4190 PUSHs(sv_2mortal(newSVpv(message,0))); \
4191}
4192
4193 AV
4194 *av;
4195
4196 char
4197 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004198 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004199
4200 ChannelFeatures
4201 *channel_features;
4202
4203 double
4204 distance;
4205
4206 ExceptionInfo
4207 *exception;
4208
4209 Image
4210 *image;
4211
4212 register ssize_t
4213 i;
4214
4215 ssize_t
4216 count;
4217
4218 struct PackageInfo
4219 *info;
4220
4221 SV
4222 *perl_exception,
4223 *reference;
4224
4225 PERL_UNUSED_VAR(ref);
4226 PERL_UNUSED_VAR(ix);
4227 exception=AcquireExceptionInfo();
4228 perl_exception=newSVpv("",0);
4229 av=NULL;
4230 if (sv_isobject(ST(0)) == 0)
4231 {
4232 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4233 PackageName);
4234 goto PerlException;
4235 }
4236 reference=SvRV(ST(0));
4237 av=newAV();
4238 SvREFCNT_dec(av);
4239 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4240 if (image == (Image *) NULL)
4241 {
4242 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4243 PackageName);
4244 goto PerlException;
4245 }
cristy7dbd9262014-07-02 17:53:42 +00004246 distance=1.0;
cristy4a3ce0a2013-08-03 20:06:59 +00004247 for (i=2; i < items; i+=2)
4248 {
4249 attribute=(char *) SvPV(ST(i-1),na);
4250 switch (*attribute)
4251 {
4252 case 'D':
4253 case 'd':
4254 {
4255 if (LocaleCompare(attribute,"distance") == 0)
4256 {
4257 distance=StringToLong((char *) SvPV(ST(1),na));
4258 break;
4259 }
4260 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4261 attribute);
4262 break;
4263 }
4264 default:
4265 {
4266 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4267 attribute);
4268 break;
4269 }
4270 }
4271 }
4272 count=0;
4273 for ( ; image; image=image->next)
4274 {
Cristy5a854dc2017-02-11 15:43:46 -05004275 register ssize_t
4276 j;
4277
cristy4a3ce0a2013-08-03 20:06:59 +00004278 channel_features=GetImageFeatures(image,distance,exception);
4279 if (channel_features == (ChannelFeatures *) NULL)
4280 continue;
4281 count++;
Cristy5a854dc2017-02-11 15:43:46 -05004282 for (j=0; j < 4; j++)
cristy4a3ce0a2013-08-03 20:06:59 +00004283 {
Cristy5a854dc2017-02-11 15:43:46 -05004284 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
4285 {
4286 PixelChannel channel=GetPixelChannelChannel(image,i);
4287 PixelTrait traits=GetPixelChannelTraits(image,channel);
4288 if (traits == UndefinedPixelTrait)
4289 continue;
4290 EXTEND(sp,14*(i+1)*count);
4291 ChannelFeatures(channel,j);
4292 }
cristy4a3ce0a2013-08-03 20:06:59 +00004293 }
4294 channel_features=(ChannelFeatures *)
4295 RelinquishMagickMemory(channel_features);
4296 }
4297
4298 PerlException:
4299 InheritPerlException(exception,perl_exception);
4300 exception=DestroyExceptionInfo(exception);
4301 SvREFCNT_dec(perl_exception);
4302 }
4303
4304#
4305###############################################################################
4306# #
4307# #
4308# #
4309# F l a t t e n #
4310# #
4311# #
4312# #
4313###############################################################################
4314#
4315#
4316void
4317Flatten(ref)
4318 Image::Magick ref=NO_INIT
4319 ALIAS:
4320 FlattenImage = 1
4321 flatten = 2
4322 flattenimage = 3
4323 PPCODE:
4324 {
4325 AV
4326 *av;
4327
4328 char
4329 *attribute,
4330 *p;
4331
4332 ExceptionInfo
4333 *exception;
4334
4335 HV
4336 *hv;
4337
4338 Image
4339 *image;
4340
4341 PixelInfo
4342 background_color;
4343
4344 register ssize_t
4345 i;
4346
4347 struct PackageInfo
4348 *info;
4349
4350 SV
4351 *perl_exception,
4352 *reference,
4353 *rv,
4354 *sv;
4355
4356 PERL_UNUSED_VAR(ref);
4357 PERL_UNUSED_VAR(ix);
4358 exception=AcquireExceptionInfo();
4359 perl_exception=newSVpv("",0);
4360 sv=NULL;
4361 if (sv_isobject(ST(0)) == 0)
4362 {
4363 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4364 PackageName);
4365 goto PerlException;
4366 }
4367 reference=SvRV(ST(0));
4368 hv=SvSTASH(reference);
4369 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4370 if (image == (Image *) NULL)
4371 {
4372 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4373 PackageName);
4374 goto PerlException;
4375 }
4376 background_color=image->background_color;
4377 if (items == 2)
4378 (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4379 &background_color,exception);
4380 else
4381 for (i=2; i < items; i+=2)
4382 {
4383 attribute=(char *) SvPV(ST(i-1),na);
4384 switch (*attribute)
4385 {
4386 case 'B':
4387 case 'b':
4388 {
4389 if (LocaleCompare(attribute,"background") == 0)
4390 {
4391 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4392 AllCompliance,&background_color,exception);
4393 break;
4394 }
4395 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4396 attribute);
4397 break;
4398 }
4399 default:
4400 {
4401 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4402 attribute);
4403 break;
4404 }
4405 }
4406 }
4407 image->background_color=background_color;
4408 image=MergeImageLayers(image,FlattenLayer,exception);
4409 if (image == (Image *) NULL)
4410 goto PerlException;
4411 /*
4412 Create blessed Perl array for the returned image.
4413 */
4414 av=newAV();
4415 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4416 SvREFCNT_dec(av);
4417 AddImageToRegistry(sv,image);
4418 rv=newRV(sv);
4419 av_push(av,sv_bless(rv,hv));
4420 SvREFCNT_dec(sv);
4421 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00004422 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4423 "flatten-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00004424 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4425 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00004426 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004427 SetImageInfo(info->image_info,0,exception);
4428 exception=DestroyExceptionInfo(exception);
4429 SvREFCNT_dec(perl_exception);
4430 XSRETURN(1);
4431
4432 PerlException:
4433 InheritPerlException(exception,perl_exception);
4434 exception=DestroyExceptionInfo(exception);
4435 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4436 SvPOK_on(perl_exception); /* return messages in string context */
4437 ST(0)=sv_2mortal(perl_exception);
4438 XSRETURN(1);
4439 }
4440
4441#
4442###############################################################################
4443# #
4444# #
4445# #
4446# F x #
4447# #
4448# #
4449# #
4450###############################################################################
4451#
4452#
4453void
4454Fx(ref,...)
4455 Image::Magick ref=NO_INIT
4456 ALIAS:
4457 FxImage = 1
4458 fx = 2
4459 fximage = 3
4460 PPCODE:
4461 {
4462 AV
4463 *av;
4464
4465 char
4466 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004467 expression[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004468
4469 ChannelType
4470 channel,
4471 channel_mask;
4472
4473 ExceptionInfo
4474 *exception;
4475
4476 HV
4477 *hv;
4478
4479 Image
4480 *image;
4481
4482 register ssize_t
4483 i;
4484
4485 struct PackageInfo
4486 *info;
4487
4488 SV
4489 *av_reference,
4490 *perl_exception,
4491 *reference,
4492 *rv,
4493 *sv;
4494
4495 PERL_UNUSED_VAR(ref);
4496 PERL_UNUSED_VAR(ix);
4497 exception=AcquireExceptionInfo();
4498 perl_exception=newSVpv("",0);
4499 sv=NULL;
4500 attribute=NULL;
4501 av=NULL;
4502 if (sv_isobject(ST(0)) == 0)
4503 {
4504 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4505 PackageName);
4506 goto PerlException;
4507 }
4508 reference=SvRV(ST(0));
4509 hv=SvSTASH(reference);
4510 av=newAV();
4511 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4512 SvREFCNT_dec(av);
4513 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4514 if (image == (Image *) NULL)
4515 {
4516 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4517 PackageName);
4518 goto PerlException;
4519 }
4520 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4521 /*
4522 Get options.
4523 */
4524 channel=DefaultChannels;
cristy151b66d2015-04-15 10:50:31 +00004525 (void) CopyMagickString(expression,"u",MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004526 if (items == 2)
cristy151b66d2015-04-15 10:50:31 +00004527 (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004528 else
4529 for (i=2; i < items; i+=2)
4530 {
4531 attribute=(char *) SvPV(ST(i-1),na);
4532 switch (*attribute)
4533 {
4534 case 'C':
4535 case 'c':
4536 {
4537 if (LocaleCompare(attribute,"channel") == 0)
4538 {
4539 ssize_t
4540 option;
4541
4542 option=ParseChannelOption(SvPV(ST(i),na));
4543 if (option < 0)
4544 {
4545 ThrowPerlException(exception,OptionError,
4546 "UnrecognizedType",SvPV(ST(i),na));
4547 return;
4548 }
4549 channel=(ChannelType) option;
4550 break;
4551 }
4552 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4553 attribute);
4554 break;
4555 }
4556 case 'E':
4557 case 'e':
4558 {
4559 if (LocaleCompare(attribute,"expression") == 0)
4560 {
4561 (void) CopyMagickString(expression,SvPV(ST(i),na),
cristy151b66d2015-04-15 10:50:31 +00004562 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004563 break;
4564 }
4565 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4566 attribute);
4567 break;
4568 }
4569 default:
4570 {
4571 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4572 attribute);
4573 break;
4574 }
4575 }
4576 }
4577 channel_mask=SetImageChannelMask(image,channel);
4578 image=FxImage(image,expression,exception);
4579 if (image != (Image *) NULL)
4580 (void) SetImageChannelMask(image,channel_mask);
4581 if (image == (Image *) NULL)
4582 goto PerlException;
4583 for ( ; image; image=image->next)
4584 {
4585 AddImageToRegistry(sv,image);
4586 rv=newRV(sv);
4587 av_push(av,sv_bless(rv,hv));
4588 SvREFCNT_dec(sv);
4589 }
4590 exception=DestroyExceptionInfo(exception);
4591 ST(0)=av_reference;
4592 SvREFCNT_dec(perl_exception); /* can't return warning messages */
4593 XSRETURN(1);
4594
4595 PerlException:
4596 InheritPerlException(exception,perl_exception);
4597 exception=DestroyExceptionInfo(exception);
4598 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4599 SvPOK_on(perl_exception);
4600 ST(0)=sv_2mortal(perl_exception);
4601 XSRETURN(1);
4602 }
4603
4604#
4605###############################################################################
4606# #
4607# #
4608# #
4609# G e t #
4610# #
4611# #
4612# #
4613###############################################################################
4614#
4615#
4616void
4617Get(ref,...)
4618 Image::Magick ref=NO_INIT
4619 ALIAS:
4620 GetAttributes = 1
4621 GetAttribute = 2
4622 get = 3
4623 getattributes = 4
4624 getattribute = 5
4625 PPCODE:
4626 {
4627 char
4628 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004629 color[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004630
4631 const char
4632 *value;
4633
4634 ExceptionInfo
4635 *exception;
4636
4637 Image
4638 *image;
4639
4640 long
4641 j;
4642
4643 register ssize_t
4644 i;
4645
4646 struct PackageInfo
4647 *info;
4648
4649 SV
4650 *perl_exception,
4651 *reference,
4652 *s;
4653
4654 PERL_UNUSED_VAR(ref);
4655 PERL_UNUSED_VAR(ix);
4656 exception=AcquireExceptionInfo();
4657 perl_exception=newSVpv("",0);
4658 if (sv_isobject(ST(0)) == 0)
4659 {
4660 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4661 PackageName);
4662 XSRETURN_EMPTY;
4663 }
4664 reference=SvRV(ST(0));
4665 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4666 if (image == (Image *) NULL && !info)
4667 XSRETURN_EMPTY;
4668 EXTEND(sp,items);
4669 for (i=1; i < items; i++)
4670 {
4671 attribute=(char *) SvPV(ST(i),na);
4672 s=NULL;
4673 switch (*attribute)
4674 {
4675 case 'A':
4676 case 'a':
4677 {
4678 if (LocaleCompare(attribute,"adjoin") == 0)
4679 {
4680 if (info)
4681 s=newSViv((ssize_t) info->image_info->adjoin);
4682 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4683 continue;
4684 }
4685 if (LocaleCompare(attribute,"antialias") == 0)
4686 {
4687 if (info)
4688 s=newSViv((ssize_t) info->image_info->antialias);
4689 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4690 continue;
4691 }
4692 if (LocaleCompare(attribute,"area") == 0)
4693 {
4694 s=newSViv(GetMagickResource(AreaResource));
4695 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4696 continue;
4697 }
4698 if (LocaleCompare(attribute,"attenuate") == 0)
4699 {
4700 const char
4701 *value;
4702
4703 value=GetImageProperty(image,attribute,exception);
4704 if (value != (const char *) NULL)
4705 s=newSVpv(value,0);
4706 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4707 continue;
4708 }
4709 if (LocaleCompare(attribute,"authenticate") == 0)
4710 {
4711 if (info)
4712 {
4713 const char
4714 *option;
4715
4716 option=GetImageOption(info->image_info,attribute);
4717 if (option != (const char *) NULL)
4718 s=newSVpv(option,0);
4719 }
4720 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4721 continue;
4722 }
4723 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4724 attribute);
4725 break;
4726 }
4727 case 'B':
4728 case 'b':
4729 {
4730 if (LocaleCompare(attribute,"background") == 0)
4731 {
4732 if (image == (Image *) NULL)
4733 break;
cristy151b66d2015-04-15 10:50:31 +00004734 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004735 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4736 (double) image->background_color.green,
4737 (double) image->background_color.blue,
4738 (double) image->background_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004739 s=newSVpv(color,0);
4740 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4741 continue;
4742 }
4743 if (LocaleCompare(attribute,"base-columns") == 0)
4744 {
4745 if (image != (Image *) NULL)
4746 s=newSViv((ssize_t) image->magick_columns);
4747 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4748 continue;
4749 }
4750 if (LocaleCompare(attribute,"base-filename") == 0)
4751 {
4752 if (image != (Image *) NULL)
4753 s=newSVpv(image->magick_filename,0);
4754 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4755 continue;
4756 }
4757 if (LocaleCompare(attribute,"base-height") == 0)
4758 {
4759 if (image != (Image *) NULL)
4760 s=newSViv((ssize_t) image->magick_rows);
4761 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4762 continue;
4763 }
4764 if (LocaleCompare(attribute,"base-rows") == 0)
4765 {
4766 if (image != (Image *) NULL)
4767 s=newSViv((ssize_t) image->magick_rows);
4768 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4769 continue;
4770 }
4771 if (LocaleCompare(attribute,"base-width") == 0)
4772 {
4773 if (image != (Image *) NULL)
4774 s=newSViv((ssize_t) image->magick_columns);
4775 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4776 continue;
4777 }
4778 if (LocaleCompare(attribute,"blue-primary") == 0)
4779 {
4780 if (image == (Image *) NULL)
4781 break;
Cristyb1710fe2017-02-11 13:51:48 -05004782 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00004783 image->chromaticity.blue_primary.x,
4784 image->chromaticity.blue_primary.y);
4785 s=newSVpv(color,0);
4786 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4787 continue;
4788 }
4789 if (LocaleCompare(attribute,"bordercolor") == 0)
4790 {
4791 if (image == (Image *) NULL)
4792 break;
cristy151b66d2015-04-15 10:50:31 +00004793 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004794 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4795 (double) image->border_color.green,
4796 (double) image->border_color.blue,
4797 (double) image->border_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004798 s=newSVpv(color,0);
4799 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4800 continue;
4801 }
4802 if (LocaleCompare(attribute,"bounding-box") == 0)
4803 {
4804 char
cristy151b66d2015-04-15 10:50:31 +00004805 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004806
4807 RectangleInfo
4808 page;
4809
4810 if (image == (Image *) NULL)
4811 break;
4812 page=GetImageBoundingBox(image,exception);
cristy151b66d2015-04-15 10:50:31 +00004813 (void) FormatLocaleString(geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00004814 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4815 page.height,(double) page.x,(double) page.y);
4816 s=newSVpv(geometry,0);
4817 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4818 continue;
4819 }
4820 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4821 attribute);
4822 break;
4823 }
4824 case 'C':
4825 case 'c':
4826 {
4827 if (LocaleCompare(attribute,"class") == 0)
4828 {
4829 if (image == (Image *) NULL)
4830 break;
4831 s=newSViv(image->storage_class);
4832 (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4833 image->storage_class));
4834 SvIOK_on(s);
4835 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4836 continue;
4837 }
4838 if (LocaleCompare(attribute,"clip-mask") == 0)
4839 {
4840 if (image != (Image *) NULL)
4841 {
4842 Image
4843 *mask_image;
4844
4845 SV
4846 *sv;
4847
4848 sv=NULL;
4849 if (image->read_mask == MagickFalse)
4850 ClipImage(image,exception);
Cristyda6b91a2016-01-11 16:05:27 -05004851 mask_image=GetImageMask(image,ReadPixelMask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004852 if (mask_image != (Image *) NULL)
4853 {
4854 AddImageToRegistry(sv,mask_image);
4855 s=sv_bless(newRV(sv),SvSTASH(reference));
4856 }
4857 }
4858 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4859 continue;
4860 }
4861 if (LocaleCompare(attribute,"clip-path") == 0)
4862 {
4863 if (image != (Image *) NULL)
4864 {
4865 Image
4866 *mask_image;
4867
4868 SV
4869 *sv;
4870
4871 sv=NULL;
4872 if (image->read_mask != MagickFalse)
4873 ClipImage(image,exception);
Cristyda6b91a2016-01-11 16:05:27 -05004874 mask_image=GetImageMask(image,ReadPixelMask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004875 if (mask_image != (Image *) NULL)
4876 {
4877 AddImageToRegistry(sv,mask_image);
4878 s=sv_bless(newRV(sv),SvSTASH(reference));
4879 }
4880 }
4881 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4882 continue;
4883 }
4884 if (LocaleCompare(attribute,"compression") == 0)
4885 {
4886 j=info ? info->image_info->compression : image ?
4887 image->compression : UndefinedCompression;
4888 if (info)
4889 if (info->image_info->compression == UndefinedCompression)
4890 j=image->compression;
4891 s=newSViv(j);
4892 (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4893 j));
4894 SvIOK_on(s);
4895 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4896 continue;
4897 }
4898 if (LocaleCompare(attribute,"colorspace") == 0)
4899 {
4900 j=image ? image->colorspace : RGBColorspace;
4901 s=newSViv(j);
4902 (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4903 j));
4904 SvIOK_on(s);
4905 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4906 continue;
4907 }
4908 if (LocaleCompare(attribute,"colors") == 0)
4909 {
4910 if (image != (Image *) NULL)
4911 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4912 exception));
4913 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4914 continue;
4915 }
4916 if (LocaleNCompare(attribute,"colormap",8) == 0)
4917 {
4918 int
4919 items;
4920
4921 if (image == (Image *) NULL || !image->colormap)
4922 break;
4923 j=0;
4924 items=sscanf(attribute,"%*[^[][%ld",&j);
4925 (void) items;
4926 if (j > (ssize_t) image->colors)
4927 j%=image->colors;
cristy151b66d2015-04-15 10:50:31 +00004928 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004929 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4930 (double) image->colormap[j].green,
4931 (double) image->colormap[j].blue,
4932 (double) image->colormap[j].alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004933 s=newSVpv(color,0);
4934 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4935 continue;
4936 }
4937 if (LocaleCompare(attribute,"columns") == 0)
4938 {
4939 if (image != (Image *) NULL)
4940 s=newSViv((ssize_t) image->columns);
4941 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4942 continue;
4943 }
4944 if (LocaleCompare(attribute,"comment") == 0)
4945 {
4946 const char
4947 *value;
4948
Cristy935a4052017-03-31 17:45:37 -04004949 value=GetImageProperty(image,attribute,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004950 if (value != (const char *) NULL)
4951 s=newSVpv(value,0);
4952 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4953 continue;
4954 }
4955 if (LocaleCompare(attribute,"copyright") == 0)
4956 {
4957 s=newSVpv(GetMagickCopyright(),0);
4958 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4959 continue;
4960 }
4961 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4962 attribute);
4963 break;
4964 }
4965 case 'D':
4966 case 'd':
4967 {
4968 if (LocaleCompare(attribute,"density") == 0)
4969 {
4970 char
cristy151b66d2015-04-15 10:50:31 +00004971 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004972
4973 if (image == (Image *) NULL)
4974 break;
Cristyb1710fe2017-02-11 13:51:48 -05004975 (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00004976 image->resolution.x,image->resolution.y);
4977 s=newSVpv(geometry,0);
4978 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4979 continue;
4980 }
4981 if (LocaleCompare(attribute,"delay") == 0)
4982 {
4983 if (image != (Image *) NULL)
4984 s=newSViv((ssize_t) image->delay);
4985 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4986 continue;
4987 }
4988 if (LocaleCompare(attribute,"depth") == 0)
4989 {
4990 s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4991 if (image != (Image *) NULL)
4992 s=newSViv((ssize_t) GetImageDepth(image,exception));
4993 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4994 continue;
4995 }
4996 if (LocaleCompare(attribute,"directory") == 0)
4997 {
4998 if (image && image->directory)
4999 s=newSVpv(image->directory,0);
5000 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5001 continue;
5002 }
5003 if (LocaleCompare(attribute,"dispose") == 0)
5004 {
5005 if (image == (Image *) NULL)
5006 break;
5007
5008 s=newSViv(image->dispose);
5009 (void) sv_setpv(s,
5010 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
5011 SvIOK_on(s);
5012 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5013 continue;
5014 }
5015 if (LocaleCompare(attribute,"disk") == 0)
5016 {
5017 s=newSViv(GetMagickResource(DiskResource));
5018 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5019 continue;
5020 }
5021 if (LocaleCompare(attribute,"dither") == 0)
5022 {
5023 if (info)
5024 s=newSViv((ssize_t) info->image_info->dither);
5025 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5026 continue;
5027 }
5028 if (LocaleCompare(attribute,"display") == 0) /* same as server */
5029 {
5030 if (info && info->image_info->server_name)
5031 s=newSVpv(info->image_info->server_name,0);
5032 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5033 continue;
5034 }
5035 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5036 attribute);
5037 break;
5038 }
5039 case 'E':
5040 case 'e':
5041 {
5042 if (LocaleCompare(attribute,"elapsed-time") == 0)
5043 {
5044 if (image != (Image *) NULL)
5045 s=newSVnv(GetElapsedTime(&image->timer));
5046 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5047 continue;
5048 }
5049 if (LocaleCompare(attribute,"endian") == 0)
5050 {
5051 j=info ? info->image_info->endian : image ? image->endian :
5052 UndefinedEndian;
5053 s=newSViv(j);
5054 (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
5055 SvIOK_on(s);
5056 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5057 continue;
5058 }
5059 if (LocaleCompare(attribute,"error") == 0)
5060 {
5061 if (image != (Image *) NULL)
5062 s=newSVnv(image->error.mean_error_per_pixel);
5063 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5064 continue;
5065 }
5066 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5067 attribute);
5068 break;
5069 }
5070 case 'F':
5071 case 'f':
5072 {
5073 if (LocaleCompare(attribute,"filesize") == 0)
5074 {
5075 if (image != (Image *) NULL)
5076 s=newSViv((ssize_t) GetBlobSize(image));
5077 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5078 continue;
5079 }
5080 if (LocaleCompare(attribute,"filename") == 0)
5081 {
Cristy2273d6a2017-07-14 19:19:55 -04005082 if (info && *info->image_info->filename)
cristy4a3ce0a2013-08-03 20:06:59 +00005083 s=newSVpv(info->image_info->filename,0);
5084 if (image != (Image *) NULL)
5085 s=newSVpv(image->filename,0);
5086 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5087 continue;
5088 }
5089 if (LocaleCompare(attribute,"filter") == 0)
5090 {
5091 s=image ? newSViv(image->filter) : newSViv(0);
5092 (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5093 image->filter));
5094 SvIOK_on(s);
5095 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5096 continue;
5097 }
5098 if (LocaleCompare(attribute,"font") == 0)
5099 {
5100 if (info && info->image_info->font)
5101 s=newSVpv(info->image_info->font,0);
5102 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5103 continue;
5104 }
5105 if (LocaleCompare(attribute,"foreground") == 0)
5106 continue;
5107 if (LocaleCompare(attribute,"format") == 0)
5108 {
5109 const MagickInfo
5110 *magick_info;
5111
5112 magick_info=(const MagickInfo *) NULL;
5113 if (info && (*info->image_info->magick != '\0'))
5114 magick_info=GetMagickInfo(info->image_info->magick,exception);
5115 if (image != (Image *) NULL)
5116 magick_info=GetMagickInfo(image->magick,exception);
5117 if ((magick_info != (const MagickInfo *) NULL) &&
5118 (*magick_info->description != '\0'))
5119 s=newSVpv((char *) magick_info->description,0);
5120 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5121 continue;
5122 }
5123 if (LocaleCompare(attribute,"fuzz") == 0)
5124 {
5125 if (info)
5126 s=newSVnv(info->image_info->fuzz);
5127 if (image != (Image *) NULL)
5128 s=newSVnv(image->fuzz);
5129 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5130 continue;
5131 }
5132 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5133 attribute);
5134 break;
5135 }
5136 case 'G':
5137 case 'g':
5138 {
5139 if (LocaleCompare(attribute,"gamma") == 0)
5140 {
5141 if (image != (Image *) NULL)
5142 s=newSVnv(image->gamma);
5143 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5144 continue;
5145 }
5146 if (LocaleCompare(attribute,"geometry") == 0)
5147 {
5148 if (image && image->geometry)
5149 s=newSVpv(image->geometry,0);
5150 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5151 continue;
5152 }
5153 if (LocaleCompare(attribute,"gravity") == 0)
5154 {
5155 s=image ? newSViv(image->gravity) : newSViv(0);
5156 (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5157 image->gravity));
5158 SvIOK_on(s);
5159 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5160 continue;
5161 }
5162 if (LocaleCompare(attribute,"green-primary") == 0)
5163 {
5164 if (image == (Image *) NULL)
5165 break;
Cristyb1710fe2017-02-11 13:51:48 -05005166 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005167 image->chromaticity.green_primary.x,
5168 image->chromaticity.green_primary.y);
5169 s=newSVpv(color,0);
5170 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5171 continue;
5172 }
5173 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5174 attribute);
5175 break;
5176 }
5177 case 'H':
5178 case 'h':
5179 {
5180 if (LocaleCompare(attribute,"height") == 0)
5181 {
5182 if (image != (Image *) NULL)
5183 s=newSViv((ssize_t) image->rows);
5184 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5185 continue;
5186 }
5187 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5188 attribute);
5189 break;
5190 }
5191 case 'I':
5192 case 'i':
5193 {
5194 if (LocaleCompare(attribute,"icc") == 0)
5195 {
5196 if (image != (Image *) NULL)
5197 {
5198 const StringInfo
5199 *profile;
5200
5201 profile=GetImageProfile(image,"icc");
5202 if (profile != (StringInfo *) NULL)
5203 s=newSVpv((const char *) GetStringInfoDatum(profile),
5204 GetStringInfoLength(profile));
5205 }
5206 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5207 continue;
5208 }
5209 if (LocaleCompare(attribute,"icm") == 0)
5210 {
5211 if (image != (Image *) NULL)
5212 {
5213 const StringInfo
5214 *profile;
5215
5216 profile=GetImageProfile(image,"icm");
5217 if (profile != (const StringInfo *) NULL)
5218 s=newSVpv((const char *) GetStringInfoDatum(profile),
5219 GetStringInfoLength(profile));
5220 }
5221 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5222 continue;
5223 }
5224 if (LocaleCompare(attribute,"id") == 0)
5225 {
5226 if (image != (Image *) NULL)
5227 {
5228 char
cristy151b66d2015-04-15 10:50:31 +00005229 key[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005230
5231 MagickBooleanType
5232 status;
5233
5234 static ssize_t
5235 id = 0;
5236
cristy151b66d2015-04-15 10:50:31 +00005237 (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
cristy4a3ce0a2013-08-03 20:06:59 +00005238 id);
5239 status=SetImageRegistry(ImageRegistryType,key,image,
5240 exception);
5241 (void) status;
5242 s=newSViv(id++);
5243 }
5244 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5245 continue;
5246 }
5247 if (LocaleNCompare(attribute,"index",5) == 0)
5248 {
5249 char
cristy151b66d2015-04-15 10:50:31 +00005250 name[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005251
5252 int
5253 items;
5254
5255 long
5256 x,
5257 y;
5258
5259 register const Quantum
5260 *p;
5261
5262 CacheView
5263 *image_view;
5264
5265 if (image == (Image *) NULL)
5266 break;
5267 if (image->storage_class != PseudoClass)
5268 break;
5269 x=0;
5270 y=0;
5271 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5272 (void) items;
5273 image_view=AcquireVirtualCacheView(image,exception);
5274 p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5275 if (p != (const Quantum *) NULL)
5276 {
cristy151b66d2015-04-15 10:50:31 +00005277 (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
cristy4a3ce0a2013-08-03 20:06:59 +00005278 GetPixelIndex(image,p));
5279 s=newSVpv(name,0);
5280 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5281 }
5282 image_view=DestroyCacheView(image_view);
5283 continue;
5284 }
5285 if (LocaleCompare(attribute,"iptc") == 0)
5286 {
5287 if (image != (Image *) NULL)
5288 {
5289 const StringInfo
5290 *profile;
5291
5292 profile=GetImageProfile(image,"iptc");
5293 if (profile != (const StringInfo *) NULL)
5294 s=newSVpv((const char *) GetStringInfoDatum(profile),
5295 GetStringInfoLength(profile));
5296 }
5297 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5298 continue;
5299 }
5300 if (LocaleCompare(attribute,"iterations") == 0) /* same as loop */
5301 {
5302 if (image != (Image *) NULL)
5303 s=newSViv((ssize_t) image->iterations);
5304 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5305 continue;
5306 }
5307 if (LocaleCompare(attribute,"interlace") == 0)
5308 {
5309 j=info ? info->image_info->interlace : image ? image->interlace :
5310 UndefinedInterlace;
5311 s=newSViv(j);
5312 (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5313 j));
5314 SvIOK_on(s);
5315 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5316 continue;
5317 }
5318 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5319 attribute);
5320 break;
5321 }
5322 case 'L':
5323 case 'l':
5324 {
5325 if (LocaleCompare(attribute,"label") == 0)
5326 {
5327 const char
5328 *value;
5329
5330 if (image == (Image *) NULL)
5331 break;
Cristy935a4052017-03-31 17:45:37 -04005332 value=GetImageProperty(image,"Label",exception);
cristy4a3ce0a2013-08-03 20:06:59 +00005333 if (value != (const char *) NULL)
5334 s=newSVpv(value,0);
5335 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5336 continue;
5337 }
5338 if (LocaleCompare(attribute,"loop") == 0) /* same as iterations */
5339 {
5340 if (image != (Image *) NULL)
5341 s=newSViv((ssize_t) image->iterations);
5342 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5343 continue;
5344 }
5345 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5346 attribute);
5347 break;
5348 }
5349 case 'M':
5350 case 'm':
5351 {
5352 if (LocaleCompare(attribute,"magick") == 0)
5353 {
5354 if (info && *info->image_info->magick)
5355 s=newSVpv(info->image_info->magick,0);
5356 if (image != (Image *) NULL)
5357 s=newSVpv(image->magick,0);
5358 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5359 continue;
5360 }
5361 if (LocaleCompare(attribute,"map") == 0)
5362 {
5363 s=newSViv(GetMagickResource(MapResource));
5364 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5365 continue;
5366 }
5367 if (LocaleCompare(attribute,"maximum-error") == 0)
5368 {
5369 if (image != (Image *) NULL)
5370 s=newSVnv(image->error.normalized_maximum_error);
5371 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5372 continue;
5373 }
5374 if (LocaleCompare(attribute,"memory") == 0)
5375 {
5376 s=newSViv(GetMagickResource(MemoryResource));
5377 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5378 continue;
5379 }
5380 if (LocaleCompare(attribute,"mean-error") == 0)
5381 {
5382 if (image != (Image *) NULL)
5383 s=newSVnv(image->error.normalized_mean_error);
5384 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5385 continue;
5386 }
5387 if (LocaleCompare(attribute,"mime") == 0)
5388 {
5389 if (info && *info->image_info->magick)
5390 s=newSVpv(MagickToMime(info->image_info->magick),0);
5391 if (image != (Image *) NULL)
5392 s=newSVpv(MagickToMime(image->magick),0);
5393 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5394 continue;
5395 }
5396 if (LocaleCompare(attribute,"mattecolor") == 0)
5397 {
5398 if (image == (Image *) NULL)
5399 break;
cristy151b66d2015-04-15 10:50:31 +00005400 (void) FormatLocaleString(color,MagickPathExtent,
Cristy8645e042016-02-03 16:35:29 -05005401 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5402 (double) image->alpha_color.green,
5403 (double) image->alpha_color.blue,
5404 (double) image->alpha_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00005405 s=newSVpv(color,0);
5406 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5407 continue;
5408 }
5409 if (LocaleCompare(attribute,"matte") == 0)
5410 {
5411 if (image != (Image *) NULL)
cristy17f11b02014-12-20 19:37:04 +00005412 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
cristy4a3ce0a2013-08-03 20:06:59 +00005413 1 : 0);
5414 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5415 continue;
5416 }
5417 if (LocaleCompare(attribute,"mime") == 0)
5418 {
5419 const char
5420 *magick;
5421
5422 magick=NULL;
5423 if (info && *info->image_info->magick)
5424 magick=info->image_info->magick;
5425 if (image != (Image *) NULL)
5426 magick=image->magick;
5427 if (magick)
5428 {
5429 char
5430 *mime;
5431
5432 mime=MagickToMime(magick);
5433 s=newSVpv(mime,0);
5434 mime=(char *) RelinquishMagickMemory(mime);
5435 }
5436 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5437 continue;
5438 }
5439 if (LocaleCompare(attribute,"monochrome") == 0)
5440 {
5441 if (image == (Image *) NULL)
5442 continue;
5443 j=info ? info->image_info->monochrome :
cristy932cb072015-04-13 20:06:25 +00005444 SetImageMonochrome(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00005445 s=newSViv(j);
5446 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5447 continue;
5448 }
5449 if (LocaleCompare(attribute,"montage") == 0)
5450 {
5451 if (image && image->montage)
5452 s=newSVpv(image->montage,0);
5453 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5454 continue;
5455 }
5456 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5457 attribute);
5458 break;
5459 }
5460 case 'O':
5461 case 'o':
5462 {
5463 if (LocaleCompare(attribute,"orientation") == 0)
5464 {
5465 j=info ? info->image_info->orientation : image ?
5466 image->orientation : UndefinedOrientation;
5467 s=newSViv(j);
5468 (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5469 j));
5470 SvIOK_on(s);
5471 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5472 continue;
5473 }
5474 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5475 attribute);
5476 break;
5477 }
5478 case 'P':
5479 case 'p':
5480 {
5481 if (LocaleCompare(attribute,"page") == 0)
5482 {
5483 if (info && info->image_info->page)
5484 s=newSVpv(info->image_info->page,0);
5485 if (image != (Image *) NULL)
5486 {
5487 char
cristy151b66d2015-04-15 10:50:31 +00005488 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005489
cristy151b66d2015-04-15 10:50:31 +00005490 (void) FormatLocaleString(geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00005491 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5492 (double) image->page.height,(double) image->page.x,(double)
5493 image->page.y);
5494 s=newSVpv(geometry,0);
5495 }
5496 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5497 continue;
5498 }
5499 if (LocaleCompare(attribute,"page.x") == 0)
5500 {
5501 if (image != (Image *) NULL)
5502 s=newSViv((ssize_t) image->page.x);
5503 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5504 continue;
5505 }
5506 if (LocaleCompare(attribute,"page.y") == 0)
5507 {
5508 if (image != (Image *) NULL)
5509 s=newSViv((ssize_t) image->page.y);
5510 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5511 continue;
5512 }
5513 if (LocaleNCompare(attribute,"pixel",5) == 0)
5514 {
5515 char
cristy151b66d2015-04-15 10:50:31 +00005516 tuple[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005517
5518 int
5519 items;
5520
5521 long
5522 x,
5523 y;
5524
5525 register const Quantum
5526 *p;
5527
5528 if (image == (Image *) NULL)
5529 break;
5530 x=0;
5531 y=0;
5532 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5533 (void) items;
5534 p=GetVirtualPixels(image,x,y,1,1,exception);
5535 if (image->colorspace != CMYKColorspace)
cristy151b66d2015-04-15 10:50:31 +00005536 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
cristy4a3ce0a2013-08-03 20:06:59 +00005537 QuantumFormat "," QuantumFormat "," QuantumFormat,
5538 GetPixelRed(image,p),GetPixelGreen(image,p),
5539 GetPixelBlue(image,p),GetPixelAlpha(image,p));
5540 else
cristy151b66d2015-04-15 10:50:31 +00005541 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
cristy4a3ce0a2013-08-03 20:06:59 +00005542 QuantumFormat "," QuantumFormat "," QuantumFormat ","
5543 QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5544 GetPixelBlue(image,p),GetPixelBlack(image,p),
5545 GetPixelAlpha(image,p));
5546 s=newSVpv(tuple,0);
5547 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5548 continue;
5549 }
5550 if (LocaleCompare(attribute,"pointsize") == 0)
5551 {
5552 if (info)
5553 s=newSViv((ssize_t) info->image_info->pointsize);
5554 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5555 continue;
5556 }
cristy4a3ce0a2013-08-03 20:06:59 +00005557 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5558 attribute);
5559 break;
5560 }
5561 case 'Q':
5562 case 'q':
5563 {
5564 if (LocaleCompare(attribute,"quality") == 0)
5565 {
5566 if (info)
5567 s=newSViv((ssize_t) info->image_info->quality);
5568 if (image != (Image *) NULL)
5569 s=newSViv((ssize_t) image->quality);
5570 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5571 continue;
5572 }
5573 if (LocaleCompare(attribute,"quantum") == 0)
5574 {
5575 if (info)
5576 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5577 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5578 continue;
5579 }
5580 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5581 attribute);
5582 break;
5583 }
5584 case 'R':
5585 case 'r':
5586 {
5587 if (LocaleCompare(attribute,"rendering-intent") == 0)
5588 {
5589 s=newSViv(image->rendering_intent);
5590 (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5591 image->rendering_intent));
5592 SvIOK_on(s);
5593 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5594 continue;
5595 }
5596 if (LocaleCompare(attribute,"red-primary") == 0)
5597 {
5598 if (image == (Image *) NULL)
5599 break;
Cristyb1710fe2017-02-11 13:51:48 -05005600 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005601 image->chromaticity.red_primary.x,
5602 image->chromaticity.red_primary.y);
5603 s=newSVpv(color,0);
5604 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5605 continue;
5606 }
5607 if (LocaleCompare(attribute,"rows") == 0)
5608 {
5609 if (image != (Image *) NULL)
5610 s=newSViv((ssize_t) image->rows);
5611 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5612 continue;
5613 }
5614 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5615 attribute);
5616 break;
5617 }
5618 case 'S':
5619 case 's':
5620 {
5621 if (LocaleCompare(attribute,"sampling-factor") == 0)
5622 {
5623 if (info && info->image_info->sampling_factor)
5624 s=newSVpv(info->image_info->sampling_factor,0);
5625 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5626 continue;
5627 }
5628 if (LocaleCompare(attribute,"server") == 0) /* same as display */
5629 {
5630 if (info && info->image_info->server_name)
5631 s=newSVpv(info->image_info->server_name,0);
5632 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5633 continue;
5634 }
5635 if (LocaleCompare(attribute,"size") == 0)
5636 {
5637 if (info && info->image_info->size)
5638 s=newSVpv(info->image_info->size,0);
5639 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5640 continue;
5641 }
5642 if (LocaleCompare(attribute,"scene") == 0)
5643 {
5644 if (image != (Image *) NULL)
5645 s=newSViv((ssize_t) image->scene);
5646 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5647 continue;
5648 }
5649 if (LocaleCompare(attribute,"scenes") == 0)
5650 {
5651 if (image != (Image *) NULL)
5652 s=newSViv((ssize_t) info->image_info->number_scenes);
5653 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5654 continue;
5655 }
5656 if (LocaleCompare(attribute,"signature") == 0)
5657 {
5658 const char
5659 *value;
5660
5661 if (image == (Image *) NULL)
5662 break;
5663 (void) SignatureImage(image,exception);
5664 value=GetImageProperty(image,"Signature",exception);
5665 if (value != (const char *) NULL)
5666 s=newSVpv(value,0);
5667 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5668 continue;
5669 }
5670 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5671 attribute);
5672 break;
5673 }
5674 case 'T':
5675 case 't':
5676 {
5677 if (LocaleCompare(attribute,"taint") == 0)
5678 {
5679 if (image != (Image *) NULL)
5680 s=newSViv((ssize_t) IsTaintImage(image));
5681 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5682 continue;
5683 }
5684 if (LocaleCompare(attribute,"texture") == 0)
5685 {
5686 if (info && info->image_info->texture)
5687 s=newSVpv(info->image_info->texture,0);
5688 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5689 continue;
5690 }
5691 if (LocaleCompare(attribute,"total-ink-density") == 0)
5692 {
5693 s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5694 if (image != (Image *) NULL)
5695 s=newSVnv(GetImageTotalInkDensity(image,exception));
5696 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5697 continue;
5698 }
5699 if (LocaleCompare(attribute,"transparent-color") == 0)
5700 {
5701 if (image == (Image *) NULL)
5702 break;
cristy151b66d2015-04-15 10:50:31 +00005703 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00005704 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5705 (double) image->transparent_color.green,
5706 (double) image->transparent_color.blue,
5707 (double) image->transparent_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00005708 s=newSVpv(color,0);
5709 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5710 continue;
5711 }
5712 if (LocaleCompare(attribute,"type") == 0)
5713 {
5714 if (image == (Image *) NULL)
5715 break;
cristya26f54c2015-07-29 12:26:12 +00005716 j=(ssize_t) GetImageType(image);
cristy4a3ce0a2013-08-03 20:06:59 +00005717 s=newSViv(j);
5718 (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5719 SvIOK_on(s);
5720 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5721 continue;
5722 }
5723 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5724 attribute);
5725 break;
5726 }
5727 case 'U':
5728 case 'u':
5729 {
5730 if (LocaleCompare(attribute,"units") == 0)
5731 {
5732 j=info ? info->image_info->units : image ? image->units :
5733 UndefinedResolution;
5734 if (info && (info->image_info->units == UndefinedResolution))
5735 if (image)
5736 j=image->units;
5737 if (j == UndefinedResolution)
5738 s=newSVpv("undefined units",0);
5739 else
5740 if (j == PixelsPerInchResolution)
5741 s=newSVpv("pixels / inch",0);
5742 else
5743 s=newSVpv("pixels / centimeter",0);
5744 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5745 continue;
5746 }
5747 if (LocaleCompare(attribute,"user-time") == 0)
5748 {
5749 if (image != (Image *) NULL)
5750 s=newSVnv(GetUserTime(&image->timer));
5751 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5752 continue;
5753 }
5754 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5755 attribute);
5756 break;
5757 }
5758 case 'V':
5759 case 'v':
5760 {
5761 if (LocaleCompare(attribute,"verbose") == 0)
5762 {
5763 if (info)
5764 s=newSViv((ssize_t) info->image_info->verbose);
5765 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5766 continue;
5767 }
5768 if (LocaleCompare(attribute,"version") == 0)
5769 {
5770 s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5771 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5772 continue;
5773 }
cristy4a3ce0a2013-08-03 20:06:59 +00005774 if (LocaleCompare(attribute,"virtual-pixel") == 0)
5775 {
5776 if (image == (Image *) NULL)
5777 break;
5778 j=(ssize_t) GetImageVirtualPixelMethod(image);
5779 s=newSViv(j);
5780 (void) sv_setpv(s,CommandOptionToMnemonic(
5781 MagickVirtualPixelOptions,j));
5782 SvIOK_on(s);
5783 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5784 continue;
5785 }
5786 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5787 attribute);
5788 break;
5789 }
5790 case 'W':
5791 case 'w':
5792 {
5793 if (LocaleCompare(attribute,"white-point") == 0)
5794 {
5795 if (image == (Image *) NULL)
5796 break;
Cristyb1710fe2017-02-11 13:51:48 -05005797 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005798 image->chromaticity.white_point.x,
5799 image->chromaticity.white_point.y);
5800 s=newSVpv(color,0);
5801 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5802 continue;
5803 }
5804 if (LocaleCompare(attribute,"width") == 0)
5805 {
5806 if (image != (Image *) NULL)
5807 s=newSViv((ssize_t) image->columns);
5808 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5809 continue;
5810 }
5811 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5812 attribute);
5813 break;
5814 }
5815 case 'X':
5816 case 'x':
5817 {
Cristyc1f9f9f2016-01-05 08:19:28 -05005818 if (LocaleCompare(attribute,"xmp") == 0)
5819 {
5820 if (image != (Image *) NULL)
5821 {
5822 const StringInfo
5823 *profile;
5824
5825 profile=GetImageProfile(image,"xmp");
5826 if (profile != (StringInfo *) NULL)
5827 s=newSVpv((const char *) GetStringInfoDatum(profile),
5828 GetStringInfoLength(profile));
5829 }
5830 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5831 continue;
5832 }
cristy4a3ce0a2013-08-03 20:06:59 +00005833 if (LocaleCompare(attribute,"x-resolution") == 0)
5834 {
5835 if (image != (Image *) NULL)
5836 s=newSVnv(image->resolution.x);
5837 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5838 continue;
5839 }
5840 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5841 attribute);
5842 break;
5843 }
5844 case 'Y':
5845 case 'y':
5846 {
5847 if (LocaleCompare(attribute,"y-resolution") == 0)
5848 {
5849 if (image != (Image *) NULL)
5850 s=newSVnv(image->resolution.y);
5851 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5852 continue;
5853 }
5854 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5855 attribute);
5856 break;
5857 }
5858 default:
5859 break;
5860 }
5861 if (image == (Image *) NULL)
5862 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5863 attribute)
5864 else
5865 {
5866 value=GetImageProperty(image,attribute,exception);
5867 if (value != (const char *) NULL)
5868 {
5869 s=newSVpv(value,0);
5870 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5871 }
5872 else
5873 if (*attribute != '%')
5874 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5875 attribute)
5876 else
5877 {
5878 char
5879 *meta;
5880
5881 meta=InterpretImageProperties(info ? info->image_info :
5882 (ImageInfo *) NULL,image,attribute,exception);
5883 s=newSVpv(meta,0);
5884 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5885 meta=(char *) RelinquishMagickMemory(meta);
5886 }
5887 }
5888 }
5889 exception=DestroyExceptionInfo(exception);
5890 SvREFCNT_dec(perl_exception); /* can't return warning messages */
5891 }
5892
5893#
5894###############################################################################
5895# #
5896# #
5897# #
5898# G e t A u t h e n t i c P i x e l s #
5899# #
5900# #
5901# #
5902###############################################################################
5903#
5904#
5905void *
5906GetAuthenticPixels(ref,...)
5907 Image::Magick ref = NO_INIT
5908 ALIAS:
5909 getauthenticpixels = 1
5910 GetImagePixels = 2
5911 getimagepixels = 3
5912 CODE:
5913 {
5914 char
5915 *attribute;
5916
5917 ExceptionInfo
5918 *exception;
5919
5920 Image
5921 *image;
5922
5923 RectangleInfo
5924 region;
5925
5926 ssize_t
5927 i;
5928
5929 struct PackageInfo
5930 *info;
5931
5932 SV
5933 *perl_exception,
5934 *reference;
5935
5936 void
5937 *blob = NULL;
5938
5939 PERL_UNUSED_VAR(ref);
5940 PERL_UNUSED_VAR(ix);
5941 exception=AcquireExceptionInfo();
5942 perl_exception=newSVpv("",0);
5943 if (sv_isobject(ST(0)) == 0)
5944 {
5945 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5946 PackageName);
5947 goto PerlException;
5948 }
5949 reference=SvRV(ST(0));
5950
5951 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5952 if (image == (Image *) NULL)
5953 {
5954 ThrowPerlException(exception,OptionError,"NoImagesDefined",
5955 PackageName);
5956 goto PerlException;
5957 }
5958
5959 region.x=0;
5960 region.y=0;
5961 region.width=image->columns;
5962 region.height=1;
5963 if (items == 1)
5964 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5965 for (i=2; i < items; i+=2)
5966 {
5967 attribute=(char *) SvPV(ST(i-1),na);
5968 switch (*attribute)
5969 {
5970 case 'g':
5971 case 'G':
5972 {
5973 if (LocaleCompare(attribute,"geometry") == 0)
5974 {
5975 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5976 break;
5977 }
5978 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5979 attribute);
5980 break;
5981 }
5982 case 'H':
5983 case 'h':
5984 {
5985 if (LocaleCompare(attribute,"height") == 0)
5986 {
5987 region.height=SvIV(ST(i));
5988 continue;
5989 }
5990 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5991 attribute);
5992 break;
5993 }
5994 case 'X':
5995 case 'x':
5996 {
5997 if (LocaleCompare(attribute,"x") == 0)
5998 {
5999 region.x=SvIV(ST(i));
6000 continue;
6001 }
6002 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6003 attribute);
6004 break;
6005 }
6006 case 'Y':
6007 case 'y':
6008 {
6009 if (LocaleCompare(attribute,"y") == 0)
6010 {
6011 region.y=SvIV(ST(i));
6012 continue;
6013 }
6014 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6015 attribute);
6016 break;
6017 }
6018 case 'W':
6019 case 'w':
6020 {
6021 if (LocaleCompare(attribute,"width") == 0)
6022 {
6023 region.width=SvIV(ST(i));
6024 continue;
6025 }
6026 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6027 attribute);
6028 break;
6029 }
6030 }
6031 }
6032 blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
6033 region.height,exception);
6034 if (blob != (void *) NULL)
6035 goto PerlEnd;
6036
6037 PerlException:
6038 InheritPerlException(exception,perl_exception);
6039 exception=DestroyExceptionInfo(exception);
6040 SvREFCNT_dec(perl_exception); /* throw away all errors */
6041
6042 PerlEnd:
6043 RETVAL = blob;
6044 }
6045 OUTPUT:
6046 RETVAL
6047
6048#
6049###############################################################################
6050# #
6051# #
6052# #
6053# G e t V i r t u a l P i x e l s #
6054# #
6055# #
6056# #
6057###############################################################################
6058#
6059#
6060void *
6061GetVirtualPixels(ref,...)
6062 Image::Magick ref = NO_INIT
6063 ALIAS:
6064 getvirtualpixels = 1
6065 AcquireImagePixels = 2
6066 acquireimagepixels = 3
6067 CODE:
6068 {
6069 char
6070 *attribute;
6071
6072 const void
6073 *blob = NULL;
6074
6075 ExceptionInfo
6076 *exception;
6077
6078 Image
6079 *image;
6080
6081 RectangleInfo
6082 region;
6083
6084 ssize_t
6085 i;
6086
6087 struct PackageInfo
6088 *info;
6089
6090 SV
6091 *perl_exception,
6092 *reference;
6093
6094 PERL_UNUSED_VAR(ref);
6095 PERL_UNUSED_VAR(ix);
6096 exception=AcquireExceptionInfo();
6097 perl_exception=newSVpv("",0);
6098 if (sv_isobject(ST(0)) == 0)
6099 {
6100 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6101 PackageName);
6102 goto PerlException;
6103 }
6104 reference=SvRV(ST(0));
6105
6106 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6107 if (image == (Image *) NULL)
6108 {
6109 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6110 PackageName);
6111 goto PerlException;
6112 }
6113
6114 region.x=0;
6115 region.y=0;
6116 region.width=image->columns;
6117 region.height=1;
6118 if (items == 1)
6119 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6120 for (i=2; i < items; i+=2)
6121 {
6122 attribute=(char *) SvPV(ST(i-1),na);
6123 switch (*attribute)
6124 {
6125 case 'g':
6126 case 'G':
6127 {
6128 if (LocaleCompare(attribute,"geometry") == 0)
6129 {
6130 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6131 break;
6132 }
6133 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6134 attribute);
6135 break;
6136 }
6137 case 'H':
6138 case 'h':
6139 {
6140 if (LocaleCompare(attribute,"height") == 0)
6141 {
6142 region.height=SvIV(ST(i));
6143 continue;
6144 }
6145 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6146 attribute);
6147 break;
6148 }
6149 case 'X':
6150 case 'x':
6151 {
6152 if (LocaleCompare(attribute,"x") == 0)
6153 {
6154 region.x=SvIV(ST(i));
6155 continue;
6156 }
6157 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6158 attribute);
6159 break;
6160 }
6161 case 'Y':
6162 case 'y':
6163 {
6164 if (LocaleCompare(attribute,"y") == 0)
6165 {
6166 region.y=SvIV(ST(i));
6167 continue;
6168 }
6169 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6170 attribute);
6171 break;
6172 }
6173 case 'W':
6174 case 'w':
6175 {
6176 if (LocaleCompare(attribute,"width") == 0)
6177 {
6178 region.width=SvIV(ST(i));
6179 continue;
6180 }
6181 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6182 attribute);
6183 break;
6184 }
6185 }
6186 }
6187 blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6188 region.height,exception);
6189 if (blob != (void *) NULL)
6190 goto PerlEnd;
6191
6192 PerlException:
6193 InheritPerlException(exception,perl_exception);
6194 exception=DestroyExceptionInfo(exception);
6195 SvREFCNT_dec(perl_exception); /* throw away all errors */
6196
6197 PerlEnd:
6198 RETVAL = (void *) blob;
6199 }
6200 OUTPUT:
6201 RETVAL
6202
6203#
6204###############################################################################
6205# #
6206# #
6207# #
6208# G e t A u t h e n t i c M e t a c o n t e n t #
6209# #
6210# #
6211# #
6212###############################################################################
6213#
6214#
6215void *
6216GetAuthenticMetacontent(ref,...)
6217 Image::Magick ref = NO_INIT
6218 ALIAS:
6219 getauthenticmetacontent = 1
6220 GetMetacontent = 2
6221 getmetacontent = 3
6222 CODE:
6223 {
6224 ExceptionInfo
6225 *exception;
6226
6227 Image
6228 *image;
6229
6230 struct PackageInfo
6231 *info;
6232
6233 SV
6234 *perl_exception,
6235 *reference;
6236
6237 void
6238 *blob = NULL;
6239
6240 PERL_UNUSED_VAR(ref);
6241 PERL_UNUSED_VAR(ix);
6242 exception=AcquireExceptionInfo();
6243 perl_exception=newSVpv("",0);
6244 if (sv_isobject(ST(0)) == 0)
6245 {
6246 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6247 PackageName);
6248 goto PerlException;
6249 }
6250 reference=SvRV(ST(0));
6251
6252 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6253 if (image == (Image *) NULL)
6254 {
6255 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6256 PackageName);
6257 goto PerlException;
6258 }
6259
6260 blob=(void *) GetAuthenticMetacontent(image);
6261 if (blob != (void *) NULL)
6262 goto PerlEnd;
6263
6264 PerlException:
6265 InheritPerlException(exception,perl_exception);
6266 exception=DestroyExceptionInfo(exception);
6267 SvREFCNT_dec(perl_exception); /* throw away all errors */
6268
6269 PerlEnd:
6270 RETVAL = blob;
6271 }
6272 OUTPUT:
6273 RETVAL
6274
6275#
6276###############################################################################
6277# #
6278# #
6279# #
6280# G e t V i r t u a l M e t a c o n t e n t #
6281# #
6282# #
6283# #
6284###############################################################################
6285#
6286#
6287void *
6288GetVirtualMetacontent(ref,...)
6289 Image::Magick ref = NO_INIT
6290 ALIAS:
6291 getvirtualmetacontent = 1
6292 CODE:
6293 {
6294 ExceptionInfo
6295 *exception;
6296
6297 Image
6298 *image;
6299
6300 struct PackageInfo
6301 *info;
6302
6303 SV
6304 *perl_exception,
6305 *reference;
6306
6307 void
6308 *blob = NULL;
6309
6310 PERL_UNUSED_VAR(ref);
6311 PERL_UNUSED_VAR(ix);
6312 exception=AcquireExceptionInfo();
6313 perl_exception=newSVpv("",0);
6314 if (sv_isobject(ST(0)) == 0)
6315 {
6316 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6317 PackageName);
6318 goto PerlException;
6319 }
6320 reference=SvRV(ST(0));
6321
6322 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6323 if (image == (Image *) NULL)
6324 {
6325 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6326 PackageName);
6327 goto PerlException;
6328 }
6329
6330 blob=(void *) GetVirtualMetacontent(image);
6331 if (blob != (void *) NULL)
6332 goto PerlEnd;
6333
6334 PerlException:
6335 InheritPerlException(exception,perl_exception);
6336 exception=DestroyExceptionInfo(exception);
6337 SvREFCNT_dec(perl_exception); /* throw away all errors */
6338
6339 PerlEnd:
6340 RETVAL = blob;
6341 }
6342 OUTPUT:
6343 RETVAL
6344
6345#
6346###############################################################################
6347# #
6348# #
6349# #
6350# H i s t o g r a m #
6351# #
6352# #
6353# #
6354###############################################################################
6355#
6356#
6357void
6358Histogram(ref,...)
6359 Image::Magick ref=NO_INIT
6360 ALIAS:
6361 HistogramImage = 1
6362 histogram = 2
6363 histogramimage = 3
6364 PPCODE:
6365 {
6366 AV
6367 *av;
6368
6369 char
cristy151b66d2015-04-15 10:50:31 +00006370 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00006371
6372 PixelInfo
6373 *histogram;
6374
6375 ExceptionInfo
6376 *exception;
6377
6378 Image
6379 *image;
6380
6381 register ssize_t
6382 i;
6383
6384 ssize_t
6385 count;
6386
6387 struct PackageInfo
6388 *info;
6389
6390 SV
6391 *perl_exception,
6392 *reference;
6393
6394 size_t
6395 number_colors;
6396
6397 PERL_UNUSED_VAR(ref);
6398 PERL_UNUSED_VAR(ix);
6399 exception=AcquireExceptionInfo();
6400 perl_exception=newSVpv("",0);
6401 av=NULL;
6402 if (sv_isobject(ST(0)) == 0)
6403 {
6404 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6405 PackageName);
6406 goto PerlException;
6407 }
6408 reference=SvRV(ST(0));
6409 av=newAV();
6410 SvREFCNT_dec(av);
6411 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6412 if (image == (Image *) NULL)
6413 {
6414 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6415 PackageName);
6416 goto PerlException;
6417 }
cristy4a3ce0a2013-08-03 20:06:59 +00006418 count=0;
6419 for ( ; image; image=image->next)
6420 {
6421 histogram=GetImageHistogram(image,&number_colors,exception);
6422 if (histogram == (PixelInfo *) NULL)
6423 continue;
6424 count+=(ssize_t) number_colors;
6425 EXTEND(sp,6*count);
6426 for (i=0; i < (ssize_t) number_colors; i++)
6427 {
cristy151b66d2015-04-15 10:50:31 +00006428 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006429 histogram[i].red);
6430 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006431 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006432 histogram[i].green);
6433 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006434 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006435 histogram[i].blue);
6436 PUSHs(sv_2mortal(newSVpv(message,0)));
6437 if (image->colorspace == CMYKColorspace)
6438 {
cristy151b66d2015-04-15 10:50:31 +00006439 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006440 histogram[i].black);
6441 PUSHs(sv_2mortal(newSVpv(message,0)));
6442 }
cristy151b66d2015-04-15 10:50:31 +00006443 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006444 histogram[i].alpha);
6445 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006446 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
cristy4a3ce0a2013-08-03 20:06:59 +00006447 histogram[i].count);
6448 PUSHs(sv_2mortal(newSVpv(message,0)));
6449 }
6450 histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6451 }
6452
6453 PerlException:
6454 InheritPerlException(exception,perl_exception);
6455 exception=DestroyExceptionInfo(exception);
6456 SvREFCNT_dec(perl_exception);
6457 }
6458
6459#
6460###############################################################################
6461# #
6462# #
6463# #
6464# G e t P i x e l #
6465# #
6466# #
6467# #
6468###############################################################################
6469#
6470#
6471void
6472GetPixel(ref,...)
6473 Image::Magick ref=NO_INIT
6474 ALIAS:
6475 getpixel = 1
6476 getPixel = 2
6477 PPCODE:
6478 {
6479 AV
6480 *av;
6481
6482 char
6483 *attribute;
6484
6485 ExceptionInfo
6486 *exception;
6487
6488 Image
6489 *image;
6490
6491 MagickBooleanType
6492 normalize;
6493
6494 RectangleInfo
6495 region;
6496
6497 register const Quantum
6498 *p;
6499
6500 register ssize_t
6501 i;
6502
6503 ssize_t
6504 option;
6505
6506 struct PackageInfo
6507 *info;
6508
6509 SV
6510 *perl_exception,
6511 *reference; /* reference is the SV* of ref=SvIV(reference) */
6512
6513 PERL_UNUSED_VAR(ref);
6514 PERL_UNUSED_VAR(ix);
6515 exception=AcquireExceptionInfo();
6516 perl_exception=newSVpv("",0);
6517 reference=SvRV(ST(0));
6518 av=(AV *) reference;
6519 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6520 exception);
6521 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6522 if (image == (Image *) NULL)
6523 {
6524 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6525 PackageName);
6526 goto PerlException;
6527 }
6528 normalize=MagickTrue;
6529 region.x=0;
6530 region.y=0;
6531 region.width=image->columns;
6532 region.height=1;
6533 if (items == 1)
6534 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6535 for (i=2; i < items; i+=2)
6536 {
6537 attribute=(char *) SvPV(ST(i-1),na);
6538 switch (*attribute)
6539 {
6540 case 'C':
6541 case 'c':
6542 {
6543 if (LocaleCompare(attribute,"channel") == 0)
6544 {
6545 ssize_t
6546 option;
6547
6548 option=ParseChannelOption(SvPV(ST(i),na));
6549 if (option < 0)
6550 {
6551 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6552 SvPV(ST(i),na));
6553 return;
6554 }
cristybcd59342015-06-07 14:07:19 +00006555 (void) SetPixelChannelMask(image,(ChannelType) option);
cristy4a3ce0a2013-08-03 20:06:59 +00006556 break;
6557 }
6558 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6559 attribute);
6560 break;
6561 }
6562 case 'g':
6563 case 'G':
6564 {
6565 if (LocaleCompare(attribute,"geometry") == 0)
6566 {
6567 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6568 break;
6569 }
6570 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6571 attribute);
6572 break;
6573 }
6574 case 'N':
6575 case 'n':
6576 {
6577 if (LocaleCompare(attribute,"normalize") == 0)
6578 {
6579 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6580 SvPV(ST(i),na));
6581 if (option < 0)
6582 {
6583 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6584 SvPV(ST(i),na));
6585 break;
6586 }
6587 normalize=option != 0 ? MagickTrue : MagickFalse;
6588 break;
6589 }
6590 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6591 attribute);
6592 break;
6593 }
6594 case 'x':
6595 case 'X':
6596 {
6597 if (LocaleCompare(attribute,"x") == 0)
6598 {
6599 region.x=SvIV(ST(i));
6600 break;
6601 }
6602 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6603 attribute);
6604 break;
6605 }
6606 case 'y':
6607 case 'Y':
6608 {
6609 if (LocaleCompare(attribute,"y") == 0)
6610 {
6611 region.y=SvIV(ST(i));
6612 break;
6613 }
6614 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6615 attribute);
6616 break;
6617 }
6618 default:
6619 {
6620 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6621 attribute);
6622 break;
6623 }
6624 }
6625 }
6626 p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6627 if (p == (const Quantum *) NULL)
6628 PUSHs(&sv_undef);
6629 else
6630 {
6631 double
6632 scale;
6633
6634 scale=1.0;
6635 if (normalize != MagickFalse)
6636 scale=1.0/QuantumRange;
6637 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6638 PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6639 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6640 PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6641 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6642 PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6643 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6644 (image->colorspace == CMYKColorspace))
6645 PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6646 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6647 PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6648 }
6649
6650 PerlException:
6651 InheritPerlException(exception,perl_exception);
6652 exception=DestroyExceptionInfo(exception);
6653 SvREFCNT_dec(perl_exception);
6654 }
6655
6656#
6657###############################################################################
6658# #
6659# #
6660# #
6661# G e t P i x e l s #
6662# #
6663# #
6664# #
6665###############################################################################
6666#
6667#
6668void
6669GetPixels(ref,...)
6670 Image::Magick ref=NO_INIT
6671 ALIAS:
6672 getpixels = 1
6673 getPixels = 2
6674 PPCODE:
6675 {
6676 AV
6677 *av;
6678
6679 char
6680 *attribute;
6681
6682 const char
6683 *map;
6684
6685 ExceptionInfo
6686 *exception;
6687
6688 Image
6689 *image;
6690
6691 MagickBooleanType
6692 normalize,
6693 status;
6694
6695 RectangleInfo
6696 region;
6697
6698 register ssize_t
6699 i;
6700
6701 ssize_t
6702 option;
6703
6704 struct PackageInfo
6705 *info;
6706
6707 SV
6708 *perl_exception,
6709 *reference; /* reference is the SV* of ref=SvIV(reference) */
6710
6711 PERL_UNUSED_VAR(ref);
6712 PERL_UNUSED_VAR(ix);
6713 exception=AcquireExceptionInfo();
6714 perl_exception=newSVpv("",0);
6715 reference=SvRV(ST(0));
6716 av=(AV *) reference;
6717 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6718 exception);
6719 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6720 if (image == (Image *) NULL)
6721 {
6722 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6723 PackageName);
6724 goto PerlException;
6725 }
6726 map="RGB";
cristy17f11b02014-12-20 19:37:04 +00006727 if (image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00006728 map="RGBA";
6729 if (image->colorspace == CMYKColorspace)
6730 {
6731 map="CMYK";
cristy17f11b02014-12-20 19:37:04 +00006732 if (image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00006733 map="CMYKA";
6734 }
6735 normalize=MagickFalse;
6736 region.x=0;
6737 region.y=0;
6738 region.width=image->columns;
6739 region.height=1;
6740 if (items == 1)
6741 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6742 for (i=2; i < items; i+=2)
6743 {
6744 attribute=(char *) SvPV(ST(i-1),na);
6745 switch (*attribute)
6746 {
6747 case 'g':
6748 case 'G':
6749 {
6750 if (LocaleCompare(attribute,"geometry") == 0)
6751 {
6752 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6753 break;
6754 }
6755 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6756 attribute);
6757 break;
6758 }
6759 case 'H':
6760 case 'h':
6761 {
6762 if (LocaleCompare(attribute,"height") == 0)
6763 {
6764 region.height=SvIV(ST(i));
6765 break;
6766 }
6767 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6768 attribute);
6769 break;
6770 }
6771 case 'M':
6772 case 'm':
6773 {
6774 if (LocaleCompare(attribute,"map") == 0)
6775 {
6776 map=SvPV(ST(i),na);
6777 break;
6778 }
6779 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6780 attribute);
6781 break;
6782 }
6783 case 'N':
6784 case 'n':
6785 {
6786 if (LocaleCompare(attribute,"normalize") == 0)
6787 {
6788 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6789 SvPV(ST(i),na));
6790 if (option < 0)
6791 {
6792 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6793 SvPV(ST(i),na));
6794 break;
6795 }
6796 normalize=option != 0 ? MagickTrue : MagickFalse;
6797 break;
6798 }
6799 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6800 attribute);
6801 break;
6802 }
6803 case 'W':
6804 case 'w':
6805 {
6806 if (LocaleCompare(attribute,"width") == 0)
6807 {
6808 region.width=SvIV(ST(i));
6809 break;
6810 }
6811 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6812 attribute);
6813 break;
6814 }
6815 case 'x':
6816 case 'X':
6817 {
6818 if (LocaleCompare(attribute,"x") == 0)
6819 {
6820 region.x=SvIV(ST(i));
6821 break;
6822 }
6823 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6824 attribute);
6825 break;
6826 }
6827 case 'y':
6828 case 'Y':
6829 {
6830 if (LocaleCompare(attribute,"y") == 0)
6831 {
6832 region.y=SvIV(ST(i));
6833 break;
6834 }
6835 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6836 attribute);
6837 break;
6838 }
6839 default:
6840 {
6841 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6842 attribute);
6843 break;
6844 }
6845 }
6846 }
6847 if (normalize != MagickFalse)
6848 {
6849 float
6850 *pixels;
6851
6852 pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6853 region.height*sizeof(*pixels));
6854 if (pixels == (float *) NULL)
6855 {
6856 ThrowPerlException(exception,ResourceLimitError,
6857 "MemoryAllocationFailed",PackageName);
6858 goto PerlException;
6859 }
6860 status=ExportImagePixels(image,region.x,region.y,region.width,
6861 region.height,map,FloatPixel,pixels,exception);
6862 if (status == MagickFalse)
6863 PUSHs(&sv_undef);
6864 else
6865 {
6866 EXTEND(sp,strlen(map)*region.width*region.height);
6867 for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6868 PUSHs(sv_2mortal(newSVnv(pixels[i])));
6869 }
6870 pixels=(float *) RelinquishMagickMemory(pixels);
6871 }
6872 else
6873 {
6874 Quantum
6875 *pixels;
6876
6877 pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6878 region.height*sizeof(*pixels));
6879 if (pixels == (Quantum *) NULL)
6880 {
6881 ThrowPerlException(exception,ResourceLimitError,
6882 "MemoryAllocationFailed",PackageName);
6883 goto PerlException;
6884 }
6885 status=ExportImagePixels(image,region.x,region.y,region.width,
6886 region.height,map,QuantumPixel,pixels,exception);
6887 if (status == MagickFalse)
6888 PUSHs(&sv_undef);
6889 else
6890 {
6891 EXTEND(sp,strlen(map)*region.width*region.height);
6892 for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6893 PUSHs(sv_2mortal(newSViv(pixels[i])));
6894 }
6895 pixels=(Quantum *) RelinquishMagickMemory(pixels);
6896 }
6897
6898 PerlException:
6899 InheritPerlException(exception,perl_exception);
6900 exception=DestroyExceptionInfo(exception);
6901 SvREFCNT_dec(perl_exception);
6902 }
6903
6904#
6905###############################################################################
6906# #
6907# #
6908# #
6909# I m a g e T o B l o b #
6910# #
6911# #
6912# #
6913###############################################################################
6914#
6915#
6916void
6917ImageToBlob(ref,...)
6918 Image::Magick ref=NO_INIT
6919 ALIAS:
6920 ImageToBlob = 1
6921 imagetoblob = 2
6922 toblob = 3
6923 blob = 4
6924 PPCODE:
6925 {
6926 char
cristy151b66d2015-04-15 10:50:31 +00006927 filename[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00006928
6929 ExceptionInfo
6930 *exception;
6931
6932 Image
6933 *image,
6934 *next;
6935
6936 register ssize_t
6937 i;
6938
6939 struct PackageInfo
6940 *info,
6941 *package_info;
6942
6943 size_t
6944 length;
6945
6946 ssize_t
6947 scene;
6948
6949 SV
6950 *perl_exception,
6951 *reference;
6952
6953 void
6954 *blob;
6955
6956 PERL_UNUSED_VAR(ref);
6957 PERL_UNUSED_VAR(ix);
6958 exception=AcquireExceptionInfo();
6959 perl_exception=newSVpv("",0);
6960 package_info=(struct PackageInfo *) NULL;
6961 if (sv_isobject(ST(0)) == 0)
6962 {
6963 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6964 PackageName);
6965 goto PerlException;
6966 }
6967 reference=SvRV(ST(0));
6968 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6969 if (image == (Image *) NULL)
6970 {
6971 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6972 PackageName);
6973 goto PerlException;
6974 }
6975 package_info=ClonePackageInfo(info,exception);
6976 for (i=2; i < items; i+=2)
6977 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6978 (void) CopyMagickString(filename,package_info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00006979 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00006980 scene=0;
6981 for (next=image; next; next=next->next)
6982 {
cristy151b66d2015-04-15 10:50:31 +00006983 (void) CopyMagickString(next->filename,filename,MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00006984 next->scene=scene++;
6985 }
6986 SetImageInfo(package_info->image_info,(unsigned int)
6987 GetImageListLength(image),exception);
6988 EXTEND(sp,(ssize_t) GetImageListLength(image));
6989 for ( ; image; image=image->next)
6990 {
6991 length=0;
6992 blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6993 if (blob != (char *) NULL)
6994 {
6995 PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6996 blob=(unsigned char *) RelinquishMagickMemory(blob);
6997 }
6998 if (package_info->image_info->adjoin)
6999 break;
7000 }
7001
7002 PerlException:
7003 if (package_info != (struct PackageInfo *) NULL)
7004 DestroyPackageInfo(package_info);
7005 InheritPerlException(exception,perl_exception);
7006 exception=DestroyExceptionInfo(exception);
7007 SvREFCNT_dec(perl_exception); /* throw away all errors */
7008 }
7009
7010#
7011###############################################################################
7012# #
7013# #
7014# #
7015# L a y e r s #
7016# #
7017# #
7018# #
7019###############################################################################
7020#
7021#
7022void
7023Layers(ref,...)
7024 Image::Magick ref=NO_INIT
7025 ALIAS:
7026 Layers = 1
7027 layers = 2
7028 OptimizeImageLayers = 3
7029 optimizelayers = 4
7030 optimizeimagelayers = 5
7031 PPCODE:
7032 {
7033 AV
7034 *av;
7035
7036 char
7037 *attribute;
7038
7039 CompositeOperator
7040 compose;
7041
7042 ExceptionInfo
7043 *exception;
7044
7045 HV
7046 *hv;
7047
7048 Image
7049 *image,
7050 *layers;
7051
7052 LayerMethod
7053 method;
7054
7055 register ssize_t
7056 i;
7057
7058 ssize_t
7059 option,
7060 sp;
7061
7062 struct PackageInfo
7063 *info;
7064
7065 SV
7066 *av_reference,
7067 *perl_exception,
7068 *reference,
7069 *rv,
7070 *sv;
7071
7072 PERL_UNUSED_VAR(ref);
7073 PERL_UNUSED_VAR(ix);
7074 exception=AcquireExceptionInfo();
7075 perl_exception=newSVpv("",0);
7076 sv=NULL;
7077 if (sv_isobject(ST(0)) == 0)
7078 {
7079 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7080 PackageName);
7081 goto PerlException;
7082 }
7083 reference=SvRV(ST(0));
7084 hv=SvSTASH(reference);
7085 av=newAV();
7086 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7087 SvREFCNT_dec(av);
7088 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7089 if (image == (Image *) NULL)
7090 {
7091 ThrowPerlException(exception,OptionError,"NoImagesDefined",
7092 PackageName);
7093 goto PerlException;
7094 }
7095 compose=image->compose;
7096 method=OptimizeLayer;
7097 for (i=2; i < items; i+=2)
7098 {
7099 attribute=(char *) SvPV(ST(i-1),na);
7100 switch (*attribute)
7101 {
7102 case 'C':
7103 case 'c':
7104 {
7105 if (LocaleCompare(attribute,"compose") == 0)
7106 {
7107 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7108 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7109 if (sp < 0)
7110 {
7111 ThrowPerlException(exception,OptionError,"UnrecognizedType",
7112 SvPV(ST(i),na));
7113 break;
7114 }
7115 compose=(CompositeOperator) sp;
7116 break;
7117 }
7118 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7119 attribute);
7120 break;
7121 }
7122 case 'M':
7123 case 'm':
7124 {
7125 if (LocaleCompare(attribute,"method") == 0)
7126 {
7127 option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7128 SvPV(ST(i),na));
7129 if (option < 0)
7130 {
7131 ThrowPerlException(exception,OptionError,"UnrecognizedType",
7132 SvPV(ST(i),na));
7133 break;
7134 }
7135 method=(LayerMethod) option;
7136 break;
7137 }
7138 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7139 attribute);
7140 break;
7141 }
7142 default:
7143 {
7144 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7145 attribute);
7146 break;
7147 }
7148 }
7149 }
7150 layers=(Image *) NULL;
7151 switch (method)
7152 {
7153 case CompareAnyLayer:
7154 case CompareClearLayer:
7155 case CompareOverlayLayer:
7156 default:
7157 {
7158 layers=CompareImagesLayers(image,method,exception);
7159 break;
7160 }
7161 case MergeLayer:
7162 case FlattenLayer:
7163 case MosaicLayer:
7164 {
7165 layers=MergeImageLayers(image,method,exception);
7166 break;
7167 }
7168 case DisposeLayer:
7169 {
7170 layers=DisposeImages(image,exception);
7171 break;
7172 }
7173 case OptimizeImageLayer:
7174 {
7175 layers=OptimizeImageLayers(image,exception);
7176 break;
7177 }
7178 case OptimizePlusLayer:
7179 {
7180 layers=OptimizePlusImageLayers(image,exception);
7181 break;
7182 }
7183 case OptimizeTransLayer:
7184 {
7185 OptimizeImageTransparency(image,exception);
7186 break;
7187 }
7188 case RemoveDupsLayer:
7189 {
7190 RemoveDuplicateLayers(&image,exception);
7191 break;
7192 }
7193 case RemoveZeroLayer:
7194 {
7195 RemoveZeroDelayLayers(&image,exception);
7196 break;
7197 }
7198 case OptimizeLayer:
7199 {
7200 QuantizeInfo
7201 *quantize_info;
7202
7203 /*
7204 General Purpose, GIF Animation Optimizer.
7205 */
7206 layers=CoalesceImages(image,exception);
7207 if (layers == (Image *) NULL)
7208 break;
7209 image=layers;
7210 layers=OptimizeImageLayers(image,exception);
7211 if (layers == (Image *) NULL)
7212 break;
7213 image=DestroyImageList(image);
7214 image=layers;
7215 layers=(Image *) NULL;
7216 OptimizeImageTransparency(image,exception);
7217 quantize_info=AcquireQuantizeInfo(info->image_info);
7218 (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7219 quantize_info=DestroyQuantizeInfo(quantize_info);
7220 break;
7221 }
7222 case CompositeLayer:
7223 {
7224 Image
7225 *source;
7226
7227 RectangleInfo
7228 geometry;
7229
7230 /*
7231 Split image sequence at the first 'NULL:' image.
7232 */
7233 source=image;
7234 while (source != (Image *) NULL)
7235 {
7236 source=GetNextImageInList(source);
7237 if ((source != (Image *) NULL) &&
7238 (LocaleCompare(source->magick,"NULL") == 0))
7239 break;
7240 }
7241 if (source != (Image *) NULL)
7242 {
7243 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7244 (GetNextImageInList(source) == (Image *) NULL))
7245 source=(Image *) NULL;
7246 else
7247 {
7248 /*
7249 Separate the two lists, junk the null: image.
7250 */
7251 source=SplitImageList(source->previous);
7252 DeleteImageFromList(&source);
7253 }
7254 }
7255 if (source == (Image *) NULL)
7256 {
7257 (void) ThrowMagickException(exception,GetMagickModule(),
7258 OptionError,"MissingNullSeparator","layers Composite");
7259 break;
7260 }
7261 /*
7262 Adjust offset with gravity and virtual canvas.
7263 */
7264 SetGeometry(image,&geometry);
7265 (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7266 geometry.width=source->page.width != 0 ? source->page.width :
7267 source->columns;
7268 geometry.height=source->page.height != 0 ? source->page.height :
7269 source->rows;
7270 GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7271 image->columns,image->page.height != 0 ? image->page.height :
7272 image->rows,image->gravity,&geometry);
7273 CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7274 source=DestroyImageList(source);
7275 break;
7276 }
7277 }
7278 if (layers != (Image *) NULL)
7279 image=layers;
cristy83a28a02013-08-03 20:25:48 +00007280 else
7281 image=CloneImage(image,0,0,MagickTrue,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007282 if (image == (Image *) NULL)
7283 goto PerlException;
7284 for ( ; image; image=image->next)
7285 {
7286 AddImageToRegistry(sv,image);
7287 rv=newRV(sv);
7288 av_push(av,sv_bless(rv,hv));
7289 SvREFCNT_dec(sv);
7290 }
7291 exception=DestroyExceptionInfo(exception);
7292 ST(0)=av_reference;
7293 SvREFCNT_dec(perl_exception);
7294 XSRETURN(1);
7295
7296 PerlException:
7297 InheritPerlException(exception,perl_exception);
7298 exception=DestroyExceptionInfo(exception);
7299 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7300 SvPOK_on(perl_exception);
7301 ST(0)=sv_2mortal(perl_exception);
7302 XSRETURN(1);
7303 }
7304
7305#
7306###############################################################################
7307# #
7308# #
7309# #
7310# M a g i c k T o M i m e #
7311# #
7312# #
7313# #
7314###############################################################################
7315#
7316#
7317SV *
7318MagickToMime(ref,name)
7319 Image::Magick ref=NO_INIT
7320 char *name
7321 ALIAS:
7322 magicktomime = 1
7323 CODE:
7324 {
7325 char
7326 *mime;
7327
7328 PERL_UNUSED_VAR(ref);
7329 PERL_UNUSED_VAR(ix);
7330 mime=MagickToMime(name);
7331 RETVAL=newSVpv(mime,0);
7332 mime=(char *) RelinquishMagickMemory(mime);
7333 }
7334 OUTPUT:
7335 RETVAL
7336
7337#
7338###############################################################################
7339# #
7340# #
7341# #
7342# M o g r i f y #
7343# #
7344# #
7345# #
7346###############################################################################
7347#
7348#
7349void
7350Mogrify(ref,...)
7351 Image::Magick ref=NO_INIT
7352 ALIAS:
7353 Comment = 1
7354 CommentImage = 2
7355 Label = 3
7356 LabelImage = 4
7357 AddNoise = 5
7358 AddNoiseImage = 6
7359 Colorize = 7
7360 ColorizeImage = 8
7361 Border = 9
7362 BorderImage = 10
7363 Blur = 11
7364 BlurImage = 12
7365 Chop = 13
7366 ChopImage = 14
7367 Crop = 15
7368 CropImage = 16
7369 Despeckle = 17
7370 DespeckleImage = 18
7371 Edge = 19
7372 EdgeImage = 20
7373 Emboss = 21
7374 EmbossImage = 22
7375 Enhance = 23
7376 EnhanceImage = 24
7377 Flip = 25
7378 FlipImage = 26
7379 Flop = 27
7380 FlopImage = 28
7381 Frame = 29
7382 FrameImage = 30
7383 Implode = 31
7384 ImplodeImage = 32
7385 Magnify = 33
7386 MagnifyImage = 34
7387 MedianFilter = 35
7388 MedianConvolveImage = 36
7389 Minify = 37
7390 MinifyImage = 38
7391 OilPaint = 39
7392 OilPaintImage = 40
7393 ReduceNoise = 41
7394 ReduceNoiseImage = 42
7395 Roll = 43
7396 RollImage = 44
7397 Rotate = 45
7398 RotateImage = 46
7399 Sample = 47
7400 SampleImage = 48
7401 Scale = 49
7402 ScaleImage = 50
7403 Shade = 51
7404 ShadeImage = 52
7405 Sharpen = 53
7406 SharpenImage = 54
7407 Shear = 55
7408 ShearImage = 56
7409 Spread = 57
7410 SpreadImage = 58
7411 Swirl = 59
7412 SwirlImage = 60
7413 Resize = 61
7414 ResizeImage = 62
7415 Zoom = 63
7416 ZoomImage = 64
7417 Annotate = 65
7418 AnnotateImage = 66
7419 ColorFloodfill = 67
7420 ColorFloodfillImage= 68
7421 Composite = 69
7422 CompositeImage = 70
7423 Contrast = 71
7424 ContrastImage = 72
7425 CycleColormap = 73
7426 CycleColormapImage = 74
7427 Draw = 75
7428 DrawImage = 76
7429 Equalize = 77
7430 EqualizeImage = 78
7431 Gamma = 79
7432 GammaImage = 80
7433 Map = 81
7434 MapImage = 82
7435 MatteFloodfill = 83
7436 MatteFloodfillImage= 84
7437 Modulate = 85
7438 ModulateImage = 86
7439 Negate = 87
7440 NegateImage = 88
7441 Normalize = 89
7442 NormalizeImage = 90
7443 NumberColors = 91
7444 NumberColorsImage = 92
7445 Opaque = 93
7446 OpaqueImage = 94
7447 Quantize = 95
7448 QuantizeImage = 96
7449 Raise = 97
7450 RaiseImage = 98
7451 Segment = 99
7452 SegmentImage = 100
7453 Signature = 101
7454 SignatureImage = 102
7455 Solarize = 103
7456 SolarizeImage = 104
7457 Sync = 105
7458 SyncImage = 106
7459 Texture = 107
7460 TextureImage = 108
7461 Evaluate = 109
7462 EvaluateImage = 110
7463 Transparent = 111
7464 TransparentImage = 112
7465 Threshold = 113
7466 ThresholdImage = 114
7467 Charcoal = 115
7468 CharcoalImage = 116
7469 Trim = 117
7470 TrimImage = 118
7471 Wave = 119
7472 WaveImage = 120
7473 Separate = 121
7474 SeparateImage = 122
7475 Stereo = 125
7476 StereoImage = 126
7477 Stegano = 127
7478 SteganoImage = 128
7479 Deconstruct = 129
7480 DeconstructImage = 130
7481 GaussianBlur = 131
7482 GaussianBlurImage = 132
7483 Convolve = 133
7484 ConvolveImage = 134
7485 Profile = 135
7486 ProfileImage = 136
7487 UnsharpMask = 137
7488 UnsharpMaskImage = 138
7489 MotionBlur = 139
7490 MotionBlurImage = 140
7491 OrderedDither = 141
7492 OrderedDitherImage = 142
7493 Shave = 143
7494 ShaveImage = 144
7495 Level = 145
7496 LevelImage = 146
7497 Clip = 147
7498 ClipImage = 148
7499 AffineTransform = 149
7500 AffineTransformImage = 150
7501 Difference = 151
7502 DifferenceImage = 152
7503 AdaptiveThreshold = 153
7504 AdaptiveThresholdImage = 154
7505 Resample = 155
7506 ResampleImage = 156
7507 Describe = 157
7508 DescribeImage = 158
7509 BlackThreshold = 159
7510 BlackThresholdImage= 160
7511 WhiteThreshold = 161
7512 WhiteThresholdImage= 162
cristy60c73c02014-03-25 12:09:58 +00007513 RotationalBlur = 163
7514 RotationalBlurImage= 164
cristy4a3ce0a2013-08-03 20:06:59 +00007515 Thumbnail = 165
7516 ThumbnailImage = 166
7517 Strip = 167
7518 StripImage = 168
7519 Tint = 169
7520 TintImage = 170
7521 Channel = 171
7522 ChannelImage = 172
7523 Splice = 173
7524 SpliceImage = 174
7525 Posterize = 175
7526 PosterizeImage = 176
7527 Shadow = 177
7528 ShadowImage = 178
7529 Identify = 179
7530 IdentifyImage = 180
7531 SepiaTone = 181
7532 SepiaToneImage = 182
7533 SigmoidalContrast = 183
7534 SigmoidalContrastImage = 184
7535 Extent = 185
7536 ExtentImage = 186
7537 Vignette = 187
7538 VignetteImage = 188
7539 ContrastStretch = 189
7540 ContrastStretchImage = 190
7541 Sans0 = 191
7542 Sans0Image = 192
7543 Sans1 = 193
7544 Sans1Image = 194
7545 AdaptiveSharpen = 195
7546 AdaptiveSharpenImage = 196
7547 Transpose = 197
7548 TransposeImage = 198
7549 Transverse = 199
7550 TransverseImage = 200
7551 AutoOrient = 201
7552 AutoOrientImage = 202
7553 AdaptiveBlur = 203
7554 AdaptiveBlurImage = 204
7555 Sketch = 205
7556 SketchImage = 206
7557 UniqueColors = 207
7558 UniqueColorsImage = 208
7559 AdaptiveResize = 209
7560 AdaptiveResizeImage= 210
7561 ClipMask = 211
7562 ClipMaskImage = 212
7563 LinearStretch = 213
7564 LinearStretchImage = 214
7565 ColorMatrix = 215
7566 ColorMatrixImage = 216
7567 Mask = 217
7568 MaskImage = 218
7569 Polaroid = 219
7570 PolaroidImage = 220
7571 FloodfillPaint = 221
7572 FloodfillPaintImage= 222
7573 Distort = 223
7574 DistortImage = 224
7575 Clut = 225
7576 ClutImage = 226
7577 LiquidRescale = 227
7578 LiquidRescaleImage = 228
7579 Encipher = 229
7580 EncipherImage = 230
7581 Decipher = 231
7582 DecipherImage = 232
7583 Deskew = 233
7584 DeskewImage = 234
7585 Remap = 235
7586 RemapImage = 236
7587 SparseColor = 237
7588 SparseColorImage = 238
7589 Function = 239
7590 FunctionImage = 240
7591 SelectiveBlur = 241
7592 SelectiveBlurImage = 242
7593 HaldClut = 243
7594 HaldClutImage = 244
7595 BlueShift = 245
7596 BlueShiftImage = 246
7597 ForwardFourierTransform = 247
7598 ForwardFourierTransformImage = 248
7599 InverseFourierTransform = 249
7600 InverseFourierTransformImage = 250
7601 ColorDecisionList = 251
7602 ColorDecisionListImage = 252
7603 AutoGamma = 253
7604 AutoGammaImage = 254
7605 AutoLevel = 255
7606 AutoLevelImage = 256
7607 LevelColors = 257
7608 LevelImageColors = 258
7609 Clamp = 259
7610 ClampImage = 260
7611 BrightnessContrast = 261
7612 BrightnessContrastImage = 262
7613 Morphology = 263
7614 MorphologyImage = 264
Cristy3ca633e2016-02-13 12:49:01 -05007615 Mode = 265
7616 ModeImage = 266
7617 Statistic = 267
7618 StatisticImage = 268
7619 Perceptible = 269
7620 PerceptibleImage = 270
7621 Poly = 271
7622 PolyImage = 272
7623 Grayscale = 273
7624 GrayscaleImage = 274
7625 CannyEdge = 275
7626 CannyEdgeImage = 276
7627 HoughLine = 277
7628 HoughLineImage = 278
7629 MeanShift = 279
7630 MeanShiftImage = 280
7631 Kuwahara = 281
7632 KuwaharaImage = 282
Cristy0f5df812017-07-04 18:30:05 -04007633 ConnectedComponents = 283
7634 ConnectedComponentsImage = 284
Cristy3ca633e2016-02-13 12:49:01 -05007635 CopyPixels = 285
7636 CopyImagePixels = 286
Cristy5488c982016-02-13 14:07:50 -05007637 Color = 287
7638 ColorImage = 288
Cristy2d830ed2016-02-21 10:54:16 -05007639 WaveletDenoise = 289
7640 WaveletDenoiseImage= 290
Cristy99a57162016-12-05 11:47:57 -05007641 Colorspace = 291
7642 ColorspaceImage = 292
Cristy53353872017-07-02 12:24:24 -04007643 AutoThreshold = 293
7644 AutoThresholdImage = 294
Cristy532b3382018-08-05 17:56:56 -04007645 RangeThreshold = 295
7646 RangeThresholdImage= 296
Cristy9f252542018-11-21 19:13:46 -05007647 CLAHE = 297
7648 CLAHEImage = 298
cristy4a3ce0a2013-08-03 20:06:59 +00007649 MogrifyRegion = 666
7650 PPCODE:
7651 {
7652 AffineMatrix
7653 affine,
7654 current;
7655
7656 char
7657 attribute_flag[MaxArguments],
cristy151b66d2015-04-15 10:50:31 +00007658 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00007659
7660 ChannelType
7661 channel,
7662 channel_mask;
7663
7664 CompositeOperator
7665 compose;
7666
7667 const char
7668 *attribute,
7669 *value;
7670
7671 double
7672 angle;
7673
7674 ExceptionInfo
7675 *exception;
7676
7677 GeometryInfo
7678 geometry_info;
7679
7680 Image
7681 *image,
Cristy7e567962018-02-03 12:42:20 -05007682 *next;
cristy4a3ce0a2013-08-03 20:06:59 +00007683
cristy4a3ce0a2013-08-03 20:06:59 +00007684 MagickStatusType
7685 flags;
7686
7687 PixelInfo
7688 fill_color;
7689
7690 RectangleInfo
7691 geometry,
7692 region_info;
7693
7694 register ssize_t
7695 i;
7696
7697 ssize_t
7698 base,
7699 j,
7700 number_images;
7701
7702 struct Methods
7703 *rp;
7704
7705 struct PackageInfo
7706 *info;
7707
7708 SV
7709 *perl_exception,
7710 **pv,
7711 *reference,
7712 **reference_vector;
7713
7714 struct ArgumentList
7715 argument_list[MaxArguments];
7716
7717 PERL_UNUSED_VAR(ref);
7718 PERL_UNUSED_VAR(ix);
7719 exception=AcquireExceptionInfo();
7720 perl_exception=newSVpv("",0);
7721 reference_vector=NULL;
cristy4a3ce0a2013-08-03 20:06:59 +00007722 number_images=0;
7723 base=2;
7724 if (sv_isobject(ST(0)) == 0)
7725 {
7726 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7727 PackageName);
7728 goto PerlException;
7729 }
7730 reference=SvRV(ST(0));
7731 region_info.width=0;
7732 region_info.height=0;
7733 region_info.x=0;
7734 region_info.y=0;
cristy4a3ce0a2013-08-03 20:06:59 +00007735 image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7736 if (ix && (ix != 666))
7737 {
7738 /*
7739 Called as Method(...)
7740 */
7741 ix=(ix+1)/2;
7742 rp=(&Methods[ix-1]);
7743 attribute=rp->name;
7744 }
7745 else
7746 {
7747 /*
7748 Called as Mogrify("Method",...)
7749 */
7750 attribute=(char *) SvPV(ST(1),na);
7751 if (ix)
7752 {
7753 flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7754 attribute=(char *) SvPV(ST(2),na);
7755 base++;
7756 }
7757 for (rp=Methods; ; rp++)
7758 {
7759 if (rp >= EndOf(Methods))
7760 {
7761 ThrowPerlException(exception,OptionError,
7762 "UnrecognizedPerlMagickMethod",attribute);
7763 goto PerlException;
7764 }
7765 if (strEQcase(attribute,rp->name))
7766 break;
7767 }
7768 ix=rp-Methods+1;
7769 base++;
7770 }
7771 if (image == (Image *) NULL)
7772 {
7773 ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7774 goto PerlException;
7775 }
7776 Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7777 Zero(&attribute_flag,NumberOf(attribute_flag),char);
7778 for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7779 {
7780 Arguments
7781 *pp,
7782 *qq;
7783
7784 ssize_t
7785 ssize_test;
7786
7787 struct ArgumentList
7788 *al;
7789
7790 SV
7791 *sv;
7792
7793 sv=NULL;
7794 ssize_test=0;
7795 pp=(Arguments *) NULL;
7796 qq=rp->arguments;
7797 if (i == items)
7798 {
7799 pp=rp->arguments,
7800 sv=ST(i-1);
7801 }
7802 else
7803 for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7804 {
7805 if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7806 break;
7807 if (strEQcase(attribute,qq->method) > ssize_test)
7808 {
7809 pp=qq;
7810 ssize_test=strEQcase(attribute,qq->method);
7811 }
7812 }
7813 if (pp == (Arguments *) NULL)
7814 {
7815 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7816 attribute);
7817 goto continue_outer_loop;
7818 }
7819 al=(&argument_list[pp-rp->arguments]);
7820 switch (pp->type)
7821 {
7822 case ArrayReference:
7823 {
7824 if (SvTYPE(sv) != SVt_RV)
7825 {
cristy151b66d2015-04-15 10:50:31 +00007826 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007827 "invalid %.60s value",pp->method);
7828 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7829 goto continue_outer_loop;
7830 }
7831 al->array_reference=SvRV(sv);
7832 break;
7833 }
7834 case RealReference:
7835 {
7836 al->real_reference=SvNV(sv);
7837 break;
7838 }
7839 case FileReference:
7840 {
7841 al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7842 break;
7843 }
7844 case ImageReference:
7845 {
7846 if (!sv_isobject(sv) ||
7847 !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7848 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7849 {
7850 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7851 PackageName);
7852 goto PerlException;
7853 }
7854 break;
7855 }
7856 case IntegerReference:
7857 {
7858 al->integer_reference=SvIV(sv);
7859 break;
7860 }
7861 case StringReference:
7862 {
7863 al->string_reference=(char *) SvPV(sv,al->length);
7864 if (sv_isobject(sv))
7865 al->image_reference=SetupList(aTHX_ SvRV(sv),
7866 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7867 break;
7868 }
7869 default:
7870 {
7871 /*
7872 Is a string; look up name.
7873 */
7874 if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7875 {
7876 al->string_reference=(char *) SvPV(sv,al->length);
7877 al->integer_reference=(-1);
7878 break;
7879 }
7880 al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7881 MagickFalse,SvPV(sv,na));
7882 if (pp->type == MagickChannelOptions)
7883 al->integer_reference=ParseChannelOption(SvPV(sv,na));
7884 if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7885 {
cristy151b66d2015-04-15 10:50:31 +00007886 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007887 "invalid %.60s value",pp->method);
7888 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7889 goto continue_outer_loop;
7890 }
7891 break;
7892 }
7893 }
7894 attribute_flag[pp-rp->arguments]++;
7895 continue_outer_loop: ;
7896 }
7897 (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7898 pv=reference_vector;
7899 SetGeometryInfo(&geometry_info);
7900 channel=DefaultChannels;
7901 for (next=image; next; next=next->next)
7902 {
7903 image=next;
7904 SetGeometry(image,&geometry);
7905 if ((region_info.width*region_info.height) != 0)
Cristy7e567962018-02-03 12:42:20 -05007906 (void) SetImageRegionMask(image,WritePixelMask,&region_info,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007907 switch (ix)
7908 {
7909 default:
7910 {
cristy151b66d2015-04-15 10:50:31 +00007911 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
cristy4a3ce0a2013-08-03 20:06:59 +00007912 ThrowPerlException(exception,OptionError,
7913 "UnrecognizedPerlMagickMethod",message);
7914 goto PerlException;
7915 }
7916 case 1: /* Comment */
7917 {
7918 if (attribute_flag[0] == 0)
7919 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007920 (void) SetImageProperty(image,"comment",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007921 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007922 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007923 break;
7924 }
7925 case 2: /* Label */
7926 {
7927 if (attribute_flag[0] == 0)
7928 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007929 (void) SetImageProperty(image,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007930 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007931 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007932 break;
7933 }
7934 case 3: /* AddNoise */
7935 {
7936 double
7937 attenuate;
7938
7939 if (attribute_flag[0] == 0)
7940 argument_list[0].integer_reference=UniformNoise;
7941 attenuate=1.0;
7942 if (attribute_flag[1] != 0)
7943 attenuate=argument_list[1].real_reference;
7944 if (attribute_flag[2] != 0)
7945 channel=(ChannelType) argument_list[2].integer_reference;
7946 channel_mask=SetImageChannelMask(image,channel);
7947 image=AddNoiseImage(image,(NoiseType)
7948 argument_list[0].integer_reference,attenuate,exception);
7949 if (image != (Image *) NULL)
7950 (void) SetImageChannelMask(image,channel_mask);
7951 break;
7952 }
7953 case 4: /* Colorize */
7954 {
7955 PixelInfo
7956 target;
7957
7958 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7959 0,0,&target,exception);
7960 if (attribute_flag[0] != 0)
7961 (void) QueryColorCompliance(argument_list[0].string_reference,
7962 AllCompliance,&target,exception);
7963 if (attribute_flag[1] == 0)
7964 argument_list[1].string_reference="100%";
7965 image=ColorizeImage(image,argument_list[1].string_reference,&target,
7966 exception);
7967 break;
7968 }
7969 case 5: /* Border */
7970 {
7971 CompositeOperator
7972 compose;
7973
7974 geometry.width=0;
7975 geometry.height=0;
7976 if (attribute_flag[0] != 0)
7977 flags=ParsePageGeometry(image,argument_list[0].string_reference,
7978 &geometry,exception);
7979 if (attribute_flag[1] != 0)
7980 geometry.width=argument_list[1].integer_reference;
7981 if (attribute_flag[2] != 0)
7982 geometry.height=argument_list[2].integer_reference;
7983 if (attribute_flag[3] != 0)
7984 QueryColorCompliance(argument_list[3].string_reference,
7985 AllCompliance,&image->border_color,exception);
7986 if (attribute_flag[4] != 0)
7987 QueryColorCompliance(argument_list[4].string_reference,
7988 AllCompliance,&image->border_color,exception);
7989 if (attribute_flag[5] != 0)
7990 QueryColorCompliance(argument_list[5].string_reference,
7991 AllCompliance,&image->border_color,exception);
7992 compose=image->compose;
7993 if (attribute_flag[6] != 0)
7994 compose=(CompositeOperator) argument_list[6].integer_reference;
7995 image=BorderImage(image,&geometry,compose,exception);
7996 break;
7997 }
7998 case 6: /* Blur */
7999 {
8000 if (attribute_flag[0] != 0)
8001 {
8002 flags=ParseGeometry(argument_list[0].string_reference,
8003 &geometry_info);
8004 if ((flags & SigmaValue) == 0)
8005 geometry_info.sigma=1.0;
8006 }
8007 if (attribute_flag[1] != 0)
8008 geometry_info.rho=argument_list[1].real_reference;
8009 if (attribute_flag[2] != 0)
8010 geometry_info.sigma=argument_list[2].real_reference;
8011 if (attribute_flag[3] != 0)
8012 channel=(ChannelType) argument_list[3].integer_reference;
8013 channel_mask=SetImageChannelMask(image,channel);
8014 image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
8015 exception);
8016 if (image != (Image *) NULL)
8017 (void) SetImageChannelMask(image,channel_mask);
8018 break;
8019 }
8020 case 7: /* Chop */
8021 {
cristy260bd762014-08-15 12:46:34 +00008022 if (attribute_flag[5] != 0)
8023 image->gravity=(GravityType) argument_list[5].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00008024 if (attribute_flag[0] != 0)
8025 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8026 &geometry,exception);
8027 if (attribute_flag[1] != 0)
8028 geometry.width=argument_list[1].integer_reference;
8029 if (attribute_flag[2] != 0)
8030 geometry.height=argument_list[2].integer_reference;
8031 if (attribute_flag[3] != 0)
8032 geometry.x=argument_list[3].integer_reference;
8033 if (attribute_flag[4] != 0)
8034 geometry.y=argument_list[4].integer_reference;
8035 image=ChopImage(image,&geometry,exception);
8036 break;
8037 }
8038 case 8: /* Crop */
8039 {
8040 if (attribute_flag[6] != 0)
8041 image->gravity=(GravityType) argument_list[6].integer_reference;
8042 if (attribute_flag[0] != 0)
8043 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8044 &geometry,exception);
8045 if (attribute_flag[1] != 0)
8046 geometry.width=argument_list[1].integer_reference;
8047 if (attribute_flag[2] != 0)
8048 geometry.height=argument_list[2].integer_reference;
8049 if (attribute_flag[3] != 0)
8050 geometry.x=argument_list[3].integer_reference;
8051 if (attribute_flag[4] != 0)
8052 geometry.y=argument_list[4].integer_reference;
8053 if (attribute_flag[5] != 0)
8054 image->fuzz=StringToDoubleInterval(
8055 argument_list[5].string_reference,(double) QuantumRange+1.0);
8056 image=CropImage(image,&geometry,exception);
8057 break;
8058 }
8059 case 9: /* Despeckle */
8060 {
8061 image=DespeckleImage(image,exception);
8062 break;
8063 }
8064 case 10: /* Edge */
8065 {
8066 if (attribute_flag[0] != 0)
8067 geometry_info.rho=argument_list[0].real_reference;
8068 image=EdgeImage(image,geometry_info.rho,exception);
8069 break;
8070 }
8071 case 11: /* Emboss */
8072 {
8073 if (attribute_flag[0] != 0)
8074 {
8075 flags=ParseGeometry(argument_list[0].string_reference,
8076 &geometry_info);
8077 if ((flags & SigmaValue) == 0)
8078 geometry_info.sigma=1.0;
8079 }
8080 if (attribute_flag[1] != 0)
8081 geometry_info.rho=argument_list[1].real_reference;
8082 if (attribute_flag[2] != 0)
8083 geometry_info.sigma=argument_list[2].real_reference;
8084 image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8085 exception);
8086 break;
8087 }
8088 case 12: /* Enhance */
8089 {
8090 image=EnhanceImage(image,exception);
8091 break;
8092 }
8093 case 13: /* Flip */
8094 {
8095 image=FlipImage(image,exception);
8096 break;
8097 }
8098 case 14: /* Flop */
8099 {
8100 image=FlopImage(image,exception);
8101 break;
8102 }
8103 case 15: /* Frame */
8104 {
8105 CompositeOperator
8106 compose;
8107
8108 FrameInfo
8109 frame_info;
8110
8111 if (attribute_flag[0] != 0)
8112 {
8113 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8114 &geometry,exception);
8115 frame_info.width=geometry.width;
8116 frame_info.height=geometry.height;
8117 frame_info.outer_bevel=geometry.x;
8118 frame_info.inner_bevel=geometry.y;
8119 }
8120 if (attribute_flag[1] != 0)
8121 frame_info.width=argument_list[1].integer_reference;
8122 if (attribute_flag[2] != 0)
8123 frame_info.height=argument_list[2].integer_reference;
8124 if (attribute_flag[3] != 0)
8125 frame_info.inner_bevel=argument_list[3].integer_reference;
8126 if (attribute_flag[4] != 0)
8127 frame_info.outer_bevel=argument_list[4].integer_reference;
8128 if (attribute_flag[5] != 0)
8129 QueryColorCompliance(argument_list[5].string_reference,
8130 AllCompliance,&fill_color,exception);
8131 if (attribute_flag[6] != 0)
8132 QueryColorCompliance(argument_list[6].string_reference,
8133 AllCompliance,&fill_color,exception);
8134 frame_info.x=(ssize_t) frame_info.width;
8135 frame_info.y=(ssize_t) frame_info.height;
8136 frame_info.width=image->columns+2*frame_info.x;
8137 frame_info.height=image->rows+2*frame_info.y;
8138 if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
Cristy8645e042016-02-03 16:35:29 -05008139 image->alpha_color=fill_color;
cristy4a3ce0a2013-08-03 20:06:59 +00008140 compose=image->compose;
8141 if (attribute_flag[7] != 0)
8142 compose=(CompositeOperator) argument_list[7].integer_reference;
8143 image=FrameImage(image,&frame_info,compose,exception);
8144 break;
8145 }
8146 case 16: /* Implode */
8147 {
8148 PixelInterpolateMethod
8149 method;
8150
8151 if (attribute_flag[0] == 0)
8152 argument_list[0].real_reference=0.5;
8153 method=UndefinedInterpolatePixel;
8154 if (attribute_flag[1] != 0)
8155 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8156 image=ImplodeImage(image,argument_list[0].real_reference,
8157 method,exception);
8158 break;
8159 }
8160 case 17: /* Magnify */
8161 {
8162 image=MagnifyImage(image,exception);
8163 break;
8164 }
8165 case 18: /* MedianFilter */
8166 {
8167 if (attribute_flag[0] != 0)
8168 {
8169 flags=ParseGeometry(argument_list[0].string_reference,
8170 &geometry_info);
8171 if ((flags & SigmaValue) == 0)
8172 geometry_info.sigma=geometry_info.rho;
8173 }
8174 if (attribute_flag[1] != 0)
8175 geometry_info.rho=argument_list[1].real_reference;
8176 if (attribute_flag[2] != 0)
8177 geometry_info.sigma=argument_list[2].real_reference;
8178 if (attribute_flag[3] != 0)
8179 channel=(ChannelType) argument_list[3].integer_reference;
8180 channel_mask=SetImageChannelMask(image,channel);
8181 image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8182 (size_t) geometry_info.sigma,exception);
8183 if (image != (Image *) NULL)
8184 (void) SetImageChannelMask(image,channel_mask);
8185 break;
8186 }
8187 case 19: /* Minify */
8188 {
8189 image=MinifyImage(image,exception);
8190 break;
8191 }
8192 case 20: /* OilPaint */
8193 {
8194 if (attribute_flag[0] == 0)
8195 argument_list[0].real_reference=0.0;
8196 if (attribute_flag[1] == 0)
8197 argument_list[1].real_reference=1.0;
8198 image=OilPaintImage(image,argument_list[0].real_reference,
8199 argument_list[1].real_reference,exception);
8200 break;
8201 }
8202 case 21: /* ReduceNoise */
8203 {
8204 if (attribute_flag[0] != 0)
8205 {
8206 flags=ParseGeometry(argument_list[0].string_reference,
8207 &geometry_info);
8208 if ((flags & SigmaValue) == 0)
8209 geometry_info.sigma=1.0;
8210 }
8211 if (attribute_flag[1] != 0)
8212 geometry_info.rho=argument_list[1].real_reference;
8213 if (attribute_flag[2] != 0)
8214 geometry_info.sigma=argument_list[2].real_reference;
8215 if (attribute_flag[3] != 0)
8216 channel=(ChannelType) argument_list[3].integer_reference;
8217 channel_mask=SetImageChannelMask(image,channel);
8218 image=StatisticImage(image,NonpeakStatistic,(size_t)
8219 geometry_info.rho,(size_t) geometry_info.sigma,exception);
8220 if (image != (Image *) NULL)
8221 (void) SetImageChannelMask(image,channel_mask);
8222 break;
8223 }
8224 case 22: /* Roll */
8225 {
8226 if (attribute_flag[0] != 0)
Cristyf94b0842017-07-14 07:05:02 -04008227 {
8228 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8229 &geometry,exception);
8230 if ((flags & PercentValue) != 0)
8231 {
8232 geometry.x*=(double) image->columns/100.0;
8233 geometry.y*=(double) image->rows/100.0;
8234 }
8235 }
cristy4a3ce0a2013-08-03 20:06:59 +00008236 if (attribute_flag[1] != 0)
8237 geometry.x=argument_list[1].integer_reference;
8238 if (attribute_flag[2] != 0)
8239 geometry.y=argument_list[2].integer_reference;
8240 image=RollImage(image,geometry.x,geometry.y,exception);
8241 break;
8242 }
8243 case 23: /* Rotate */
8244 {
8245 if (attribute_flag[0] == 0)
8246 argument_list[0].real_reference=90.0;
8247 if (attribute_flag[1] != 0)
8248 {
8249 QueryColorCompliance(argument_list[1].string_reference,
8250 AllCompliance,&image->background_color,exception);
cristy17f11b02014-12-20 19:37:04 +00008251 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8252 (image->alpha_trait == UndefinedPixelTrait))
cristy4a3ce0a2013-08-03 20:06:59 +00008253 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8254 }
8255 image=RotateImage(image,argument_list[0].real_reference,exception);
8256 break;
8257 }
8258 case 24: /* Sample */
8259 {
8260 if (attribute_flag[0] != 0)
8261 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8262 &geometry,exception);
8263 if (attribute_flag[1] != 0)
8264 geometry.width=argument_list[1].integer_reference;
8265 if (attribute_flag[2] != 0)
8266 geometry.height=argument_list[2].integer_reference;
8267 image=SampleImage(image,geometry.width,geometry.height,exception);
8268 break;
8269 }
8270 case 25: /* Scale */
8271 {
8272 if (attribute_flag[0] != 0)
8273 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8274 &geometry,exception);
8275 if (attribute_flag[1] != 0)
8276 geometry.width=argument_list[1].integer_reference;
8277 if (attribute_flag[2] != 0)
8278 geometry.height=argument_list[2].integer_reference;
8279 image=ScaleImage(image,geometry.width,geometry.height,exception);
8280 break;
8281 }
8282 case 26: /* Shade */
8283 {
8284 if (attribute_flag[0] != 0)
8285 {
8286 flags=ParseGeometry(argument_list[0].string_reference,
8287 &geometry_info);
8288 if ((flags & SigmaValue) == 0)
8289 geometry_info.sigma=0.0;
8290 }
8291 if (attribute_flag[1] != 0)
8292 geometry_info.rho=argument_list[1].real_reference;
8293 if (attribute_flag[2] != 0)
8294 geometry_info.sigma=argument_list[2].real_reference;
8295 image=ShadeImage(image,
8296 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8297 geometry_info.rho,geometry_info.sigma,exception);
8298 break;
8299 }
8300 case 27: /* Sharpen */
8301 {
8302 if (attribute_flag[0] != 0)
8303 {
8304 flags=ParseGeometry(argument_list[0].string_reference,
8305 &geometry_info);
8306 if ((flags & SigmaValue) == 0)
8307 geometry_info.sigma=1.0;
8308 }
8309 if (attribute_flag[1] != 0)
8310 geometry_info.rho=argument_list[1].real_reference;
8311 if (attribute_flag[2] != 0)
8312 geometry_info.sigma=argument_list[2].real_reference;
8313 if (attribute_flag[3] != 0)
8314 channel=(ChannelType) argument_list[3].integer_reference;
8315 channel_mask=SetImageChannelMask(image,channel);
8316 image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8317 exception);
8318 if (image != (Image *) NULL)
8319 (void) SetImageChannelMask(image,channel_mask);
8320 break;
8321 }
8322 case 28: /* Shear */
8323 {
8324 if (attribute_flag[0] != 0)
8325 {
8326 flags=ParseGeometry(argument_list[0].string_reference,
8327 &geometry_info);
8328 if ((flags & SigmaValue) == 0)
8329 geometry_info.sigma=geometry_info.rho;
8330 }
8331 if (attribute_flag[1] != 0)
8332 geometry_info.rho=argument_list[1].real_reference;
8333 if (attribute_flag[2] != 0)
8334 geometry_info.sigma=argument_list[2].real_reference;
8335 if (attribute_flag[3] != 0)
8336 QueryColorCompliance(argument_list[3].string_reference,
8337 AllCompliance,&image->background_color,exception);
8338 if (attribute_flag[4] != 0)
8339 QueryColorCompliance(argument_list[4].string_reference,
8340 AllCompliance,&image->background_color,exception);
8341 image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8342 exception);
8343 break;
8344 }
8345 case 29: /* Spread */
8346 {
Cristye3319c12015-08-24 07:11:48 -04008347 PixelInterpolateMethod
8348 method;
8349
cristy4a3ce0a2013-08-03 20:06:59 +00008350 if (attribute_flag[0] == 0)
8351 argument_list[0].real_reference=1.0;
Cristye3319c12015-08-24 07:11:48 -04008352 method=UndefinedInterpolatePixel;
8353 if (attribute_flag[1] != 0)
8354 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8355 image=SpreadImage(image,method,argument_list[0].real_reference,
8356 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008357 break;
8358 }
8359 case 30: /* Swirl */
8360 {
8361 PixelInterpolateMethod
8362 method;
8363
8364 if (attribute_flag[0] == 0)
8365 argument_list[0].real_reference=50.0;
8366 method=UndefinedInterpolatePixel;
8367 if (attribute_flag[1] != 0)
8368 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8369 image=SwirlImage(image,argument_list[0].real_reference,
8370 method,exception);
8371 break;
8372 }
8373 case 31: /* Resize */
8374 case 32: /* Zoom */
8375 {
8376 if (attribute_flag[0] != 0)
8377 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8378 &geometry,exception);
8379 if (attribute_flag[1] != 0)
8380 geometry.width=argument_list[1].integer_reference;
8381 if (attribute_flag[2] != 0)
8382 geometry.height=argument_list[2].integer_reference;
8383 if (attribute_flag[3] == 0)
8384 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8385 if (attribute_flag[4] != 0)
8386 SetImageArtifact(image,"filter:support",
8387 argument_list[4].string_reference);
8388 image=ResizeImage(image,geometry.width,geometry.height,
Cristy8645e042016-02-03 16:35:29 -05008389 (FilterType) argument_list[3].integer_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00008390 exception);
8391 break;
8392 }
8393 case 33: /* Annotate */
8394 {
8395 DrawInfo
8396 *draw_info;
8397
8398 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8399 (DrawInfo *) NULL);
8400 if (attribute_flag[0] != 0)
8401 {
8402 char
8403 *text;
8404
8405 text=InterpretImageProperties(info ? info->image_info :
8406 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8407 exception);
8408 (void) CloneString(&draw_info->text,text);
8409 text=DestroyString(text);
8410 }
8411 if (attribute_flag[1] != 0)
8412 (void) CloneString(&draw_info->font,
8413 argument_list[1].string_reference);
8414 if (attribute_flag[2] != 0)
8415 draw_info->pointsize=argument_list[2].real_reference;
8416 if (attribute_flag[3] != 0)
8417 (void) CloneString(&draw_info->density,
8418 argument_list[3].string_reference);
8419 if (attribute_flag[4] != 0)
8420 (void) QueryColorCompliance(argument_list[4].string_reference,
8421 AllCompliance,&draw_info->undercolor,exception);
8422 if (attribute_flag[5] != 0)
8423 {
8424 (void) QueryColorCompliance(argument_list[5].string_reference,
8425 AllCompliance,&draw_info->stroke,exception);
8426 if (argument_list[5].image_reference != (Image *) NULL)
8427 draw_info->stroke_pattern=CloneImage(
8428 argument_list[5].image_reference,0,0,MagickTrue,exception);
8429 }
8430 if (attribute_flag[6] != 0)
8431 {
8432 (void) QueryColorCompliance(argument_list[6].string_reference,
8433 AllCompliance,&draw_info->fill,exception);
8434 if (argument_list[6].image_reference != (Image *) NULL)
8435 draw_info->fill_pattern=CloneImage(
8436 argument_list[6].image_reference,0,0,MagickTrue,exception);
8437 }
8438 if (attribute_flag[7] != 0)
8439 {
8440 (void) CloneString(&draw_info->geometry,
8441 argument_list[7].string_reference);
8442 flags=ParsePageGeometry(image,argument_list[7].string_reference,
8443 &geometry,exception);
8444 if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8445 geometry_info.sigma=geometry_info.xi;
8446 }
8447 if (attribute_flag[8] != 0)
8448 (void) QueryColorCompliance(argument_list[8].string_reference,
8449 AllCompliance,&draw_info->fill,exception);
8450 if (attribute_flag[11] != 0)
8451 draw_info->gravity=(GravityType)
8452 argument_list[11].integer_reference;
8453 if (attribute_flag[25] != 0)
8454 {
8455 AV
8456 *av;
8457
8458 av=(AV *) argument_list[25].array_reference;
8459 if ((av_len(av) != 3) && (av_len(av) != 5))
8460 {
8461 ThrowPerlException(exception,OptionError,
8462 "affine matrix must have 4 or 6 elements",PackageName);
8463 goto PerlException;
8464 }
8465 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8466 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8467 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8468 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8469 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8470 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8471 {
8472 ThrowPerlException(exception,OptionError,
8473 "affine matrix is singular",PackageName);
8474 goto PerlException;
8475 }
8476 if (av_len(av) == 5)
8477 {
8478 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8479 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8480 }
8481 }
8482 for (j=12; j < 17; j++)
8483 {
8484 if (attribute_flag[j] == 0)
8485 continue;
8486 value=argument_list[j].string_reference;
8487 angle=argument_list[j].real_reference;
8488 current=draw_info->affine;
8489 GetAffineMatrix(&affine);
8490 switch (j)
8491 {
8492 case 12:
8493 {
8494 /*
8495 Translate.
8496 */
8497 flags=ParseGeometry(value,&geometry_info);
8498 affine.tx=geometry_info.xi;
8499 affine.ty=geometry_info.psi;
8500 if ((flags & PsiValue) == 0)
8501 affine.ty=affine.tx;
8502 break;
8503 }
8504 case 13:
8505 {
8506 /*
8507 Scale.
8508 */
8509 flags=ParseGeometry(value,&geometry_info);
8510 affine.sx=geometry_info.rho;
8511 affine.sy=geometry_info.sigma;
8512 if ((flags & SigmaValue) == 0)
8513 affine.sy=affine.sx;
8514 break;
8515 }
8516 case 14:
8517 {
8518 /*
8519 Rotate.
8520 */
8521 if (angle == 0.0)
8522 break;
8523 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8524 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8525 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8526 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8527 break;
8528 }
8529 case 15:
8530 {
8531 /*
8532 SkewX.
8533 */
8534 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8535 break;
8536 }
8537 case 16:
8538 {
8539 /*
8540 SkewY.
8541 */
8542 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8543 break;
8544 }
8545 }
8546 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8547 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8548 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8549 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8550 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8551 current.tx;
8552 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8553 current.ty;
8554 }
8555 if (attribute_flag[9] == 0)
8556 argument_list[9].real_reference=0.0;
8557 if (attribute_flag[10] == 0)
8558 argument_list[10].real_reference=0.0;
8559 if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8560 {
8561 char
cristy151b66d2015-04-15 10:50:31 +00008562 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008563
cristy151b66d2015-04-15 10:50:31 +00008564 (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
cristy4a3ce0a2013-08-03 20:06:59 +00008565 (double) argument_list[9].real_reference+draw_info->affine.tx,
8566 (double) argument_list[10].real_reference+draw_info->affine.ty);
8567 (void) CloneString(&draw_info->geometry,geometry);
8568 }
8569 if (attribute_flag[17] != 0)
8570 draw_info->stroke_width=argument_list[17].real_reference;
8571 if (attribute_flag[18] != 0)
8572 {
8573 draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8574 MagickTrue : MagickFalse;
8575 draw_info->stroke_antialias=draw_info->text_antialias;
8576 }
8577 if (attribute_flag[19] != 0)
8578 (void) CloneString(&draw_info->family,
8579 argument_list[19].string_reference);
8580 if (attribute_flag[20] != 0)
8581 draw_info->style=(StyleType) argument_list[20].integer_reference;
8582 if (attribute_flag[21] != 0)
8583 draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8584 if (attribute_flag[22] != 0)
8585 draw_info->weight=argument_list[22].integer_reference;
8586 if (attribute_flag[23] != 0)
8587 draw_info->align=(AlignType) argument_list[23].integer_reference;
8588 if (attribute_flag[24] != 0)
8589 (void) CloneString(&draw_info->encoding,
8590 argument_list[24].string_reference);
8591 if (attribute_flag[25] != 0)
8592 draw_info->fill_pattern=CloneImage(
8593 argument_list[25].image_reference,0,0,MagickTrue,exception);
8594 if (attribute_flag[26] != 0)
8595 draw_info->fill_pattern=CloneImage(
8596 argument_list[26].image_reference,0,0,MagickTrue,exception);
8597 if (attribute_flag[27] != 0)
8598 draw_info->stroke_pattern=CloneImage(
8599 argument_list[27].image_reference,0,0,MagickTrue,exception);
8600 if (attribute_flag[29] != 0)
8601 draw_info->kerning=argument_list[29].real_reference;
8602 if (attribute_flag[30] != 0)
8603 draw_info->interline_spacing=argument_list[30].real_reference;
8604 if (attribute_flag[31] != 0)
8605 draw_info->interword_spacing=argument_list[31].real_reference;
8606 if (attribute_flag[32] != 0)
8607 draw_info->direction=(DirectionType)
8608 argument_list[32].integer_reference;
8609 (void) AnnotateImage(image,draw_info,exception);
8610 draw_info=DestroyDrawInfo(draw_info);
8611 break;
8612 }
8613 case 34: /* ColorFloodfill */
8614 {
8615 DrawInfo
8616 *draw_info;
8617
8618 MagickBooleanType
8619 invert;
8620
8621 PixelInfo
8622 target;
8623
8624 draw_info=CloneDrawInfo(info ? info->image_info :
8625 (ImageInfo *) NULL,(DrawInfo *) NULL);
8626 if (attribute_flag[0] != 0)
8627 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8628 &geometry,exception);
8629 if (attribute_flag[1] != 0)
8630 geometry.x=argument_list[1].integer_reference;
8631 if (attribute_flag[2] != 0)
8632 geometry.y=argument_list[2].integer_reference;
8633 if (attribute_flag[3] != 0)
8634 (void) QueryColorCompliance(argument_list[3].string_reference,
8635 AllCompliance,&draw_info->fill,exception);
8636 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8637 geometry.x,geometry.y,&target,exception);
8638 invert=MagickFalse;
8639 if (attribute_flag[4] != 0)
8640 {
8641 QueryColorCompliance(argument_list[4].string_reference,
8642 AllCompliance,&target,exception);
8643 invert=MagickTrue;
8644 }
8645 if (attribute_flag[5] != 0)
8646 image->fuzz=StringToDoubleInterval(
8647 argument_list[5].string_reference,(double) QuantumRange+1.0);
8648 if (attribute_flag[6] != 0)
8649 invert=(MagickBooleanType) argument_list[6].integer_reference;
8650 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8651 geometry.y,invert,exception);
8652 draw_info=DestroyDrawInfo(draw_info);
8653 break;
8654 }
8655 case 35: /* Composite */
8656 {
8657 char
cristy151b66d2015-04-15 10:50:31 +00008658 composite_geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008659
8660 Image
8661 *composite_image,
8662 *rotate_image;
8663
8664 MagickBooleanType
8665 clip_to_self;
8666
8667 compose=OverCompositeOp;
8668 if (attribute_flag[0] != 0)
8669 composite_image=argument_list[0].image_reference;
8670 else
8671 {
8672 ThrowPerlException(exception,OptionError,
8673 "CompositeImageRequired",PackageName);
8674 goto PerlException;
8675 }
8676 /*
8677 Parameter Handling used for BOTH normal and tiled composition.
8678 */
8679 if (attribute_flag[1] != 0) /* compose */
8680 compose=(CompositeOperator) argument_list[1].integer_reference;
8681 if (attribute_flag[6] != 0) /* opacity */
8682 {
8683 if (compose != DissolveCompositeOp)
8684 (void) SetImageAlpha(composite_image,(Quantum)
8685 StringToDoubleInterval(argument_list[6].string_reference,
8686 (double) QuantumRange+1.0),exception);
8687 else
8688 {
8689 CacheView
8690 *composite_view;
8691
8692 double
8693 opacity;
8694
8695 MagickBooleanType
8696 sync;
8697
8698 register ssize_t
8699 x;
8700
8701 register Quantum
8702 *q;
8703
8704 ssize_t
8705 y;
8706
8707 /*
8708 Handle dissolve composite operator (patch by
8709 Kevin A. McGrail).
8710 */
8711 (void) CloneString(&image->geometry,
8712 argument_list[6].string_reference);
8713 opacity=(Quantum) StringToDoubleInterval(
8714 argument_list[6].string_reference,(double) QuantumRange+
8715 1.0);
cristy17f11b02014-12-20 19:37:04 +00008716 if (composite_image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00008717 (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8718 composite_view=AcquireAuthenticCacheView(composite_image,exception);
8719 for (y=0; y < (ssize_t) composite_image->rows ; y++)
8720 {
8721 q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8722 composite_image->columns,1,exception);
8723 for (x=0; x < (ssize_t) composite_image->columns; x++)
8724 {
8725 if (GetPixelAlpha(image,q) == OpaqueAlpha)
8726 SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8727 q);
8728 q+=GetPixelChannels(composite_image);
8729 }
8730 sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8731 if (sync == MagickFalse)
8732 break;
8733 }
8734 composite_view=DestroyCacheView(composite_view);
8735 }
8736 }
8737 if (attribute_flag[9] != 0) /* "color=>" */
8738 QueryColorCompliance(argument_list[9].string_reference,
8739 AllCompliance,&composite_image->background_color,exception);
8740 if (attribute_flag[12] != 0) /* "interpolate=>" */
8741 image->interpolate=(PixelInterpolateMethod)
8742 argument_list[12].integer_reference;
8743 if (attribute_flag[13] != 0) /* "args=>" */
8744 (void) SetImageArtifact(composite_image,"compose:args",
8745 argument_list[13].string_reference);
8746 if (attribute_flag[14] != 0) /* "blend=>" depreciated */
8747 (void) SetImageArtifact(composite_image,"compose:args",
8748 argument_list[14].string_reference);
Cristy72aed842018-07-08 18:25:50 -04008749 clip_to_self=MagickTrue;
8750 switch (compose)
8751 {
8752 case ClearCompositeOp:
8753 case SrcCompositeOp:
8754 case InCompositeOp:
8755 case SrcInCompositeOp:
8756 case OutCompositeOp:
8757 case SrcOutCompositeOp:
8758 case DstInCompositeOp:
8759 case DstAtopCompositeOp:
Cristy901f5212018-07-08 18:43:34 -04008760 case CopyAlphaCompositeOp:
Cristy72aed842018-07-08 18:25:50 -04008761 case ChangeMaskCompositeOp:
8762 case DissolveCompositeOp:
8763 case BlendCompositeOp:
8764 {
Cristy901f5212018-07-08 18:43:34 -04008765 clip_to_self=MagickFalse;
Cristy72aed842018-07-08 18:25:50 -04008766 break;
8767 }
8768 default:
8769 break;
8770 }
cristy4a3ce0a2013-08-03 20:06:59 +00008771 if (attribute_flag[15] != 0)
8772 clip_to_self=(MagickBooleanType)
8773 argument_list[15].integer_reference;
8774 /*
8775 Tiling Composition (with orthogonal rotate).
8776 */
8777 rotate_image=(Image *) NULL;
8778 if (attribute_flag[8] != 0) /* "rotate=>" */
8779 {
8780 /*
8781 Rotate image.
8782 */
8783 rotate_image=RotateImage(composite_image,
8784 argument_list[8].real_reference,exception);
8785 if (rotate_image == (Image *) NULL)
8786 break;
8787 }
8788 if ((attribute_flag[7] != 0) &&
8789 (argument_list[7].integer_reference != 0)) /* tile */
8790 {
8791 ssize_t
8792 x,
8793 y;
8794
8795 /*
8796 Tile the composite image.
8797 */
cristy4a3ce0a2013-08-03 20:06:59 +00008798 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8799 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8800 {
8801 if (attribute_flag[8] != 0) /* rotate */
8802 (void) CompositeImage(image,rotate_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008803 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008804 else
8805 (void) CompositeImage(image,composite_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008806 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008807 }
8808 if (attribute_flag[8] != 0) /* rotate */
8809 rotate_image=DestroyImage(rotate_image);
8810 break;
8811 }
8812 /*
8813 Parameter Handling used used ONLY for normal composition.
8814 */
8815 if (attribute_flag[5] != 0) /* gravity */
8816 image->gravity=(GravityType) argument_list[5].integer_reference;
8817 if (attribute_flag[2] != 0) /* geometry offset */
8818 {
8819 SetGeometry(image,&geometry);
8820 (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8821 &geometry);
8822 GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8823 &geometry);
8824 }
8825 if (attribute_flag[3] != 0) /* x offset */
8826 geometry.x=argument_list[3].integer_reference;
8827 if (attribute_flag[4] != 0) /* y offset */
8828 geometry.y=argument_list[4].integer_reference;
8829 if (attribute_flag[10] != 0) /* mask */
8830 {
8831 if ((image->compose == DisplaceCompositeOp) ||
8832 (image->compose == DistortCompositeOp))
8833 {
8834 /*
8835 Merge Y displacement into X displacement image.
8836 */
8837 composite_image=CloneImage(composite_image,0,0,MagickTrue,
8838 exception);
8839 (void) CompositeImage(composite_image,
8840 argument_list[10].image_reference,CopyGreenCompositeOp,
Cristy74e39292018-07-08 13:13:20 -04008841 clip_to_self,0,0,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008842 }
8843 else
8844 {
8845 Image
8846 *mask_image;
8847
8848 /*
8849 Set a blending mask for the composition.
8850 */
8851 mask_image=CloneImage(argument_list[10].image_reference,0,0,
8852 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +00008853 (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
cristyf3023752015-07-28 17:13:22 +00008854 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008855 mask_image=DestroyImage(mask_image);
8856 }
8857 }
8858 if (attribute_flag[11] != 0) /* channel */
8859 channel=(ChannelType) argument_list[11].integer_reference;
8860 /*
8861 Composite two images (normal composition).
8862 */
cristy151b66d2015-04-15 10:50:31 +00008863 (void) FormatLocaleString(composite_geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00008864 "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8865 (double) composite_image->rows,(double) geometry.x,(double)
8866 geometry.y);
8867 flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8868 exception);
8869 channel_mask=SetImageChannelMask(image,channel);
8870 if (attribute_flag[8] == 0) /* no rotate */
8871 CompositeImage(image,composite_image,compose,clip_to_self,
8872 geometry.x,geometry.y,exception);
8873 else
8874 {
8875 /*
8876 Position adjust rotated image then composite.
8877 */
8878 geometry.x-=(ssize_t) (rotate_image->columns-
8879 composite_image->columns)/2;
8880 geometry.y-=(ssize_t) (rotate_image->rows-
8881 composite_image->rows)/2;
8882 CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8883 geometry.y,exception);
8884 rotate_image=DestroyImage(rotate_image);
8885 }
8886 if (attribute_flag[10] != 0) /* mask */
8887 {
8888 if ((image->compose == DisplaceCompositeOp) ||
8889 (image->compose == DistortCompositeOp))
8890 composite_image=DestroyImage(composite_image);
8891 else
cristy1f7ffb72015-07-29 11:07:03 +00008892 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
cristyf3023752015-07-28 17:13:22 +00008893 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008894 }
8895 (void) SetImageChannelMask(image,channel_mask);
8896 break;
8897 }
8898 case 36: /* Contrast */
8899 {
8900 if (attribute_flag[0] == 0)
8901 argument_list[0].integer_reference=0;
8902 (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8903 MagickTrue : MagickFalse,exception);
8904 break;
8905 }
8906 case 37: /* CycleColormap */
8907 {
8908 if (attribute_flag[0] == 0)
8909 argument_list[0].integer_reference=6;
8910 (void) CycleColormapImage(image,argument_list[0].integer_reference,
8911 exception);
8912 break;
8913 }
8914 case 38: /* Draw */
8915 {
8916 DrawInfo
8917 *draw_info;
8918
8919 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8920 (DrawInfo *) NULL);
8921 (void) CloneString(&draw_info->primitive,"point");
8922 if (attribute_flag[0] != 0)
8923 {
8924 if (argument_list[0].integer_reference < 0)
8925 (void) CloneString(&draw_info->primitive,
8926 argument_list[0].string_reference);
8927 else
8928 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8929 MagickPrimitiveOptions,argument_list[0].integer_reference));
8930 }
8931 if (attribute_flag[1] != 0)
8932 {
8933 if (LocaleCompare(draw_info->primitive,"path") == 0)
8934 {
8935 (void) ConcatenateString(&draw_info->primitive," '");
8936 ConcatenateString(&draw_info->primitive,
8937 argument_list[1].string_reference);
8938 (void) ConcatenateString(&draw_info->primitive,"'");
8939 }
8940 else
8941 {
8942 (void) ConcatenateString(&draw_info->primitive," ");
8943 ConcatenateString(&draw_info->primitive,
8944 argument_list[1].string_reference);
8945 }
8946 }
8947 if (attribute_flag[2] != 0)
8948 {
8949 (void) ConcatenateString(&draw_info->primitive," ");
8950 (void) ConcatenateString(&draw_info->primitive,
8951 CommandOptionToMnemonic(MagickMethodOptions,
8952 argument_list[2].integer_reference));
8953 }
8954 if (attribute_flag[3] != 0)
8955 {
8956 (void) QueryColorCompliance(argument_list[3].string_reference,
8957 AllCompliance,&draw_info->stroke,exception);
8958 if (argument_list[3].image_reference != (Image *) NULL)
8959 draw_info->stroke_pattern=CloneImage(
8960 argument_list[3].image_reference,0,0,MagickTrue,exception);
8961 }
8962 if (attribute_flag[4] != 0)
8963 {
8964 (void) QueryColorCompliance(argument_list[4].string_reference,
8965 AllCompliance,&draw_info->fill,exception);
8966 if (argument_list[4].image_reference != (Image *) NULL)
8967 draw_info->fill_pattern=CloneImage(
8968 argument_list[4].image_reference,0,0,MagickTrue,exception);
8969 }
8970 if (attribute_flag[5] != 0)
8971 draw_info->stroke_width=argument_list[5].real_reference;
8972 if (attribute_flag[6] != 0)
8973 (void) CloneString(&draw_info->font,
8974 argument_list[6].string_reference);
8975 if (attribute_flag[7] != 0)
8976 (void) QueryColorCompliance(argument_list[7].string_reference,
8977 AllCompliance,&draw_info->border_color,exception);
8978 if (attribute_flag[8] != 0)
8979 draw_info->affine.tx=argument_list[8].real_reference;
8980 if (attribute_flag[9] != 0)
8981 draw_info->affine.ty=argument_list[9].real_reference;
8982 if (attribute_flag[20] != 0)
8983 {
8984 AV
8985 *av;
8986
8987 av=(AV *) argument_list[20].array_reference;
8988 if ((av_len(av) != 3) && (av_len(av) != 5))
8989 {
8990 ThrowPerlException(exception,OptionError,
8991 "affine matrix must have 4 or 6 elements",PackageName);
8992 goto PerlException;
8993 }
8994 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8995 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8996 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8997 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8998 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8999 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9000 {
9001 ThrowPerlException(exception,OptionError,
9002 "affine matrix is singular",PackageName);
9003 goto PerlException;
9004 }
9005 if (av_len(av) == 5)
9006 {
9007 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9008 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9009 }
9010 }
9011 for (j=10; j < 15; j++)
9012 {
9013 if (attribute_flag[j] == 0)
9014 continue;
9015 value=argument_list[j].string_reference;
9016 angle=argument_list[j].real_reference;
9017 current=draw_info->affine;
9018 GetAffineMatrix(&affine);
9019 switch (j)
9020 {
9021 case 10:
9022 {
9023 /*
9024 Translate.
9025 */
9026 flags=ParseGeometry(value,&geometry_info);
9027 affine.tx=geometry_info.xi;
9028 affine.ty=geometry_info.psi;
9029 if ((flags & PsiValue) == 0)
9030 affine.ty=affine.tx;
9031 break;
9032 }
9033 case 11:
9034 {
9035 /*
9036 Scale.
9037 */
9038 flags=ParseGeometry(value,&geometry_info);
9039 affine.sx=geometry_info.rho;
9040 affine.sy=geometry_info.sigma;
9041 if ((flags & SigmaValue) == 0)
9042 affine.sy=affine.sx;
9043 break;
9044 }
9045 case 12:
9046 {
9047 /*
9048 Rotate.
9049 */
9050 if (angle == 0.0)
9051 break;
9052 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9053 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9054 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9055 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9056 break;
9057 }
9058 case 13:
9059 {
9060 /*
9061 SkewX.
9062 */
9063 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9064 break;
9065 }
9066 case 14:
9067 {
9068 /*
9069 SkewY.
9070 */
9071 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9072 break;
9073 }
9074 }
9075 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9076 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9077 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9078 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9079 draw_info->affine.tx=
9080 current.sx*affine.tx+current.ry*affine.ty+current.tx;
9081 draw_info->affine.ty=
9082 current.rx*affine.tx+current.sy*affine.ty+current.ty;
9083 }
9084 if (attribute_flag[15] != 0)
9085 draw_info->fill_pattern=CloneImage(
9086 argument_list[15].image_reference,0,0,MagickTrue,exception);
9087 if (attribute_flag[16] != 0)
9088 draw_info->pointsize=argument_list[16].real_reference;
9089 if (attribute_flag[17] != 0)
9090 {
9091 draw_info->stroke_antialias=argument_list[17].integer_reference != 0
9092 ? MagickTrue : MagickFalse;
9093 draw_info->text_antialias=draw_info->stroke_antialias;
9094 }
9095 if (attribute_flag[18] != 0)
9096 (void) CloneString(&draw_info->density,
9097 argument_list[18].string_reference);
9098 if (attribute_flag[19] != 0)
9099 draw_info->stroke_width=argument_list[19].real_reference;
9100 if (attribute_flag[21] != 0)
9101 draw_info->dash_offset=argument_list[21].real_reference;
9102 if (attribute_flag[22] != 0)
9103 {
9104 AV
9105 *av;
9106
9107 av=(AV *) argument_list[22].array_reference;
9108 draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9109 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9110 if (draw_info->dash_pattern != (double *) NULL)
9111 {
9112 for (i=0; i <= av_len(av); i++)
9113 draw_info->dash_pattern[i]=(double)
9114 SvNV(*(av_fetch(av,i,0)));
9115 draw_info->dash_pattern[i]=0.0;
9116 }
9117 }
9118 if (attribute_flag[23] != 0)
9119 image->interpolate=(PixelInterpolateMethod)
9120 argument_list[23].integer_reference;
9121 if ((attribute_flag[24] != 0) &&
9122 (draw_info->fill_pattern != (Image *) NULL))
9123 flags=ParsePageGeometry(draw_info->fill_pattern,
9124 argument_list[24].string_reference,
9125 &draw_info->fill_pattern->tile_offset,exception);
9126 if (attribute_flag[25] != 0)
9127 {
9128 (void) ConcatenateString(&draw_info->primitive," '");
9129 (void) ConcatenateString(&draw_info->primitive,
9130 argument_list[25].string_reference);
9131 (void) ConcatenateString(&draw_info->primitive,"'");
9132 }
9133 if (attribute_flag[26] != 0)
9134 draw_info->fill_pattern=CloneImage(
9135 argument_list[26].image_reference,0,0,MagickTrue,exception);
9136 if (attribute_flag[27] != 0)
9137 draw_info->stroke_pattern=CloneImage(
9138 argument_list[27].image_reference,0,0,MagickTrue,exception);
9139 if (attribute_flag[28] != 0)
9140 (void) CloneString(&draw_info->primitive,
9141 argument_list[28].string_reference);
9142 if (attribute_flag[29] != 0)
9143 draw_info->kerning=argument_list[29].real_reference;
9144 if (attribute_flag[30] != 0)
9145 draw_info->interline_spacing=argument_list[30].real_reference;
9146 if (attribute_flag[31] != 0)
9147 draw_info->interword_spacing=argument_list[31].real_reference;
9148 if (attribute_flag[32] != 0)
9149 draw_info->direction=(DirectionType)
9150 argument_list[32].integer_reference;
9151 DrawImage(image,draw_info,exception);
9152 draw_info=DestroyDrawInfo(draw_info);
9153 break;
9154 }
9155 case 39: /* Equalize */
9156 {
9157 if (attribute_flag[0] != 0)
9158 channel=(ChannelType) argument_list[0].integer_reference;
9159 channel_mask=SetImageChannelMask(image,channel);
9160 EqualizeImage(image,exception);
9161 (void) SetImageChannelMask(image,channel_mask);
9162 break;
9163 }
9164 case 40: /* Gamma */
9165 {
9166 if (attribute_flag[1] != 0)
9167 channel=(ChannelType) argument_list[1].integer_reference;
9168 if (attribute_flag[2] == 0)
9169 argument_list[2].real_reference=1.0;
9170 if (attribute_flag[3] == 0)
9171 argument_list[3].real_reference=1.0;
9172 if (attribute_flag[4] == 0)
9173 argument_list[4].real_reference=1.0;
9174 if (attribute_flag[0] == 0)
9175 {
cristy151b66d2015-04-15 10:50:31 +00009176 (void) FormatLocaleString(message,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -05009177 "%.20g,%.20g,%.20g",(double) argument_list[2].real_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009178 (double) argument_list[3].real_reference,
9179 (double) argument_list[4].real_reference);
9180 argument_list[0].string_reference=message;
9181 }
9182 (void) GammaImage(image,StringToDouble(
9183 argument_list[0].string_reference,(char **) NULL),exception);
9184 break;
9185 }
9186 case 41: /* Map */
9187 {
9188 QuantizeInfo
9189 *quantize_info;
9190
9191 if (attribute_flag[0] == 0)
9192 {
9193 ThrowPerlException(exception,OptionError,"MapImageRequired",
9194 PackageName);
9195 goto PerlException;
9196 }
9197 quantize_info=AcquireQuantizeInfo(info->image_info);
9198 if (attribute_flag[1] != 0)
9199 quantize_info->dither_method=(DitherMethod)
9200 argument_list[1].integer_reference;
9201 (void) RemapImages(quantize_info,image,
9202 argument_list[0].image_reference,exception);
9203 quantize_info=DestroyQuantizeInfo(quantize_info);
9204 break;
9205 }
9206 case 42: /* MatteFloodfill */
9207 {
9208 DrawInfo
9209 *draw_info;
9210
9211 MagickBooleanType
9212 invert;
9213
9214 PixelInfo
9215 target;
9216
9217 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9218 (DrawInfo *) NULL);
9219 if (attribute_flag[0] != 0)
9220 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9221 &geometry,exception);
9222 if (attribute_flag[1] != 0)
9223 geometry.x=argument_list[1].integer_reference;
9224 if (attribute_flag[2] != 0)
9225 geometry.y=argument_list[2].integer_reference;
cristy17f11b02014-12-20 19:37:04 +00009226 if (image->alpha_trait == UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00009227 (void) SetImageAlpha(image,OpaqueAlpha,exception);
9228 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9229 geometry.x,geometry.y,&target,exception);
9230 if (attribute_flag[4] != 0)
9231 QueryColorCompliance(argument_list[4].string_reference,
9232 AllCompliance,&target,exception);
9233 if (attribute_flag[3] != 0)
9234 target.alpha=StringToDoubleInterval(
9235 argument_list[3].string_reference,(double) (double) QuantumRange+
9236 1.0);
9237 if (attribute_flag[5] != 0)
9238 image->fuzz=StringToDoubleInterval(
9239 argument_list[5].string_reference,(double) QuantumRange+1.0);
9240 invert=MagickFalse;
9241 if (attribute_flag[6] != 0)
9242 invert=(MagickBooleanType) argument_list[6].integer_reference;
9243 channel_mask=SetImageChannelMask(image,AlphaChannel);
9244 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9245 geometry.y,invert,exception);
9246 (void) SetImageChannelMask(image,channel_mask);
9247 draw_info=DestroyDrawInfo(draw_info);
9248 break;
9249 }
9250 case 43: /* Modulate */
9251 {
9252 char
cristy151b66d2015-04-15 10:50:31 +00009253 modulate[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00009254
9255 geometry_info.rho=100.0;
9256 geometry_info.sigma=100.0;
9257 geometry_info.xi=100.0;
9258 if (attribute_flag[0] != 0)
9259 (void)ParseGeometry(argument_list[0].string_reference,
9260 &geometry_info);
9261 if (attribute_flag[1] != 0)
9262 geometry_info.xi=argument_list[1].real_reference;
9263 if (attribute_flag[2] != 0)
9264 geometry_info.sigma=argument_list[2].real_reference;
9265 if (attribute_flag[3] != 0)
9266 {
9267 geometry_info.sigma=argument_list[3].real_reference;
9268 SetImageArtifact(image,"modulate:colorspace","HWB");
9269 }
9270 if (attribute_flag[4] != 0)
9271 {
9272 geometry_info.rho=argument_list[4].real_reference;
9273 SetImageArtifact(image,"modulate:colorspace","HSB");
9274 }
9275 if (attribute_flag[5] != 0)
9276 {
9277 geometry_info.sigma=argument_list[5].real_reference;
9278 SetImageArtifact(image,"modulate:colorspace","HSL");
9279 }
9280 if (attribute_flag[6] != 0)
9281 {
9282 geometry_info.rho=argument_list[6].real_reference;
9283 SetImageArtifact(image,"modulate:colorspace","HWB");
9284 }
Cristy935a4052017-03-31 17:45:37 -04009285 (void) FormatLocaleString(modulate,MagickPathExtent,"%.20g,%.20g,%.20g",
9286 geometry_info.rho,geometry_info.sigma,geometry_info.xi);
cristy4a3ce0a2013-08-03 20:06:59 +00009287 (void) ModulateImage(image,modulate,exception);
9288 break;
9289 }
9290 case 44: /* Negate */
9291 {
9292 if (attribute_flag[0] == 0)
9293 argument_list[0].integer_reference=0;
9294 if (attribute_flag[1] != 0)
9295 channel=(ChannelType) argument_list[1].integer_reference;
9296 channel_mask=SetImageChannelMask(image,channel);
9297 (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9298 MagickTrue : MagickFalse,exception);
9299 (void) SetImageChannelMask(image,channel_mask);
9300 break;
9301 }
9302 case 45: /* Normalize */
9303 {
9304 if (attribute_flag[0] != 0)
9305 channel=(ChannelType) argument_list[0].integer_reference;
9306 channel_mask=SetImageChannelMask(image,channel);
9307 NormalizeImage(image,exception);
9308 (void) SetImageChannelMask(image,channel_mask);
9309 break;
9310 }
9311 case 46: /* NumberColors */
9312 break;
9313 case 47: /* Opaque */
9314 {
9315 MagickBooleanType
9316 invert;
9317
9318 PixelInfo
9319 fill_color,
9320 target;
9321
9322 (void) QueryColorCompliance("none",AllCompliance,&target,
9323 exception);
9324 (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9325 exception);
9326 if (attribute_flag[0] != 0)
9327 (void) QueryColorCompliance(argument_list[0].string_reference,
9328 AllCompliance,&target,exception);
9329 if (attribute_flag[1] != 0)
9330 (void) QueryColorCompliance(argument_list[1].string_reference,
9331 AllCompliance,&fill_color,exception);
9332 if (attribute_flag[2] != 0)
9333 image->fuzz=StringToDoubleInterval(
9334 argument_list[2].string_reference,(double) QuantumRange+1.0);
9335 if (attribute_flag[3] != 0)
9336 channel=(ChannelType) argument_list[3].integer_reference;
9337 invert=MagickFalse;
9338 if (attribute_flag[4] != 0)
9339 invert=(MagickBooleanType) argument_list[4].integer_reference;
9340 channel_mask=SetImageChannelMask(image,channel);
9341 (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9342 (void) SetImageChannelMask(image,channel_mask);
9343 break;
9344 }
9345 case 48: /* Quantize */
9346 {
9347 QuantizeInfo
9348 *quantize_info;
9349
9350 quantize_info=AcquireQuantizeInfo(info->image_info);
9351 if (attribute_flag[0] != 0)
9352 quantize_info->number_colors=(size_t)
9353 argument_list[0].integer_reference;
9354 if (attribute_flag[1] != 0)
9355 quantize_info->tree_depth=(size_t)
9356 argument_list[1].integer_reference;
9357 if (attribute_flag[2] != 0)
9358 quantize_info->colorspace=(ColorspaceType)
9359 argument_list[2].integer_reference;
9360 if (attribute_flag[3] != 0)
cristy785c9342014-03-19 22:06:39 +00009361 quantize_info->dither_method=(DitherMethod)
9362 argument_list[3].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00009363 if (attribute_flag[4] != 0)
cristy71716d52014-03-19 10:11:11 +00009364 quantize_info->measure_error=
9365 argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
cristy4a3ce0a2013-08-03 20:06:59 +00009366 if (attribute_flag[6] != 0)
cristyd472dd82014-03-19 22:04:36 +00009367 (void) QueryColorCompliance(argument_list[6].string_reference,
cristyf7563392014-03-25 13:54:04 +00009368 AllCompliance,&image->transparent_color,exception);
cristy71716d52014-03-19 10:11:11 +00009369 if (attribute_flag[7] != 0)
cristy4a3ce0a2013-08-03 20:06:59 +00009370 quantize_info->dither_method=(DitherMethod)
cristy71716d52014-03-19 10:11:11 +00009371 argument_list[7].integer_reference;
9372 if (attribute_flag[5] && argument_list[5].integer_reference)
cristyf7563392014-03-25 13:54:04 +00009373 (void) QuantizeImages(quantize_info,image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009374 else
cristyf7563392014-03-25 13:54:04 +00009375 if ((image->storage_class == DirectClass) ||
9376 (image->colors > quantize_info->number_colors) ||
9377 (quantize_info->colorspace == GRAYColorspace))
9378 (void) QuantizeImage(quantize_info,image,exception);
9379 else
9380 CompressImageColormap(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009381 quantize_info=DestroyQuantizeInfo(quantize_info);
9382 break;
9383 }
9384 case 49: /* Raise */
9385 {
9386 if (attribute_flag[0] != 0)
9387 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9388 &geometry,exception);
9389 if (attribute_flag[1] != 0)
9390 geometry.width=argument_list[1].integer_reference;
9391 if (attribute_flag[2] != 0)
9392 geometry.height=argument_list[2].integer_reference;
9393 if (attribute_flag[3] == 0)
9394 argument_list[3].integer_reference=1;
9395 (void) RaiseImage(image,&geometry,
9396 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9397 exception);
9398 break;
9399 }
9400 case 50: /* Segment */
9401 {
9402 ColorspaceType
9403 colorspace;
9404
9405 double
9406 cluster_threshold,
9407 smoothing_threshold;
9408
9409 MagickBooleanType
9410 verbose;
9411
9412 cluster_threshold=1.0;
9413 smoothing_threshold=1.5;
9414 colorspace=sRGBColorspace;
9415 verbose=MagickFalse;
9416 if (attribute_flag[0] != 0)
9417 {
9418 flags=ParseGeometry(argument_list[0].string_reference,
9419 &geometry_info);
9420 cluster_threshold=geometry_info.rho;
9421 if (flags & SigmaValue)
9422 smoothing_threshold=geometry_info.sigma;
9423 }
9424 if (attribute_flag[1] != 0)
9425 cluster_threshold=argument_list[1].real_reference;
9426 if (attribute_flag[2] != 0)
9427 smoothing_threshold=argument_list[2].real_reference;
9428 if (attribute_flag[3] != 0)
9429 colorspace=(ColorspaceType) argument_list[3].integer_reference;
9430 if (attribute_flag[4] != 0)
9431 verbose=argument_list[4].integer_reference != 0 ?
9432 MagickTrue : MagickFalse;
9433 (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9434 smoothing_threshold,exception);
9435 break;
9436 }
9437 case 51: /* Signature */
9438 {
9439 (void) SignatureImage(image,exception);
9440 break;
9441 }
9442 case 52: /* Solarize */
9443 {
9444 geometry_info.rho=QuantumRange/2.0;
9445 if (attribute_flag[0] != 0)
9446 flags=ParseGeometry(argument_list[0].string_reference,
9447 &geometry_info);
9448 if (attribute_flag[1] != 0)
9449 geometry_info.rho=StringToDoubleInterval(
9450 argument_list[1].string_reference,(double) QuantumRange+1.0);
9451 (void) SolarizeImage(image,geometry_info.rho,exception);
9452 break;
9453 }
9454 case 53: /* Sync */
9455 {
9456 (void) SyncImage(image,exception);
9457 break;
9458 }
9459 case 54: /* Texture */
9460 {
9461 if (attribute_flag[0] == 0)
9462 break;
9463 TextureImage(image,argument_list[0].image_reference,exception);
9464 break;
9465 }
9466 case 55: /* Evalute */
9467 {
9468 MagickEvaluateOperator
9469 op;
9470
9471 op=SetEvaluateOperator;
9472 if (attribute_flag[0] == MagickFalse)
9473 argument_list[0].real_reference=0.0;
9474 if (attribute_flag[1] != MagickFalse)
9475 op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9476 if (attribute_flag[2] != MagickFalse)
9477 channel=(ChannelType) argument_list[2].integer_reference;
9478 channel_mask=SetImageChannelMask(image,channel);
9479 (void) EvaluateImage(image,op,argument_list[0].real_reference,
9480 exception);
9481 (void) SetImageChannelMask(image,channel_mask);
9482 break;
9483 }
9484 case 56: /* Transparent */
9485 {
9486 double
9487 opacity;
9488
9489 MagickBooleanType
9490 invert;
9491
9492 PixelInfo
9493 target;
9494
9495 (void) QueryColorCompliance("none",AllCompliance,&target,
9496 exception);
9497 if (attribute_flag[0] != 0)
9498 (void) QueryColorCompliance(argument_list[0].string_reference,
9499 AllCompliance,&target,exception);
9500 opacity=TransparentAlpha;
9501 if (attribute_flag[1] != 0)
9502 opacity=StringToDoubleInterval(argument_list[1].string_reference,
9503 (double) QuantumRange+1.0);
9504 if (attribute_flag[2] != 0)
9505 image->fuzz=StringToDoubleInterval(
9506 argument_list[2].string_reference,(double) QuantumRange+1.0);
9507 if (attribute_flag[3] == 0)
9508 argument_list[3].integer_reference=0;
9509 invert=MagickFalse;
9510 if (attribute_flag[3] != 0)
9511 invert=(MagickBooleanType) argument_list[3].integer_reference;
9512 (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9513 invert,exception);
9514 break;
9515 }
9516 case 57: /* Threshold */
9517 {
9518 double
9519 threshold;
9520
9521 if (attribute_flag[0] == 0)
9522 argument_list[0].string_reference="50%";
9523 if (attribute_flag[1] != 0)
9524 channel=(ChannelType) argument_list[1].integer_reference;
9525 threshold=StringToDoubleInterval(argument_list[0].string_reference,
9526 (double) QuantumRange+1.0);
9527 channel_mask=SetImageChannelMask(image,channel);
9528 (void) BilevelImage(image,threshold,exception);
9529 (void) SetImageChannelMask(image,channel_mask);
9530 break;
9531 }
9532 case 58: /* Charcoal */
9533 {
9534 if (attribute_flag[0] != 0)
9535 {
9536 flags=ParseGeometry(argument_list[0].string_reference,
9537 &geometry_info);
9538 if ((flags & SigmaValue) == 0)
9539 geometry_info.sigma=1.0;
9540 }
9541 if (attribute_flag[1] != 0)
9542 geometry_info.rho=argument_list[1].real_reference;
9543 if (attribute_flag[2] != 0)
9544 geometry_info.sigma=argument_list[2].real_reference;
9545 image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9546 exception);
9547 break;
9548 }
9549 case 59: /* Trim */
9550 {
9551 if (attribute_flag[0] != 0)
9552 image->fuzz=StringToDoubleInterval(
9553 argument_list[0].string_reference,(double) QuantumRange+1.0);
9554 image=TrimImage(image,exception);
9555 break;
9556 }
9557 case 60: /* Wave */
9558 {
9559 PixelInterpolateMethod
9560 method;
9561
9562 if (attribute_flag[0] != 0)
9563 {
9564 flags=ParseGeometry(argument_list[0].string_reference,
9565 &geometry_info);
9566 if ((flags & SigmaValue) == 0)
9567 geometry_info.sigma=1.0;
9568 }
9569 if (attribute_flag[1] != 0)
9570 geometry_info.rho=argument_list[1].real_reference;
9571 if (attribute_flag[2] != 0)
9572 geometry_info.sigma=argument_list[2].real_reference;
9573 method=UndefinedInterpolatePixel;
9574 if (attribute_flag[3] != 0)
9575 method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9576 image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9577 method,exception);
9578 break;
9579 }
9580 case 61: /* Separate */
9581 {
9582 if (attribute_flag[0] != 0)
9583 channel=(ChannelType) argument_list[0].integer_reference;
9584 image=SeparateImage(image,channel,exception);
9585 break;
9586 }
9587 case 63: /* Stereo */
9588 {
9589 if (attribute_flag[0] == 0)
9590 {
9591 ThrowPerlException(exception,OptionError,"StereoImageRequired",
9592 PackageName);
9593 goto PerlException;
9594 }
9595 if (attribute_flag[1] != 0)
9596 geometry.x=argument_list[1].integer_reference;
9597 if (attribute_flag[2] != 0)
9598 geometry.y=argument_list[2].integer_reference;
9599 image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9600 geometry.x,geometry.y,exception);
9601 break;
9602 }
9603 case 64: /* Stegano */
9604 {
9605 if (attribute_flag[0] == 0)
9606 {
9607 ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9608 PackageName);
9609 goto PerlException;
9610 }
9611 if (attribute_flag[1] == 0)
9612 argument_list[1].integer_reference=0;
9613 image->offset=argument_list[1].integer_reference;
9614 image=SteganoImage(image,argument_list[0].image_reference,exception);
9615 break;
9616 }
9617 case 65: /* Deconstruct */
9618 {
9619 image=CompareImagesLayers(image,CompareAnyLayer,exception);
9620 break;
9621 }
9622 case 66: /* GaussianBlur */
9623 {
9624 if (attribute_flag[0] != 0)
9625 {
9626 flags=ParseGeometry(argument_list[0].string_reference,
9627 &geometry_info);
9628 if ((flags & SigmaValue) == 0)
9629 geometry_info.sigma=1.0;
9630 }
9631 if (attribute_flag[1] != 0)
9632 geometry_info.rho=argument_list[1].real_reference;
9633 if (attribute_flag[2] != 0)
9634 geometry_info.sigma=argument_list[2].real_reference;
9635 if (attribute_flag[3] != 0)
9636 channel=(ChannelType) argument_list[3].integer_reference;
9637 channel_mask=SetImageChannelMask(image,channel);
9638 image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9639 exception);
9640 if (image != (Image *) NULL)
9641 (void) SetImageChannelMask(image,channel_mask);
9642 break;
9643 }
9644 case 67: /* Convolve */
9645 {
9646 KernelInfo
9647 *kernel;
9648
9649 kernel=(KernelInfo *) NULL;
9650 if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9651 break;
9652 if (attribute_flag[0] != 0)
9653 {
9654 AV
9655 *av;
9656
9657 size_t
9658 order;
9659
cristy2c57b742014-10-31 00:40:34 +00009660 kernel=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009661 if (kernel == (KernelInfo *) NULL)
9662 break;
9663 av=(AV *) argument_list[0].array_reference;
9664 order=(size_t) sqrt(av_len(av)+1);
9665 kernel->width=order;
9666 kernel->height=order;
9667 kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9668 order*sizeof(*kernel->values));
9669 if (kernel->values == (MagickRealType *) NULL)
9670 {
9671 kernel=DestroyKernelInfo(kernel);
9672 ThrowPerlException(exception,ResourceLimitFatalError,
9673 "MemoryAllocationFailed",PackageName);
9674 goto PerlException;
9675 }
9676 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9677 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9678 for ( ; j < (ssize_t) (order*order); j++)
9679 kernel->values[j]=0.0;
9680 }
9681 if (attribute_flag[1] != 0)
9682 channel=(ChannelType) argument_list[1].integer_reference;
9683 if (attribute_flag[2] != 0)
Cristyc4ff6bd2017-07-05 21:00:11 -04009684 SetImageArtifact(image,"convolve:bias",
cristy4a3ce0a2013-08-03 20:06:59 +00009685 argument_list[2].string_reference);
9686 if (attribute_flag[3] != 0)
9687 {
cristy2c57b742014-10-31 00:40:34 +00009688 kernel=AcquireKernelInfo(argument_list[3].string_reference,
9689 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009690 if (kernel == (KernelInfo *) NULL)
9691 break;
9692 }
9693 channel_mask=SetImageChannelMask(image,channel);
9694 image=ConvolveImage(image,kernel,exception);
9695 if (image != (Image *) NULL)
9696 (void) SetImageChannelMask(image,channel_mask);
9697 kernel=DestroyKernelInfo(kernel);
9698 break;
9699 }
9700 case 68: /* Profile */
9701 {
9702 const char
9703 *name;
9704
9705 Image
9706 *profile_image;
9707
9708 ImageInfo
9709 *profile_info;
9710
9711 StringInfo
9712 *profile;
9713
9714 name="*";
9715 if (attribute_flag[0] != 0)
9716 name=argument_list[0].string_reference;
9717 if (attribute_flag[2] != 0)
9718 image->rendering_intent=(RenderingIntent)
9719 argument_list[2].integer_reference;
9720 if (attribute_flag[3] != 0)
9721 image->black_point_compensation=
9722 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9723 if (attribute_flag[1] != 0)
9724 {
9725 if (argument_list[1].length == 0)
9726 {
9727 /*
9728 Remove a profile from the image.
9729 */
9730 (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9731 exception);
9732 break;
9733 }
9734 /*
9735 Associate user supplied profile with the image.
9736 */
9737 profile=AcquireStringInfo(argument_list[1].length);
9738 SetStringInfoDatum(profile,(const unsigned char *)
9739 argument_list[1].string_reference);
9740 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9741 (size_t) GetStringInfoLength(profile),exception);
9742 profile=DestroyStringInfo(profile);
9743 break;
9744 }
9745 /*
9746 Associate a profile with the image.
9747 */
9748 profile_info=CloneImageInfo(info ? info->image_info :
9749 (ImageInfo *) NULL);
9750 profile_image=ReadImages(profile_info,name,exception);
9751 if (profile_image == (Image *) NULL)
9752 break;
9753 ResetImageProfileIterator(profile_image);
9754 name=GetNextImageProfile(profile_image);
9755 while (name != (const char *) NULL)
9756 {
9757 const StringInfo
9758 *profile;
9759
9760 profile=GetImageProfile(profile_image,name);
9761 if (profile != (const StringInfo *) NULL)
9762 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9763 (size_t) GetStringInfoLength(profile),exception);
9764 name=GetNextImageProfile(profile_image);
9765 }
9766 profile_image=DestroyImage(profile_image);
9767 profile_info=DestroyImageInfo(profile_info);
9768 break;
9769 }
9770 case 69: /* UnsharpMask */
9771 {
9772 if (attribute_flag[0] != 0)
9773 {
9774 flags=ParseGeometry(argument_list[0].string_reference,
9775 &geometry_info);
9776 if ((flags & SigmaValue) == 0)
9777 geometry_info.sigma=1.0;
9778 if ((flags & XiValue) == 0)
9779 geometry_info.xi=1.0;
9780 if ((flags & PsiValue) == 0)
9781 geometry_info.psi=0.5;
9782 }
9783 if (attribute_flag[1] != 0)
9784 geometry_info.rho=argument_list[1].real_reference;
9785 if (attribute_flag[2] != 0)
9786 geometry_info.sigma=argument_list[2].real_reference;
9787 if (attribute_flag[3] != 0)
9788 geometry_info.xi=argument_list[3].real_reference;
9789 if (attribute_flag[4] != 0)
9790 geometry_info.psi=argument_list[4].real_reference;
9791 if (attribute_flag[5] != 0)
9792 channel=(ChannelType) argument_list[5].integer_reference;
9793 channel_mask=SetImageChannelMask(image,channel);
9794 image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9795 geometry_info.xi,geometry_info.psi,exception);
9796 if (image != (Image *) NULL)
9797 (void) SetImageChannelMask(image,channel_mask);
9798 break;
9799 }
9800 case 70: /* MotionBlur */
9801 {
9802 if (attribute_flag[0] != 0)
9803 {
9804 flags=ParseGeometry(argument_list[0].string_reference,
9805 &geometry_info);
9806 if ((flags & SigmaValue) == 0)
9807 geometry_info.sigma=1.0;
9808 if ((flags & XiValue) == 0)
9809 geometry_info.xi=1.0;
9810 }
9811 if (attribute_flag[1] != 0)
9812 geometry_info.rho=argument_list[1].real_reference;
9813 if (attribute_flag[2] != 0)
9814 geometry_info.sigma=argument_list[2].real_reference;
9815 if (attribute_flag[3] != 0)
9816 geometry_info.xi=argument_list[3].real_reference;
9817 if (attribute_flag[4] != 0)
9818 channel=(ChannelType) argument_list[4].integer_reference;
9819 channel_mask=SetImageChannelMask(image,channel);
9820 image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9821 geometry_info.xi,exception);
9822 if (image != (Image *) NULL)
9823 (void) SetImageChannelMask(image,channel_mask);
9824 break;
9825 }
9826 case 71: /* OrderedDither */
9827 {
9828 if (attribute_flag[0] == 0)
9829 argument_list[0].string_reference="o8x8";
9830 if (attribute_flag[1] != 0)
9831 channel=(ChannelType) argument_list[1].integer_reference;
9832 channel_mask=SetImageChannelMask(image,channel);
Cristy6b93c072016-02-04 07:45:48 -05009833 (void) OrderedDitherImage(image,argument_list[0].string_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009834 exception);
9835 (void) SetImageChannelMask(image,channel_mask);
9836 break;
9837 }
9838 case 72: /* Shave */
9839 {
9840 if (attribute_flag[0] != 0)
9841 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9842 &geometry,exception);
9843 if (attribute_flag[1] != 0)
9844 geometry.width=argument_list[1].integer_reference;
9845 if (attribute_flag[2] != 0)
9846 geometry.height=argument_list[2].integer_reference;
9847 image=ShaveImage(image,&geometry,exception);
9848 break;
9849 }
9850 case 73: /* Level */
9851 {
9852 double
9853 black_point,
9854 gamma,
9855 white_point;
9856
9857 black_point=0.0;
9858 white_point=(double) image->columns*image->rows;
9859 gamma=1.0;
9860 if (attribute_flag[0] != 0)
9861 {
9862 flags=ParseGeometry(argument_list[0].string_reference,
9863 &geometry_info);
9864 black_point=geometry_info.rho;
9865 if ((flags & SigmaValue) != 0)
9866 white_point=geometry_info.sigma;
9867 if ((flags & XiValue) != 0)
9868 gamma=geometry_info.xi;
9869 if ((flags & PercentValue) != 0)
9870 {
9871 black_point*=(double) (QuantumRange/100.0);
9872 white_point*=(double) (QuantumRange/100.0);
9873 }
9874 if ((flags & SigmaValue) == 0)
9875 white_point=(double) QuantumRange-black_point;
9876 }
9877 if (attribute_flag[1] != 0)
9878 black_point=argument_list[1].real_reference;
9879 if (attribute_flag[2] != 0)
9880 white_point=argument_list[2].real_reference;
9881 if (attribute_flag[3] != 0)
9882 gamma=argument_list[3].real_reference;
9883 if (attribute_flag[4] != 0)
9884 channel=(ChannelType) argument_list[4].integer_reference;
9885 if (attribute_flag[5] != 0)
9886 {
9887 argument_list[0].real_reference=argument_list[5].real_reference;
9888 attribute_flag[0]=attribute_flag[5];
9889 }
9890 channel_mask=SetImageChannelMask(image,channel);
9891 (void) LevelImage(image,black_point,white_point,gamma,exception);
9892 (void) SetImageChannelMask(image,channel_mask);
9893 break;
9894 }
9895 case 74: /* Clip */
9896 {
9897 if (attribute_flag[0] == 0)
9898 argument_list[0].string_reference="#1";
9899 if (attribute_flag[1] == 0)
9900 argument_list[1].integer_reference=MagickTrue;
9901 (void) ClipImagePath(image,argument_list[0].string_reference,
9902 argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9903 exception);
9904 break;
9905 }
9906 case 75: /* AffineTransform */
9907 {
9908 DrawInfo
9909 *draw_info;
9910
9911 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9912 (DrawInfo *) NULL);
9913 if (attribute_flag[0] != 0)
9914 {
9915 AV
9916 *av;
9917
9918 av=(AV *) argument_list[0].array_reference;
9919 if ((av_len(av) != 3) && (av_len(av) != 5))
9920 {
9921 ThrowPerlException(exception,OptionError,
9922 "affine matrix must have 4 or 6 elements",PackageName);
9923 goto PerlException;
9924 }
9925 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9926 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9927 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9928 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9929 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9930 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9931 {
9932 ThrowPerlException(exception,OptionError,
9933 "affine matrix is singular",PackageName);
9934 goto PerlException;
9935 }
9936 if (av_len(av) == 5)
9937 {
9938 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9939 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9940 }
9941 }
9942 for (j=1; j < 6; j++)
9943 {
9944 if (attribute_flag[j] == 0)
9945 continue;
9946 value=argument_list[j].string_reference;
9947 angle=argument_list[j].real_reference;
9948 current=draw_info->affine;
9949 GetAffineMatrix(&affine);
9950 switch (j)
9951 {
9952 case 1:
9953 {
9954 /*
9955 Translate.
9956 */
9957 flags=ParseGeometry(value,&geometry_info);
9958 affine.tx=geometry_info.xi;
9959 affine.ty=geometry_info.psi;
9960 if ((flags & PsiValue) == 0)
9961 affine.ty=affine.tx;
9962 break;
9963 }
9964 case 2:
9965 {
9966 /*
9967 Scale.
9968 */
9969 flags=ParseGeometry(value,&geometry_info);
9970 affine.sx=geometry_info.rho;
9971 affine.sy=geometry_info.sigma;
9972 if ((flags & SigmaValue) == 0)
9973 affine.sy=affine.sx;
9974 break;
9975 }
9976 case 3:
9977 {
9978 /*
9979 Rotate.
9980 */
9981 if (angle == 0.0)
9982 break;
9983 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9984 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9985 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9986 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9987 break;
9988 }
9989 case 4:
9990 {
9991 /*
9992 SkewX.
9993 */
9994 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9995 break;
9996 }
9997 case 5:
9998 {
9999 /*
10000 SkewY.
10001 */
10002 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
10003 break;
10004 }
10005 }
10006 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
10007 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
10008 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
10009 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
10010 draw_info->affine.tx=
10011 current.sx*affine.tx+current.ry*affine.ty+current.tx;
10012 draw_info->affine.ty=
10013 current.rx*affine.tx+current.sy*affine.ty+current.ty;
10014 }
10015 if (attribute_flag[6] != 0)
10016 image->interpolate=(PixelInterpolateMethod)
10017 argument_list[6].integer_reference;
10018 if (attribute_flag[7] != 0)
10019 QueryColorCompliance(argument_list[7].string_reference,
10020 AllCompliance,&image->background_color,exception);
10021 image=AffineTransformImage(image,&draw_info->affine,exception);
10022 draw_info=DestroyDrawInfo(draw_info);
10023 break;
10024 }
10025 case 76: /* Difference */
10026 {
10027 if (attribute_flag[0] == 0)
10028 {
10029 ThrowPerlException(exception,OptionError,
10030 "ReferenceImageRequired",PackageName);
10031 goto PerlException;
10032 }
10033 if (attribute_flag[1] != 0)
10034 image->fuzz=StringToDoubleInterval(
10035 argument_list[1].string_reference,(double) QuantumRange+1.0);
Cristyf2479812015-12-12 12:17:43 -050010036 (void) SetImageColorMetric(image,argument_list[0].image_reference,
cristy4a3ce0a2013-08-03 20:06:59 +000010037 exception);
10038 break;
10039 }
10040 case 77: /* AdaptiveThreshold */
10041 {
10042 if (attribute_flag[0] != 0)
10043 {
10044 flags=ParseGeometry(argument_list[0].string_reference,
10045 &geometry_info);
10046 if ((flags & PercentValue) != 0)
10047 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10048 }
10049 if (attribute_flag[1] != 0)
10050 geometry_info.rho=argument_list[1].integer_reference;
10051 if (attribute_flag[2] != 0)
10052 geometry_info.sigma=argument_list[2].integer_reference;
10053 if (attribute_flag[3] != 0)
10054 geometry_info.xi=argument_list[3].integer_reference;;
10055 image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
10056 (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
10057 break;
10058 }
10059 case 78: /* Resample */
10060 {
10061 size_t
10062 height,
10063 width;
10064
10065 if (attribute_flag[0] != 0)
10066 {
10067 flags=ParseGeometry(argument_list[0].string_reference,
10068 &geometry_info);
10069 if ((flags & SigmaValue) == 0)
10070 geometry_info.sigma=geometry_info.rho;
10071 }
10072 if (attribute_flag[1] != 0)
10073 geometry_info.rho=argument_list[1].real_reference;
10074 if (attribute_flag[2] != 0)
10075 geometry_info.sigma=argument_list[2].real_reference;
10076 if (attribute_flag[3] == 0)
10077 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10078 if (attribute_flag[4] == 0)
10079 SetImageArtifact(image,"filter:support",
10080 argument_list[4].string_reference);
10081 width=(size_t) (geometry_info.rho*image->columns/
10082 (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10083 height=(size_t) (geometry_info.sigma*image->rows/
10084 (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
Cristy8645e042016-02-03 16:35:29 -050010085 image=ResizeImage(image,width,height,(FilterType)
cristy4a3ce0a2013-08-03 20:06:59 +000010086 argument_list[3].integer_reference,exception);
10087 if (image != (Image *) NULL)
10088 {
10089 image->resolution.x=geometry_info.rho;
10090 image->resolution.y=geometry_info.sigma;
10091 }
10092 break;
10093 }
10094 case 79: /* Describe */
10095 {
10096 if (attribute_flag[0] == 0)
10097 argument_list[0].file_reference=(FILE *) NULL;
10098 if (attribute_flag[1] != 0)
10099 (void) SetImageArtifact(image,"identify:features",
10100 argument_list[1].string_reference);
10101 (void) IdentifyImage(image,argument_list[0].file_reference,
10102 MagickTrue,exception);
10103 break;
10104 }
10105 case 80: /* BlackThreshold */
10106 {
10107 if (attribute_flag[0] == 0)
10108 argument_list[0].string_reference="50%";
10109 if (attribute_flag[2] != 0)
10110 channel=(ChannelType) argument_list[2].integer_reference;
10111 channel_mask=SetImageChannelMask(image,channel);
10112 BlackThresholdImage(image,argument_list[0].string_reference,
10113 exception);
10114 (void) SetImageChannelMask(image,channel_mask);
10115 break;
10116 }
10117 case 81: /* WhiteThreshold */
10118 {
10119 if (attribute_flag[0] == 0)
10120 argument_list[0].string_reference="50%";
10121 if (attribute_flag[2] != 0)
10122 channel=(ChannelType) argument_list[2].integer_reference;
10123 channel_mask=SetImageChannelMask(image,channel);
10124 WhiteThresholdImage(image,argument_list[0].string_reference,
10125 exception);
10126 (void) SetImageChannelMask(image,channel_mask);
10127 break;
10128 }
cristy60c73c02014-03-25 12:09:58 +000010129 case 82: /* RotationalBlur */
cristy4a3ce0a2013-08-03 20:06:59 +000010130 {
10131 if (attribute_flag[0] != 0)
10132 {
10133 flags=ParseGeometry(argument_list[0].string_reference,
10134 &geometry_info);
10135 }
10136 if (attribute_flag[1] != 0)
10137 geometry_info.rho=argument_list[1].real_reference;
10138 if (attribute_flag[2] != 0)
10139 channel=(ChannelType) argument_list[2].integer_reference;
10140 channel_mask=SetImageChannelMask(image,channel);
cristy49d4d222014-03-16 00:37:58 +000010141 image=RotationalBlurImage(image,geometry_info.rho,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010142 if (image != (Image *) NULL)
10143 (void) SetImageChannelMask(image,channel_mask);
10144 break;
10145 }
10146 case 83: /* Thumbnail */
10147 {
10148 if (attribute_flag[0] != 0)
10149 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10150 &geometry,exception);
10151 if (attribute_flag[1] != 0)
10152 geometry.width=argument_list[1].integer_reference;
10153 if (attribute_flag[2] != 0)
10154 geometry.height=argument_list[2].integer_reference;
10155 image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10156 break;
10157 }
10158 case 84: /* Strip */
10159 {
10160 (void) StripImage(image,exception);
10161 break;
10162 }
10163 case 85: /* Tint */
10164 {
10165 PixelInfo
10166 tint;
10167
10168 GetPixelInfo(image,&tint);
10169 if (attribute_flag[0] != 0)
10170 (void) QueryColorCompliance(argument_list[0].string_reference,
10171 AllCompliance,&tint,exception);
10172 if (attribute_flag[1] == 0)
10173 argument_list[1].string_reference="100";
10174 image=TintImage(image,argument_list[1].string_reference,&tint,
10175 exception);
10176 break;
10177 }
10178 case 86: /* Channel */
10179 {
10180 if (attribute_flag[0] != 0)
10181 channel=(ChannelType) argument_list[0].integer_reference;
10182 image=SeparateImage(image,channel,exception);
10183 break;
10184 }
10185 case 87: /* Splice */
10186 {
cristy260bd762014-08-15 12:46:34 +000010187 if (attribute_flag[7] != 0)
10188 image->gravity=(GravityType) argument_list[7].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010189 if (attribute_flag[0] != 0)
10190 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10191 &geometry,exception);
10192 if (attribute_flag[1] != 0)
10193 geometry.width=argument_list[1].integer_reference;
10194 if (attribute_flag[2] != 0)
10195 geometry.height=argument_list[2].integer_reference;
10196 if (attribute_flag[3] != 0)
10197 geometry.x=argument_list[3].integer_reference;
10198 if (attribute_flag[4] != 0)
10199 geometry.y=argument_list[4].integer_reference;
10200 if (attribute_flag[5] != 0)
10201 image->fuzz=StringToDoubleInterval(
10202 argument_list[5].string_reference,(double) QuantumRange+1.0);
10203 if (attribute_flag[6] != 0)
10204 (void) QueryColorCompliance(argument_list[6].string_reference,
10205 AllCompliance,&image->background_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010206 image=SpliceImage(image,&geometry,exception);
10207 break;
10208 }
10209 case 88: /* Posterize */
10210 {
10211 if (attribute_flag[0] == 0)
10212 argument_list[0].integer_reference=3;
10213 if (attribute_flag[1] == 0)
10214 argument_list[1].integer_reference=0;
10215 (void) PosterizeImage(image,argument_list[0].integer_reference,
10216 argument_list[1].integer_reference ? RiemersmaDitherMethod :
10217 NoDitherMethod,exception);
10218 break;
10219 }
10220 case 89: /* Shadow */
10221 {
10222 if (attribute_flag[0] != 0)
10223 {
10224 flags=ParseGeometry(argument_list[0].string_reference,
10225 &geometry_info);
10226 if ((flags & SigmaValue) == 0)
10227 geometry_info.sigma=1.0;
10228 if ((flags & XiValue) == 0)
10229 geometry_info.xi=4.0;
10230 if ((flags & PsiValue) == 0)
10231 geometry_info.psi=4.0;
10232 }
10233 if (attribute_flag[1] != 0)
10234 geometry_info.rho=argument_list[1].real_reference;
10235 if (attribute_flag[2] != 0)
10236 geometry_info.sigma=argument_list[2].real_reference;
10237 if (attribute_flag[3] != 0)
10238 geometry_info.xi=argument_list[3].integer_reference;
10239 if (attribute_flag[4] != 0)
10240 geometry_info.psi=argument_list[4].integer_reference;
10241 image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10242 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10243 ceil(geometry_info.psi-0.5),exception);
10244 break;
10245 }
10246 case 90: /* Identify */
10247 {
10248 if (attribute_flag[0] == 0)
10249 argument_list[0].file_reference=(FILE *) NULL;
10250 if (attribute_flag[1] != 0)
10251 (void) SetImageArtifact(image,"identify:features",
10252 argument_list[1].string_reference);
10253 if ((attribute_flag[2] != 0) &&
10254 (argument_list[2].integer_reference != 0))
10255 (void) SetImageArtifact(image,"identify:unique","true");
10256 (void) IdentifyImage(image,argument_list[0].file_reference,
10257 MagickTrue,exception);
10258 break;
10259 }
10260 case 91: /* SepiaTone */
10261 {
10262 if (attribute_flag[0] == 0)
10263 argument_list[0].real_reference=80.0*QuantumRange/100.0;
10264 image=SepiaToneImage(image,argument_list[0].real_reference,
10265 exception);
10266 break;
10267 }
10268 case 92: /* SigmoidalContrast */
10269 {
10270 MagickBooleanType
10271 sharpen;
10272
10273 if (attribute_flag[0] != 0)
10274 {
10275 flags=ParseGeometry(argument_list[0].string_reference,
10276 &geometry_info);
10277 if ((flags & SigmaValue) == 0)
10278 geometry_info.sigma=QuantumRange/2.0;
10279 if ((flags & PercentValue) != 0)
10280 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10281 }
10282 if (attribute_flag[1] != 0)
10283 geometry_info.rho=argument_list[1].real_reference;
10284 if (attribute_flag[2] != 0)
10285 geometry_info.sigma=argument_list[2].real_reference;
10286 if (attribute_flag[3] != 0)
10287 channel=(ChannelType) argument_list[3].integer_reference;
10288 sharpen=MagickTrue;
10289 if (attribute_flag[4] != 0)
10290 sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10291 MagickFalse;
10292 channel_mask=SetImageChannelMask(image,channel);
10293 (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10294 geometry_info.sigma,exception);
10295 (void) SetImageChannelMask(image,channel_mask);
10296 break;
10297 }
10298 case 93: /* Extent */
10299 {
10300 if (attribute_flag[7] != 0)
10301 image->gravity=(GravityType) argument_list[7].integer_reference;
10302 if (attribute_flag[0] != 0)
10303 {
10304 int
10305 flags;
10306
10307 flags=ParseGravityGeometry(image,
10308 argument_list[0].string_reference,&geometry,exception);
10309 (void) flags;
10310 if (geometry.width == 0)
10311 geometry.width=image->columns;
10312 if (geometry.height == 0)
10313 geometry.height=image->rows;
10314 }
10315 if (attribute_flag[1] != 0)
10316 geometry.width=argument_list[1].integer_reference;
10317 if (attribute_flag[2] != 0)
10318 geometry.height=argument_list[2].integer_reference;
10319 if (attribute_flag[3] != 0)
10320 geometry.x=argument_list[3].integer_reference;
10321 if (attribute_flag[4] != 0)
10322 geometry.y=argument_list[4].integer_reference;
10323 if (attribute_flag[5] != 0)
10324 image->fuzz=StringToDoubleInterval(
10325 argument_list[5].string_reference,(double) QuantumRange+1.0);
10326 if (attribute_flag[6] != 0)
10327 (void) QueryColorCompliance(argument_list[6].string_reference,
10328 AllCompliance,&image->background_color,exception);
10329 image=ExtentImage(image,&geometry,exception);
10330 break;
10331 }
10332 case 94: /* Vignette */
10333 {
10334 if (attribute_flag[0] != 0)
10335 {
10336 flags=ParseGeometry(argument_list[0].string_reference,
10337 &geometry_info);
10338 if ((flags & SigmaValue) == 0)
10339 geometry_info.sigma=1.0;
10340 if ((flags & XiValue) == 0)
10341 geometry_info.xi=0.1*image->columns;
10342 if ((flags & PsiValue) == 0)
10343 geometry_info.psi=0.1*image->rows;
10344 }
10345 if (attribute_flag[1] != 0)
10346 geometry_info.rho=argument_list[1].real_reference;
10347 if (attribute_flag[2] != 0)
10348 geometry_info.sigma=argument_list[2].real_reference;
10349 if (attribute_flag[3] != 0)
10350 geometry_info.xi=argument_list[3].integer_reference;
10351 if (attribute_flag[4] != 0)
10352 geometry_info.psi=argument_list[4].integer_reference;
10353 if (attribute_flag[5] != 0)
10354 (void) QueryColorCompliance(argument_list[5].string_reference,
10355 AllCompliance,&image->background_color,exception);
10356 image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10357 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10358 ceil(geometry_info.psi-0.5),exception);
10359 break;
10360 }
10361 case 95: /* ContrastStretch */
10362 {
10363 double
10364 black_point,
10365 white_point;
10366
10367 black_point=0.0;
10368 white_point=(double) image->columns*image->rows;
10369 if (attribute_flag[0] != 0)
10370 {
10371 flags=ParseGeometry(argument_list[0].string_reference,
10372 &geometry_info);
10373 black_point=geometry_info.rho;
10374 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10375 black_point;
10376 if ((flags & PercentValue) != 0)
10377 {
10378 black_point*=(double) image->columns*image->rows/100.0;
10379 white_point*=(double) image->columns*image->rows/100.0;
10380 }
10381 white_point=(double) image->columns*image->rows-
10382 white_point;
10383 }
10384 if (attribute_flag[1] != 0)
10385 black_point=argument_list[1].real_reference;
10386 if (attribute_flag[2] != 0)
10387 white_point=argument_list[2].real_reference;
10388 if (attribute_flag[4] != 0)
10389 channel=(ChannelType) argument_list[4].integer_reference;
10390 channel_mask=SetImageChannelMask(image,channel);
10391 (void) ContrastStretchImage(image,black_point,white_point,exception);
10392 (void) SetImageChannelMask(image,channel_mask);
10393 break;
10394 }
10395 case 96: /* Sans0 */
10396 {
10397 break;
10398 }
10399 case 97: /* Sans1 */
10400 {
10401 break;
10402 }
10403 case 98: /* AdaptiveSharpen */
10404 {
10405 if (attribute_flag[0] != 0)
10406 {
10407 flags=ParseGeometry(argument_list[0].string_reference,
10408 &geometry_info);
10409 if ((flags & SigmaValue) == 0)
10410 geometry_info.sigma=1.0;
10411 if ((flags & XiValue) == 0)
10412 geometry_info.xi=0.0;
10413 }
10414 if (attribute_flag[1] != 0)
10415 geometry_info.rho=argument_list[1].real_reference;
10416 if (attribute_flag[2] != 0)
10417 geometry_info.sigma=argument_list[2].real_reference;
10418 if (attribute_flag[3] != 0)
10419 geometry_info.xi=argument_list[3].real_reference;
10420 if (attribute_flag[4] != 0)
10421 channel=(ChannelType) argument_list[4].integer_reference;
10422 channel_mask=SetImageChannelMask(image,channel);
10423 image=AdaptiveSharpenImage(image,geometry_info.rho,
10424 geometry_info.sigma,exception);
10425 if (image != (Image *) NULL)
10426 (void) SetImageChannelMask(image,channel_mask);
10427 break;
10428 }
10429 case 99: /* Transpose */
10430 {
10431 image=TransposeImage(image,exception);
10432 break;
10433 }
10434 case 100: /* Tranverse */
10435 {
10436 image=TransverseImage(image,exception);
10437 break;
10438 }
10439 case 101: /* AutoOrient */
10440 {
10441 image=AutoOrientImage(image,image->orientation,exception);
10442 break;
10443 }
10444 case 102: /* AdaptiveBlur */
10445 {
10446 if (attribute_flag[0] != 0)
10447 {
10448 flags=ParseGeometry(argument_list[0].string_reference,
10449 &geometry_info);
10450 if ((flags & SigmaValue) == 0)
10451 geometry_info.sigma=1.0;
10452 if ((flags & XiValue) == 0)
10453 geometry_info.xi=0.0;
10454 }
10455 if (attribute_flag[1] != 0)
10456 geometry_info.rho=argument_list[1].real_reference;
10457 if (attribute_flag[2] != 0)
10458 geometry_info.sigma=argument_list[2].real_reference;
10459 if (attribute_flag[3] != 0)
10460 channel=(ChannelType) argument_list[3].integer_reference;
10461 channel_mask=SetImageChannelMask(image,channel);
10462 image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10463 exception);
10464 if (image != (Image *) NULL)
10465 (void) SetImageChannelMask(image,channel_mask);
10466 break;
10467 }
10468 case 103: /* Sketch */
10469 {
10470 if (attribute_flag[0] != 0)
10471 {
10472 flags=ParseGeometry(argument_list[0].string_reference,
10473 &geometry_info);
10474 if ((flags & SigmaValue) == 0)
10475 geometry_info.sigma=1.0;
10476 if ((flags & XiValue) == 0)
10477 geometry_info.xi=1.0;
10478 }
10479 if (attribute_flag[1] != 0)
10480 geometry_info.rho=argument_list[1].real_reference;
10481 if (attribute_flag[2] != 0)
10482 geometry_info.sigma=argument_list[2].real_reference;
10483 if (attribute_flag[3] != 0)
10484 geometry_info.xi=argument_list[3].real_reference;
10485 image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10486 geometry_info.xi,exception);
10487 break;
10488 }
10489 case 104: /* UniqueColors */
10490 {
10491 image=UniqueImageColors(image,exception);
10492 break;
10493 }
10494 case 105: /* AdaptiveResize */
10495 {
10496 if (attribute_flag[0] != 0)
10497 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10498 &geometry,exception);
10499 if (attribute_flag[1] != 0)
10500 geometry.width=argument_list[1].integer_reference;
10501 if (attribute_flag[2] != 0)
10502 geometry.height=argument_list[2].integer_reference;
10503 if (attribute_flag[3] != 0)
Cristy8645e042016-02-03 16:35:29 -050010504 image->filter=(FilterType) argument_list[4].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010505 if (attribute_flag[4] != 0)
10506 SetImageArtifact(image,"filter:support",
10507 argument_list[4].string_reference);
10508 image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10509 exception);
10510 break;
10511 }
10512 case 106: /* ClipMask */
10513 {
10514 Image
10515 *mask_image;
10516
10517 if (attribute_flag[0] == 0)
10518 {
10519 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10520 PackageName);
10521 goto PerlException;
10522 }
10523 mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10524 exception);
cristy1f7ffb72015-07-29 11:07:03 +000010525 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010526 mask_image=DestroyImage(mask_image);
10527 break;
10528 }
10529 case 107: /* LinearStretch */
10530 {
10531 double
10532 black_point,
10533 white_point;
10534
10535 black_point=0.0;
10536 white_point=(double) image->columns*image->rows;
10537 if (attribute_flag[0] != 0)
10538 {
10539 flags=ParseGeometry(argument_list[0].string_reference,
10540 &geometry_info);
10541 if ((flags & SigmaValue) != 0)
10542 white_point=geometry_info.sigma;
10543 if ((flags & PercentValue) != 0)
10544 {
10545 black_point*=(double) image->columns*image->rows/100.0;
10546 white_point*=(double) image->columns*image->rows/100.0;
10547 }
10548 if ((flags & SigmaValue) == 0)
10549 white_point=(double) image->columns*image->rows-black_point;
10550 }
10551 if (attribute_flag[1] != 0)
10552 black_point=argument_list[1].real_reference;
10553 if (attribute_flag[2] != 0)
10554 white_point=argument_list[2].real_reference;
10555 (void) LinearStretchImage(image,black_point,white_point,exception);
10556 break;
10557 }
10558 case 108: /* ColorMatrix */
10559 {
10560 AV
10561 *av;
10562
10563 double
10564 *color_matrix;
10565
10566 KernelInfo
10567 *kernel_info;
10568
10569 size_t
10570 order;
10571
10572 if (attribute_flag[0] == 0)
10573 break;
10574 av=(AV *) argument_list[0].array_reference;
10575 order=(size_t) sqrt(av_len(av)+1);
10576 color_matrix=(double *) AcquireQuantumMemory(order,order*
10577 sizeof(*color_matrix));
10578 if (color_matrix == (double *) NULL)
10579 {
10580 ThrowPerlException(exception,ResourceLimitFatalError,
10581 "MemoryAllocationFailed",PackageName);
10582 goto PerlException;
10583 }
10584 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10585 color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10586 for ( ; j < (ssize_t) (order*order); j++)
10587 color_matrix[j]=0.0;
cristy2c57b742014-10-31 00:40:34 +000010588 kernel_info=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010589 if (kernel_info == (KernelInfo *) NULL)
10590 break;
10591 kernel_info->width=order;
10592 kernel_info->height=order;
10593 kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10594 order*sizeof(*kernel_info->values));
10595 if (kernel_info->values != (MagickRealType *) NULL)
10596 {
10597 for (i=0; i < (ssize_t) (order*order); i++)
10598 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10599 image=ColorMatrixImage(image,kernel_info,exception);
10600 }
10601 kernel_info=DestroyKernelInfo(kernel_info);
10602 color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10603 break;
10604 }
10605 case 109: /* Mask */
10606 {
10607 Image
10608 *mask_image;
10609
10610 if (attribute_flag[0] == 0)
10611 {
10612 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10613 PackageName);
10614 goto PerlException;
10615 }
10616 mask_image=CloneImage(argument_list[0].image_reference,0,0,
10617 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +000010618 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010619 mask_image=DestroyImage(mask_image);
10620 break;
10621 }
10622 case 110: /* Polaroid */
10623 {
10624 char
10625 *caption;
10626
10627 DrawInfo
10628 *draw_info;
10629
10630 double
10631 angle;
10632
10633 PixelInterpolateMethod
10634 method;
10635
10636 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10637 (DrawInfo *) NULL);
10638 caption=(char *) NULL;
10639 if (attribute_flag[0] != 0)
10640 caption=InterpretImageProperties(info ? info->image_info :
10641 (ImageInfo *) NULL,image,argument_list[0].string_reference,
10642 exception);
10643 angle=0.0;
10644 if (attribute_flag[1] != 0)
10645 angle=argument_list[1].real_reference;
10646 if (attribute_flag[2] != 0)
10647 (void) CloneString(&draw_info->font,
10648 argument_list[2].string_reference);
10649 if (attribute_flag[3] != 0)
10650 (void) QueryColorCompliance(argument_list[3].string_reference,
10651 AllCompliance,&draw_info->stroke,exception);
10652 if (attribute_flag[4] != 0)
10653 (void) QueryColorCompliance(argument_list[4].string_reference,
10654 AllCompliance,&draw_info->fill,exception);
10655 if (attribute_flag[5] != 0)
10656 draw_info->stroke_width=argument_list[5].real_reference;
10657 if (attribute_flag[6] != 0)
10658 draw_info->pointsize=argument_list[6].real_reference;
10659 if (attribute_flag[7] != 0)
10660 draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10661 if (attribute_flag[8] != 0)
10662 (void) QueryColorCompliance(argument_list[8].string_reference,
10663 AllCompliance,&image->background_color,exception);
10664 method=UndefinedInterpolatePixel;
10665 if (attribute_flag[9] != 0)
10666 method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10667 image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10668 draw_info=DestroyDrawInfo(draw_info);
10669 if (caption != (char *) NULL)
10670 caption=DestroyString(caption);
10671 break;
10672 }
10673 case 111: /* FloodfillPaint */
10674 {
10675 DrawInfo
10676 *draw_info;
10677
10678 MagickBooleanType
10679 invert;
10680
10681 PixelInfo
10682 target;
10683
10684 draw_info=CloneDrawInfo(info ? info->image_info :
10685 (ImageInfo *) NULL,(DrawInfo *) NULL);
10686 if (attribute_flag[0] != 0)
10687 flags=ParsePageGeometry(image,argument_list[0].string_reference,
10688 &geometry,exception);
10689 if (attribute_flag[1] != 0)
10690 geometry.x=argument_list[1].integer_reference;
10691 if (attribute_flag[2] != 0)
10692 geometry.y=argument_list[2].integer_reference;
10693 if (attribute_flag[3] != 0)
10694 (void) QueryColorCompliance(argument_list[3].string_reference,
10695 AllCompliance,&draw_info->fill,exception);
10696 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10697 geometry.x,geometry.y,&target,exception);
10698 if (attribute_flag[4] != 0)
10699 QueryColorCompliance(argument_list[4].string_reference,
10700 AllCompliance,&target,exception);
10701 if (attribute_flag[5] != 0)
10702 image->fuzz=StringToDoubleInterval(
10703 argument_list[5].string_reference,(double) QuantumRange+1.0);
10704 if (attribute_flag[6] != 0)
10705 channel=(ChannelType) argument_list[6].integer_reference;
10706 invert=MagickFalse;
10707 if (attribute_flag[7] != 0)
10708 invert=(MagickBooleanType) argument_list[7].integer_reference;
10709 channel_mask=SetImageChannelMask(image,channel);
10710 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10711 geometry.y,invert,exception);
10712 (void) SetImageChannelMask(image,channel_mask);
10713 draw_info=DestroyDrawInfo(draw_info);
10714 break;
10715 }
10716 case 112: /* Distort */
10717 {
10718 AV
10719 *av;
10720
10721 double
10722 *coordinates;
10723
Cristy8645e042016-02-03 16:35:29 -050010724 DistortMethod
cristy4a3ce0a2013-08-03 20:06:59 +000010725 method;
10726
10727 size_t
10728 number_coordinates;
10729
10730 VirtualPixelMethod
10731 virtual_pixel;
10732
10733 if (attribute_flag[0] == 0)
10734 break;
10735 method=UndefinedDistortion;
10736 if (attribute_flag[1] != 0)
Cristy8645e042016-02-03 16:35:29 -050010737 method=(DistortMethod) argument_list[1].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010738 av=(AV *) argument_list[0].array_reference;
10739 number_coordinates=(size_t) av_len(av)+1;
10740 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10741 sizeof(*coordinates));
10742 if (coordinates == (double *) NULL)
10743 {
10744 ThrowPerlException(exception,ResourceLimitFatalError,
10745 "MemoryAllocationFailed",PackageName);
10746 goto PerlException;
10747 }
10748 for (j=0; j < (ssize_t) number_coordinates; j++)
10749 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10750 virtual_pixel=UndefinedVirtualPixelMethod;
10751 if (attribute_flag[2] != 0)
10752 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10753 argument_list[2].integer_reference,exception);
10754 image=DistortImage(image,method,number_coordinates,coordinates,
10755 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10756 exception);
10757 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10758 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10759 exception);
10760 coordinates=(double *) RelinquishMagickMemory(coordinates);
10761 break;
10762 }
10763 case 113: /* Clut */
10764 {
10765 PixelInterpolateMethod
10766 method;
10767
10768 if (attribute_flag[0] == 0)
10769 {
10770 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10771 PackageName);
10772 goto PerlException;
10773 }
10774 method=UndefinedInterpolatePixel;
10775 if (attribute_flag[1] != 0)
10776 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10777 if (attribute_flag[2] != 0)
10778 channel=(ChannelType) argument_list[2].integer_reference;
10779 channel_mask=SetImageChannelMask(image,channel);
10780 (void) ClutImage(image,argument_list[0].image_reference,method,
10781 exception);
10782 (void) SetImageChannelMask(image,channel_mask);
10783 break;
10784 }
10785 case 114: /* LiquidRescale */
10786 {
10787 if (attribute_flag[0] != 0)
10788 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10789 &geometry,exception);
10790 if (attribute_flag[1] != 0)
10791 geometry.width=argument_list[1].integer_reference;
10792 if (attribute_flag[2] != 0)
10793 geometry.height=argument_list[2].integer_reference;
10794 if (attribute_flag[3] == 0)
10795 argument_list[3].real_reference=1.0;
10796 if (attribute_flag[4] == 0)
10797 argument_list[4].real_reference=0.0;
10798 image=LiquidRescaleImage(image,geometry.width,geometry.height,
10799 argument_list[3].real_reference,argument_list[4].real_reference,
10800 exception);
10801 break;
10802 }
10803 case 115: /* EncipherImage */
10804 {
10805 (void) EncipherImage(image,argument_list[0].string_reference,
10806 exception);
10807 break;
10808 }
10809 case 116: /* DecipherImage */
10810 {
10811 (void) DecipherImage(image,argument_list[0].string_reference,
10812 exception);
10813 break;
10814 }
10815 case 117: /* Deskew */
10816 {
10817 geometry_info.rho=QuantumRange/2.0;
10818 if (attribute_flag[0] != 0)
10819 flags=ParseGeometry(argument_list[0].string_reference,
10820 &geometry_info);
10821 if (attribute_flag[1] != 0)
10822 geometry_info.rho=StringToDoubleInterval(
10823 argument_list[1].string_reference,(double) QuantumRange+1.0);
10824 image=DeskewImage(image,geometry_info.rho,exception);
10825 break;
10826 }
10827 case 118: /* Remap */
10828 {
10829 QuantizeInfo
10830 *quantize_info;
10831
10832 if (attribute_flag[0] == 0)
10833 {
10834 ThrowPerlException(exception,OptionError,"RemapImageRequired",
10835 PackageName);
10836 goto PerlException;
10837 }
10838 quantize_info=AcquireQuantizeInfo(info->image_info);
10839 if (attribute_flag[1] != 0)
10840 quantize_info->dither_method=(DitherMethod)
10841 argument_list[1].integer_reference;
10842 (void) RemapImages(quantize_info,image,
10843 argument_list[0].image_reference,exception);
10844 quantize_info=DestroyQuantizeInfo(quantize_info);
10845 break;
10846 }
10847 case 119: /* SparseColor */
10848 {
10849 AV
10850 *av;
10851
10852 double
10853 *coordinates;
10854
10855 SparseColorMethod
10856 method;
10857
10858 size_t
10859 number_coordinates;
10860
10861 VirtualPixelMethod
10862 virtual_pixel;
10863
10864 if (attribute_flag[0] == 0)
10865 break;
10866 method=UndefinedColorInterpolate;
10867 if (attribute_flag[1] != 0)
10868 method=(SparseColorMethod) argument_list[1].integer_reference;
10869 av=(AV *) argument_list[0].array_reference;
10870 number_coordinates=(size_t) av_len(av)+1;
10871 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10872 sizeof(*coordinates));
10873 if (coordinates == (double *) NULL)
10874 {
10875 ThrowPerlException(exception,ResourceLimitFatalError,
10876 "MemoryAllocationFailed",PackageName);
10877 goto PerlException;
10878 }
10879 for (j=0; j < (ssize_t) number_coordinates; j++)
10880 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10881 virtual_pixel=UndefinedVirtualPixelMethod;
10882 if (attribute_flag[2] != 0)
10883 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10884 argument_list[2].integer_reference,exception);
10885 if (attribute_flag[3] != 0)
10886 channel=(ChannelType) argument_list[3].integer_reference;
10887 channel_mask=SetImageChannelMask(image,channel);
10888 image=SparseColorImage(image,method,number_coordinates,coordinates,
10889 exception);
10890 if (image != (Image *) NULL)
10891 (void) SetImageChannelMask(image,channel_mask);
10892 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10893 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10894 exception);
10895 coordinates=(double *) RelinquishMagickMemory(coordinates);
10896 break;
10897 }
10898 case 120: /* Function */
10899 {
10900 AV
10901 *av;
10902
10903 double
10904 *parameters;
10905
10906 MagickFunction
10907 function;
10908
10909 size_t
10910 number_parameters;
10911
10912 VirtualPixelMethod
10913 virtual_pixel;
10914
10915 if (attribute_flag[0] == 0)
10916 break;
10917 function=UndefinedFunction;
10918 if (attribute_flag[1] != 0)
10919 function=(MagickFunction) argument_list[1].integer_reference;
10920 av=(AV *) argument_list[0].array_reference;
10921 number_parameters=(size_t) av_len(av)+1;
10922 parameters=(double *) AcquireQuantumMemory(number_parameters,
10923 sizeof(*parameters));
10924 if (parameters == (double *) NULL)
10925 {
10926 ThrowPerlException(exception,ResourceLimitFatalError,
10927 "MemoryAllocationFailed",PackageName);
10928 goto PerlException;
10929 }
10930 for (j=0; j < (ssize_t) number_parameters; j++)
10931 parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10932 virtual_pixel=UndefinedVirtualPixelMethod;
10933 if (attribute_flag[2] != 0)
10934 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10935 argument_list[2].integer_reference,exception);
10936 (void) FunctionImage(image,function,number_parameters,parameters,
10937 exception);
10938 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10939 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10940 exception);
10941 parameters=(double *) RelinquishMagickMemory(parameters);
10942 break;
10943 }
10944 case 121: /* SelectiveBlur */
10945 {
10946 if (attribute_flag[0] != 0)
10947 {
10948 flags=ParseGeometry(argument_list[0].string_reference,
10949 &geometry_info);
10950 if ((flags & SigmaValue) == 0)
10951 geometry_info.sigma=1.0;
10952 if ((flags & PercentValue) != 0)
10953 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10954 }
10955 if (attribute_flag[1] != 0)
10956 geometry_info.rho=argument_list[1].real_reference;
10957 if (attribute_flag[2] != 0)
10958 geometry_info.sigma=argument_list[2].real_reference;
10959 if (attribute_flag[3] != 0)
10960 geometry_info.xi=argument_list[3].integer_reference;;
10961 if (attribute_flag[5] != 0)
10962 channel=(ChannelType) argument_list[5].integer_reference;
10963 channel_mask=SetImageChannelMask(image,channel);
10964 image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10965 geometry_info.xi,exception);
10966 if (image != (Image *) NULL)
10967 (void) SetImageChannelMask(image,channel_mask);
10968 break;
10969 }
10970 case 122: /* HaldClut */
10971 {
10972 if (attribute_flag[0] == 0)
10973 {
10974 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10975 PackageName);
10976 goto PerlException;
10977 }
10978 if (attribute_flag[1] != 0)
10979 channel=(ChannelType) argument_list[1].integer_reference;
10980 channel_mask=SetImageChannelMask(image,channel);
10981 (void) HaldClutImage(image,argument_list[0].image_reference,
10982 exception);
10983 (void) SetImageChannelMask(image,channel_mask);
10984 break;
10985 }
10986 case 123: /* BlueShift */
10987 {
10988 if (attribute_flag[0] != 0)
10989 (void) ParseGeometry(argument_list[0].string_reference,
10990 &geometry_info);
10991 image=BlueShiftImage(image,geometry_info.rho,exception);
10992 break;
10993 }
10994 case 124: /* ForwardFourierTransformImage */
10995 {
10996 image=ForwardFourierTransformImage(image,
10997 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10998 exception);
10999 break;
11000 }
11001 case 125: /* InverseFourierTransformImage */
11002 {
11003 image=InverseFourierTransformImage(image,image->next,
11004 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11005 exception);
11006 break;
11007 }
11008 case 126: /* ColorDecisionList */
11009 {
11010 if (attribute_flag[0] == 0)
11011 argument_list[0].string_reference=(char *) NULL;
11012 (void) ColorDecisionListImage(image,
11013 argument_list[0].string_reference,exception);
11014 break;
11015 }
11016 case 127: /* AutoGamma */
11017 {
11018 if (attribute_flag[0] != 0)
11019 channel=(ChannelType) argument_list[0].integer_reference;
11020 channel_mask=SetImageChannelMask(image,channel);
11021 (void) AutoGammaImage(image,exception);
11022 (void) SetImageChannelMask(image,channel_mask);
11023 break;
11024 }
11025 case 128: /* AutoLevel */
11026 {
11027 if (attribute_flag[0] != 0)
11028 channel=(ChannelType) argument_list[0].integer_reference;
11029 channel_mask=SetImageChannelMask(image,channel);
11030 (void) AutoLevelImage(image,exception);
11031 (void) SetImageChannelMask(image,channel_mask);
11032 break;
11033 }
11034 case 129: /* LevelColors */
11035 {
11036 PixelInfo
11037 black_point,
11038 white_point;
11039
11040 (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
11041 exception);
11042 (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
11043 exception);
11044 if (attribute_flag[1] != 0)
11045 (void) QueryColorCompliance(
11046 argument_list[1].string_reference,AllCompliance,&black_point,
11047 exception);
11048 if (attribute_flag[2] != 0)
11049 (void) QueryColorCompliance(
11050 argument_list[2].string_reference,AllCompliance,&white_point,
11051 exception);
11052 if (attribute_flag[3] != 0)
11053 channel=(ChannelType) argument_list[3].integer_reference;
11054 channel_mask=SetImageChannelMask(image,channel);
11055 (void) LevelImageColors(image,&black_point,&white_point,
11056 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11057 exception);
11058 (void) SetImageChannelMask(image,channel_mask);
11059 break;
11060 }
11061 case 130: /* Clamp */
11062 {
11063 if (attribute_flag[0] != 0)
11064 channel=(ChannelType) argument_list[0].integer_reference;
11065 channel_mask=SetImageChannelMask(image,channel);
11066 (void) ClampImage(image,exception);
11067 (void) SetImageChannelMask(image,channel_mask);
11068 break;
11069 }
11070 case 131: /* BrightnessContrast */
11071 {
11072 double
11073 brightness,
11074 contrast;
11075
11076 brightness=0.0;
11077 contrast=0.0;
11078 if (attribute_flag[0] != 0)
11079 {
11080 flags=ParseGeometry(argument_list[0].string_reference,
11081 &geometry_info);
11082 brightness=geometry_info.rho;
11083 if ((flags & SigmaValue) == 0)
11084 contrast=geometry_info.sigma;
11085 }
11086 if (attribute_flag[1] != 0)
11087 brightness=argument_list[1].real_reference;
11088 if (attribute_flag[2] != 0)
11089 contrast=argument_list[2].real_reference;
11090 if (attribute_flag[4] != 0)
11091 channel=(ChannelType) argument_list[4].integer_reference;
11092 channel_mask=SetImageChannelMask(image,channel);
11093 (void) BrightnessContrastImage(image,brightness,contrast,exception);
11094 (void) SetImageChannelMask(image,channel_mask);
11095 break;
11096 }
11097 case 132: /* Morphology */
11098 {
11099 KernelInfo
11100 *kernel;
11101
11102 MorphologyMethod
11103 method;
11104
11105 ssize_t
11106 iterations;
11107
11108 if (attribute_flag[0] == 0)
11109 break;
cristy2c57b742014-10-31 00:40:34 +000011110 kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011111 if (kernel == (KernelInfo *) NULL)
11112 break;
11113 if (attribute_flag[1] != 0)
11114 channel=(ChannelType) argument_list[1].integer_reference;
11115 method=UndefinedMorphology;
11116 if (attribute_flag[2] != 0)
11117 method=argument_list[2].integer_reference;
11118 iterations=1;
11119 if (attribute_flag[3] != 0)
11120 iterations=argument_list[3].integer_reference;
11121 channel_mask=SetImageChannelMask(image,channel);
11122 image=MorphologyImage(image,method,iterations,kernel,exception);
11123 if (image != (Image *) NULL)
11124 (void) SetImageChannelMask(image,channel_mask);
11125 kernel=DestroyKernelInfo(kernel);
11126 break;
11127 }
11128 case 133: /* Mode */
11129 {
11130 if (attribute_flag[0] != 0)
11131 {
11132 flags=ParseGeometry(argument_list[0].string_reference,
11133 &geometry_info);
11134 if ((flags & SigmaValue) == 0)
11135 geometry_info.sigma=1.0;
11136 }
11137 if (attribute_flag[1] != 0)
11138 geometry_info.rho=argument_list[1].real_reference;
11139 if (attribute_flag[2] != 0)
11140 geometry_info.sigma=argument_list[2].real_reference;
11141 if (attribute_flag[3] != 0)
11142 channel=(ChannelType) argument_list[3].integer_reference;
11143 channel_mask=SetImageChannelMask(image,channel);
11144 image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11145 (size_t) geometry_info.sigma,exception);
11146 if (image != (Image *) NULL)
11147 (void) SetImageChannelMask(image,channel_mask);
11148 break;
11149 }
11150 case 134: /* Statistic */
11151 {
11152 StatisticType
11153 statistic;
11154
11155 statistic=UndefinedStatistic;
11156 if (attribute_flag[0] != 0)
11157 {
11158 flags=ParseGeometry(argument_list[0].string_reference,
11159 &geometry_info);
11160 if ((flags & SigmaValue) == 0)
11161 geometry_info.sigma=1.0;
11162 }
11163 if (attribute_flag[1] != 0)
11164 geometry_info.rho=argument_list[1].real_reference;
11165 if (attribute_flag[2] != 0)
11166 geometry_info.sigma=argument_list[2].real_reference;
11167 if (attribute_flag[3] != 0)
11168 channel=(ChannelType) argument_list[3].integer_reference;
11169 if (attribute_flag[4] != 0)
11170 statistic=(StatisticType) argument_list[4].integer_reference;
11171 channel_mask=SetImageChannelMask(image,channel);
11172 image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11173 (size_t) geometry_info.sigma,exception);
11174 if (image != (Image *) NULL)
11175 (void) SetImageChannelMask(image,channel_mask);
11176 break;
11177 }
11178 case 135: /* Perceptible */
11179 {
11180 double
11181 epsilon;
11182
11183 epsilon=MagickEpsilon;
11184 if (attribute_flag[0] != 0)
11185 epsilon=argument_list[0].real_reference;
11186 if (attribute_flag[1] != 0)
11187 channel=(ChannelType) argument_list[1].integer_reference;
11188 channel_mask=SetImageChannelMask(image,channel);
11189 (void) PerceptibleImage(image,epsilon,exception);
11190 (void) SetImageChannelMask(image,channel_mask);
11191 break;
11192 }
11193 case 136: /* Poly */
11194 {
11195 AV
11196 *av;
11197
11198 double
11199 *terms;
11200
11201 size_t
11202 number_terms;
11203
11204 if (attribute_flag[0] == 0)
11205 break;
11206 if (attribute_flag[1] != 0)
11207 channel=(ChannelType) argument_list[1].integer_reference;
11208 av=(AV *) argument_list[0].array_reference;
11209 number_terms=(size_t) av_len(av);
11210 terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11211 if (terms == (double *) NULL)
11212 {
11213 ThrowPerlException(exception,ResourceLimitFatalError,
11214 "MemoryAllocationFailed",PackageName);
11215 goto PerlException;
11216 }
11217 for (j=0; j < av_len(av); j++)
11218 terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11219 image=PolynomialImage(image,number_terms >> 1,terms,exception);
11220 terms=(double *) RelinquishMagickMemory(terms);
11221 break;
11222 }
11223 case 137: /* Grayscale */
11224 {
11225 PixelIntensityMethod
11226 method;
11227
11228 method=UndefinedPixelIntensityMethod;
11229 if (attribute_flag[0] != 0)
11230 method=(PixelIntensityMethod) argument_list[0].integer_reference;
11231 (void) GrayscaleImage(image,method,exception);
11232 break;
11233 }
cristy4ceadb82014-03-29 15:30:43 +000011234 case 138: /* Canny */
11235 {
11236 if (attribute_flag[0] != 0)
11237 {
11238 flags=ParseGeometry(argument_list[0].string_reference,
11239 &geometry_info);
11240 if ((flags & SigmaValue) == 0)
11241 geometry_info.sigma=1.0;
11242 if ((flags & XiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011243 geometry_info.xi=0.10;
cristy4ceadb82014-03-29 15:30:43 +000011244 if ((flags & PsiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011245 geometry_info.psi=0.30;
cristy41814f22014-04-09 20:53:11 +000011246 if ((flags & PercentValue) != 0)
11247 {
11248 geometry_info.xi/=100.0;
11249 geometry_info.psi/=100.0;
11250 }
cristy4ceadb82014-03-29 15:30:43 +000011251 }
11252 if (attribute_flag[1] != 0)
11253 geometry_info.rho=argument_list[1].real_reference;
11254 if (attribute_flag[2] != 0)
11255 geometry_info.sigma=argument_list[2].real_reference;
11256 if (attribute_flag[3] != 0)
11257 geometry_info.xi=argument_list[3].real_reference;
11258 if (attribute_flag[4] != 0)
11259 geometry_info.psi=argument_list[4].real_reference;
11260 if (attribute_flag[5] != 0)
11261 channel=(ChannelType) argument_list[5].integer_reference;
11262 channel_mask=SetImageChannelMask(image,channel);
11263 image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11264 geometry_info.xi,geometry_info.psi,exception);
11265 if (image != (Image *) NULL)
11266 (void) SetImageChannelMask(image,channel_mask);
11267 break;
11268 }
cristy2fc10e52014-04-26 14:13:53 +000011269 case 139: /* HoughLine */
cristy4e215022014-04-19 18:02:35 +000011270 {
11271 if (attribute_flag[0] != 0)
11272 {
11273 flags=ParseGeometry(argument_list[0].string_reference,
11274 &geometry_info);
11275 if ((flags & SigmaValue) == 0)
11276 geometry_info.sigma=geometry_info.rho;
cristy20f90422014-04-27 13:34:21 +000011277 if ((flags & XiValue) == 0)
11278 geometry_info.xi=40;
cristy4e215022014-04-19 18:02:35 +000011279 }
11280 if (attribute_flag[1] != 0)
11281 geometry_info.rho=(double) argument_list[1].integer_reference;
11282 if (attribute_flag[2] != 0)
11283 geometry_info.sigma=(double) argument_list[2].integer_reference;
11284 if (attribute_flag[3] != 0)
11285 geometry_info.xi=(double) argument_list[3].integer_reference;
cristy2fc10e52014-04-26 14:13:53 +000011286 image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11287 geometry_info.sigma,(size_t) geometry_info.xi,exception);
11288 break;
11289 }
11290 case 140: /* MeanShift */
11291 {
11292 if (attribute_flag[0] != 0)
11293 {
11294 flags=ParseGeometry(argument_list[0].string_reference,
11295 &geometry_info);
11296 if ((flags & SigmaValue) == 0)
11297 geometry_info.sigma=geometry_info.rho;
cristy2fc10e52014-04-26 14:13:53 +000011298 if ((flags & XiValue) == 0)
cristy1309fc32014-04-26 18:48:37 +000011299 geometry_info.xi=0.10*QuantumRange;
11300 if ((flags & PercentValue) != 0)
11301 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
cristy2fc10e52014-04-26 14:13:53 +000011302 }
11303 if (attribute_flag[1] != 0)
11304 geometry_info.rho=(double) argument_list[1].integer_reference;
11305 if (attribute_flag[2] != 0)
11306 geometry_info.sigma=(double) argument_list[2].integer_reference;
11307 if (attribute_flag[3] != 0)
11308 geometry_info.xi=(double) argument_list[3].integer_reference;
11309 image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
cristy1309fc32014-04-26 18:48:37 +000011310 geometry_info.sigma,geometry_info.xi,exception);
cristy4e215022014-04-19 18:02:35 +000011311 break;
11312 }
cristy3b207f82014-09-27 14:21:20 +000011313 case 141: /* Kuwahara */
11314 {
11315 if (attribute_flag[0] != 0)
11316 {
11317 flags=ParseGeometry(argument_list[0].string_reference,
11318 &geometry_info);
11319 if ((flags & SigmaValue) == 0)
cristy3a9903c2014-10-04 01:14:20 +000011320 geometry_info.sigma=geometry_info.rho-0.5;
cristy3b207f82014-09-27 14:21:20 +000011321 }
11322 if (attribute_flag[1] != 0)
11323 geometry_info.rho=argument_list[1].real_reference;
11324 if (attribute_flag[2] != 0)
11325 geometry_info.sigma=argument_list[2].real_reference;
11326 if (attribute_flag[3] != 0)
11327 channel=(ChannelType) argument_list[3].integer_reference;
11328 channel_mask=SetImageChannelMask(image,channel);
11329 image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11330 exception);
11331 if (image != (Image *) NULL)
11332 (void) SetImageChannelMask(image,channel_mask);
11333 break;
11334 }
Cristy0f5df812017-07-04 18:30:05 -040011335 case 142: /* ConnectedComponents */
cristy6e0b3bc2014-10-19 17:51:42 +000011336 {
11337 size_t
11338 connectivity;
11339
11340 connectivity=4;
11341 if (attribute_flag[0] != 0)
11342 connectivity=argument_list[0].integer_reference;
Cristy2ca0e9a2016-01-01 08:36:14 -050011343 image=ConnectedComponentsImage(image,connectivity,
Cristy4f83be82015-12-31 08:40:53 -050011344 (CCObjectInfo **) NULL,exception);
cristy6e0b3bc2014-10-19 17:51:42 +000011345 break;
11346 }
cristy0b94b392015-06-22 18:56:37 +000011347 case 143: /* Copy */
11348 {
11349 Image
11350 *source_image;
11351
11352 OffsetInfo
11353 offset;
11354
cristy2ffdb092015-06-25 14:31:20 +000011355 RectangleInfo
11356 offset_geometry;
11357
cristyf3a724a2015-06-25 13:02:53 +000011358 source_image=image;
cristy0b94b392015-06-22 18:56:37 +000011359 if (attribute_flag[0] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011360 source_image=argument_list[0].image_reference;
cristy2ffdb092015-06-25 14:31:20 +000011361 SetGeometry(source_image,&geometry);
cristy0b94b392015-06-22 18:56:37 +000011362 if (attribute_flag[1] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011363 flags=ParseGravityGeometry(source_image,
11364 argument_list[1].string_reference,&geometry,exception);
cristy0b94b392015-06-22 18:56:37 +000011365 if (attribute_flag[2] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011366 geometry.width=argument_list[2].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011367 if (attribute_flag[3] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011368 geometry.height=argument_list[3].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011369 if (attribute_flag[4] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011370 geometry.x=argument_list[4].integer_reference;
11371 if (attribute_flag[5] != 0)
11372 geometry.y=argument_list[5].integer_reference;
11373 if (attribute_flag[6] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011374 image->gravity=(GravityType) argument_list[6].integer_reference;
dirk169d1642015-06-27 19:51:08 +000011375 SetGeometry(image,&offset_geometry);
cristyf3a724a2015-06-25 13:02:53 +000011376 if (attribute_flag[7] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011377 flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11378 &offset_geometry,exception);
11379 offset.x=offset_geometry.x;
11380 offset.y=offset_geometry.y;
cristyf3a724a2015-06-25 13:02:53 +000011381 if (attribute_flag[8] != 0)
11382 offset.x=argument_list[8].integer_reference;
11383 if (attribute_flag[9] != 0)
11384 offset.y=argument_list[9].integer_reference;
cristycd6d5182015-06-23 17:22:15 +000011385 (void) CopyImagePixels(image,source_image,&geometry,&offset,
11386 exception);
cristy0b94b392015-06-22 18:56:37 +000011387 break;
11388 }
Cristy5488c982016-02-13 14:07:50 -050011389 case 144: /* Color */
11390 {
11391 PixelInfo
11392 color;
11393
Cristyf20e3562016-02-14 09:08:15 -050011394 (void) QueryColorCompliance("none",AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011395 if (attribute_flag[0] != 0)
Cristyf20e3562016-02-14 09:08:15 -050011396 (void) QueryColorCompliance(argument_list[0].string_reference,
11397 AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011398 (void) SetImageColor(image,&color,exception);
11399 break;
11400 }
Cristy2d830ed2016-02-21 10:54:16 -050011401 case 145: /* WaveletDenoise */
11402 {
Cristyc1759412016-02-27 12:17:58 -050011403 if (attribute_flag[0] != 0)
Cristyee21f7f2016-02-27 15:56:49 -050011404 {
11405 flags=ParseGeometry(argument_list[0].string_reference,
11406 &geometry_info);
11407 if ((flags & PercentValue) != 0)
Cristy23446632016-02-29 09:36:34 -050011408 {
11409 geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11410 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11411 }
Cristyee21f7f2016-02-27 15:56:49 -050011412 if ((flags & SigmaValue) == 0)
11413 geometry_info.sigma=0.0;
11414 }
Cristyc1759412016-02-27 12:17:58 -050011415 if (attribute_flag[1] != 0)
11416 geometry_info.rho=argument_list[1].real_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011417 if (attribute_flag[2] != 0)
Cristyc1759412016-02-27 12:17:58 -050011418 geometry_info.sigma=argument_list[2].real_reference;
11419 if (attribute_flag[3] != 0)
11420 channel=(ChannelType) argument_list[3].integer_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011421 channel_mask=SetImageChannelMask(image,channel);
Cristyc1759412016-02-27 12:17:58 -050011422 image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11423 exception);
Cristy2d830ed2016-02-21 10:54:16 -050011424 if (image != (Image *) NULL)
11425 (void) SetImageChannelMask(image,channel_mask);
11426 break;
11427 }
Cristy99a57162016-12-05 11:47:57 -050011428 case 146: /* Colorspace */
11429 {
11430 ColorspaceType
11431 colorspace;
11432
11433 colorspace=sRGBColorspace;
11434 if (attribute_flag[0] != 0)
11435 colorspace=(ColorspaceType) argument_list[0].integer_reference;
11436 (void) TransformImageColorspace(image,colorspace,exception);
11437 break;
11438 }
Cristy53353872017-07-02 12:24:24 -040011439 case 147: /* AutoThreshold */
11440 {
11441 AutoThresholdMethod
11442 method;
11443
11444 method=UndefinedThresholdMethod;
11445 if (attribute_flag[0] != 0)
Cristyb63e7752017-07-02 13:22:01 -040011446 method=(AutoThresholdMethod) argument_list[0].integer_reference;
Cristy53353872017-07-02 12:24:24 -040011447 (void) AutoThresholdImage(image,method,exception);
11448 break;
11449 }
Cristy532b3382018-08-05 17:56:56 -040011450 case 148: /* RangeThreshold */
11451 {
11452 if (attribute_flag[0] != 0)
11453 {
11454 flags=ParseGeometry(argument_list[0].string_reference,
11455 &geometry_info);
11456 if ((flags & SigmaValue) == 0)
11457 geometry_info.sigma=geometry_info.rho;
11458 if ((flags & XiValue) == 0)
11459 geometry_info.xi=geometry_info.sigma;
11460 if ((flags & PsiValue) == 0)
11461 geometry_info.psi=geometry_info.xi;
11462 }
11463 if (attribute_flag[1] != 0)
11464 geometry_info.rho=argument_list[1].real_reference;
11465 if (attribute_flag[2] != 0)
11466 geometry_info.sigma=argument_list[2].real_reference;
11467 if (attribute_flag[3] != 0)
11468 geometry_info.xi=argument_list[3].real_reference;
11469 if (attribute_flag[4] != 0)
11470 geometry_info.psi=argument_list[4].real_reference;
11471 if (attribute_flag[5] != 0)
11472 channel=(ChannelType) argument_list[5].integer_reference;
11473 channel_mask=SetImageChannelMask(image,channel);
Cristy9b220db2018-08-05 18:02:28 -040011474 (void) RangeThresholdImage(image,geometry_info.rho,
11475 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
Cristy532b3382018-08-05 17:56:56 -040011476 if (image != (Image *) NULL)
11477 (void) SetImageChannelMask(image,channel_mask);
11478 break;
11479 }
Cristy9f252542018-11-21 19:13:46 -050011480 case 149: /* CLAHE */
11481 {
11482 if (attribute_flag[0] != 0)
11483 {
11484 flags=ParseGeometry(argument_list[0].string_reference,
11485 &geometry_info);
11486 if ((flags & PercentValue) != 0)
11487 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11488 }
11489 if (attribute_flag[1] != 0)
11490 geometry_info.rho=argument_list[1].integer_reference;
11491 if (attribute_flag[2] != 0)
11492 geometry_info.sigma=argument_list[2].integer_reference;
11493 if (attribute_flag[3] != 0)
11494 geometry_info.xi=argument_list[3].integer_reference;;
11495 if (attribute_flag[4] != 0)
11496 geometry_info.psi=argument_list[4].integer_reference;;
11497 image=CLAHEImage(image,(size_t) geometry_info.rho,
11498 (size_t) geometry_info.sigma,geometry_info.xi,geometry_info.psi,
11499 exception);
11500 break;
11501 }
cristy4a3ce0a2013-08-03 20:06:59 +000011502 }
11503 if (next != (Image *) NULL)
11504 (void) CatchImageException(next);
Cristy7e567962018-02-03 12:42:20 -050011505 if ((region_info.width*region_info.height) != 0)
11506 (void) SetImageRegionMask(image,WritePixelMask,
11507 (const RectangleInfo *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011508 if (image != (Image *) NULL)
11509 {
11510 number_images++;
11511 if (next && (next != image))
11512 {
11513 image->next=next->next;
11514 if (image->next != (Image *) NULL)
11515 image->next->previous=image;
11516 DeleteImageFromRegistry(*pv,next);
11517 }
11518 sv_setiv(*pv,PTR2IV(image));
11519 next=image;
11520 }
11521 if (*pv)
11522 pv++;
11523 }
11524
11525 PerlException:
11526 if (reference_vector)
11527 reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11528 InheritPerlException(exception,perl_exception);
11529 exception=DestroyExceptionInfo(exception);
11530 sv_setiv(perl_exception,(IV) number_images);
11531 SvPOK_on(perl_exception);
11532 ST(0)=sv_2mortal(perl_exception);
11533 XSRETURN(1);
11534 }
11535
11536#
11537###############################################################################
11538# #
11539# #
11540# #
11541# M o n t a g e #
11542# #
11543# #
11544# #
11545###############################################################################
11546#
11547#
11548void
11549Montage(ref,...)
11550 Image::Magick ref=NO_INIT
11551 ALIAS:
11552 MontageImage = 1
11553 montage = 2
11554 montageimage = 3
11555 PPCODE:
11556 {
11557 AV
11558 *av;
11559
11560 char
11561 *attribute;
11562
11563 ExceptionInfo
11564 *exception;
11565
11566 HV
11567 *hv;
11568
11569 Image
11570 *image,
11571 *next;
11572
11573 PixelInfo
11574 transparent_color;
11575
11576 MontageInfo
11577 *montage_info;
11578
11579 register ssize_t
11580 i;
11581
11582 ssize_t
11583 sp;
11584
11585 struct PackageInfo
11586 *info;
11587
11588 SV
11589 *av_reference,
11590 *perl_exception,
11591 *reference,
11592 *rv,
11593 *sv;
11594
11595 PERL_UNUSED_VAR(ref);
11596 PERL_UNUSED_VAR(ix);
11597 exception=AcquireExceptionInfo();
11598 perl_exception=newSVpv("",0);
11599 sv=NULL;
11600 attribute=NULL;
11601 if (sv_isobject(ST(0)) == 0)
11602 {
11603 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11604 PackageName);
11605 goto PerlException;
11606 }
11607 reference=SvRV(ST(0));
11608 hv=SvSTASH(reference);
11609 av=newAV();
11610 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11611 SvREFCNT_dec(av);
11612 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11613 if (image == (Image *) NULL)
11614 {
11615 ThrowPerlException(exception,OptionError,"NoImagesDefined",
11616 PackageName);
11617 goto PerlException;
11618 }
11619 /*
11620 Get options.
11621 */
11622 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11623 montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11624 (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11625 exception);
11626 for (i=2; i < items; i+=2)
11627 {
11628 attribute=(char *) SvPV(ST(i-1),na);
11629 switch (*attribute)
11630 {
11631 case 'B':
11632 case 'b':
11633 {
11634 if (LocaleCompare(attribute,"background") == 0)
11635 {
11636 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11637 &montage_info->background_color,exception);
11638 for (next=image; next; next=next->next)
11639 next->background_color=montage_info->background_color;
11640 break;
11641 }
11642 if (LocaleCompare(attribute,"border") == 0)
11643 {
11644 montage_info->border_width=SvIV(ST(i));
11645 break;
11646 }
11647 if (LocaleCompare(attribute,"bordercolor") == 0)
11648 {
11649 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11650 &montage_info->border_color,exception);
11651 for (next=image; next; next=next->next)
11652 next->border_color=montage_info->border_color;
11653 break;
11654 }
11655 if (LocaleCompare(attribute,"borderwidth") == 0)
11656 {
11657 montage_info->border_width=SvIV(ST(i));
11658 break;
11659 }
11660 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11661 attribute);
11662 break;
11663 }
11664 case 'C':
11665 case 'c':
11666 {
11667 if (LocaleCompare(attribute,"compose") == 0)
11668 {
11669 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11670 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11671 if (sp < 0)
11672 {
11673 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11674 SvPV(ST(i),na));
11675 break;
11676 }
11677 for (next=image; next; next=next->next)
11678 next->compose=(CompositeOperator) sp;
11679 break;
11680 }
11681 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11682 attribute);
11683 break;
11684 }
11685 case 'F':
11686 case 'f':
11687 {
11688 if (LocaleCompare(attribute,"fill") == 0)
11689 {
11690 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11691 &montage_info->fill,exception);
11692 break;
11693 }
11694 if (LocaleCompare(attribute,"font") == 0)
11695 {
11696 (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11697 break;
11698 }
11699 if (LocaleCompare(attribute,"frame") == 0)
11700 {
11701 char
11702 *p;
11703
11704 p=SvPV(ST(i),na);
11705 if (IsGeometry(p) == MagickFalse)
11706 {
11707 ThrowPerlException(exception,OptionError,"MissingGeometry",
11708 p);
11709 break;
11710 }
11711 (void) CloneString(&montage_info->frame,p);
11712 if (*p == '\0')
11713 montage_info->frame=(char *) NULL;
11714 break;
11715 }
11716 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11717 attribute);
11718 break;
11719 }
11720 case 'G':
11721 case 'g':
11722 {
11723 if (LocaleCompare(attribute,"geometry") == 0)
11724 {
11725 char
11726 *p;
11727
11728 p=SvPV(ST(i),na);
11729 if (IsGeometry(p) == MagickFalse)
11730 {
11731 ThrowPerlException(exception,OptionError,"MissingGeometry",
11732 p);
11733 break;
11734 }
11735 (void) CloneString(&montage_info->geometry,p);
11736 if (*p == '\0')
11737 montage_info->geometry=(char *) NULL;
11738 break;
11739 }
11740 if (LocaleCompare(attribute,"gravity") == 0)
11741 {
11742 ssize_t
11743 in;
11744
11745 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11746 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11747 if (in < 0)
11748 {
11749 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11750 SvPV(ST(i),na));
11751 return;
11752 }
11753 montage_info->gravity=(GravityType) in;
11754 for (next=image; next; next=next->next)
11755 next->gravity=(GravityType) in;
11756 break;
11757 }
11758 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11759 attribute);
11760 break;
11761 }
11762 case 'L':
11763 case 'l':
11764 {
11765 if (LocaleCompare(attribute,"label") == 0)
11766 {
11767 for (next=image; next; next=next->next)
Cristy935a4052017-03-31 17:45:37 -040011768 (void) SetImageProperty(next,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +000011769 info ? info->image_info : (ImageInfo *) NULL,next,
Cristy935a4052017-03-31 17:45:37 -040011770 SvPV(ST(i),na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011771 break;
11772 }
11773 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11774 attribute);
11775 break;
11776 }
11777 case 'M':
11778 case 'm':
11779 {
11780 if (LocaleCompare(attribute,"mattecolor") == 0)
11781 {
11782 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
Cristy8645e042016-02-03 16:35:29 -050011783 &montage_info->alpha_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011784 for (next=image; next; next=next->next)
Cristy8645e042016-02-03 16:35:29 -050011785 next->alpha_color=montage_info->alpha_color;
cristy4a3ce0a2013-08-03 20:06:59 +000011786 break;
11787 }
11788 if (LocaleCompare(attribute,"mode") == 0)
11789 {
11790 ssize_t
11791 in;
11792
11793 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11794 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11795 switch (in)
11796 {
11797 default:
11798 {
11799 ThrowPerlException(exception,OptionError,
11800 "UnrecognizedModeType",SvPV(ST(i),na));
11801 break;
11802 }
11803 case FrameMode:
11804 {
11805 (void) CloneString(&montage_info->frame,"15x15+3+3");
11806 montage_info->shadow=MagickTrue;
11807 break;
11808 }
11809 case UnframeMode:
11810 {
11811 montage_info->frame=(char *) NULL;
11812 montage_info->shadow=MagickFalse;
11813 montage_info->border_width=0;
11814 break;
11815 }
11816 case ConcatenateMode:
11817 {
11818 montage_info->frame=(char *) NULL;
11819 montage_info->shadow=MagickFalse;
11820 (void) CloneString(&montage_info->geometry,"+0+0");
11821 montage_info->border_width=0;
11822 }
11823 }
11824 break;
11825 }
11826 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11827 attribute);
11828 break;
11829 }
11830 case 'P':
11831 case 'p':
11832 {
11833 if (LocaleCompare(attribute,"pointsize") == 0)
11834 {
11835 montage_info->pointsize=SvIV(ST(i));
11836 break;
11837 }
11838 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11839 attribute);
11840 break;
11841 }
11842 case 'S':
11843 case 's':
11844 {
11845 if (LocaleCompare(attribute,"shadow") == 0)
11846 {
11847 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11848 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11849 if (sp < 0)
11850 {
11851 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11852 SvPV(ST(i),na));
11853 break;
11854 }
11855 montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11856 break;
11857 }
11858 if (LocaleCompare(attribute,"stroke") == 0)
11859 {
11860 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11861 &montage_info->stroke,exception);
11862 break;
11863 }
11864 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11865 attribute);
11866 break;
11867 }
11868 case 'T':
11869 case 't':
11870 {
11871 if (LocaleCompare(attribute,"texture") == 0)
11872 {
11873 (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11874 break;
11875 }
11876 if (LocaleCompare(attribute,"tile") == 0)
11877 {
11878 char *p=SvPV(ST(i),na);
11879 if (IsGeometry(p) == MagickFalse)
11880 {
11881 ThrowPerlException(exception,OptionError,"MissingGeometry",
11882 p);
11883 break;
11884 }
11885 (void) CloneString(&montage_info->tile,p);
11886 if (*p == '\0')
11887 montage_info->tile=(char *) NULL;
11888 break;
11889 }
11890 if (LocaleCompare(attribute,"title") == 0)
11891 {
11892 (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11893 break;
11894 }
11895 if (LocaleCompare(attribute,"transparent") == 0)
11896 {
11897 PixelInfo
11898 transparent_color;
11899
11900 QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11901 &transparent_color,exception);
11902 for (next=image; next; next=next->next)
11903 (void) TransparentPaintImage(next,&transparent_color,
11904 TransparentAlpha,MagickFalse,exception);
11905 break;
11906 }
11907 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11908 attribute);
11909 break;
11910 }
11911 default:
11912 {
11913 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11914 attribute);
11915 break;
11916 }
11917 }
11918 }
11919 image=MontageImageList(info->image_info,montage_info,image,exception);
11920 montage_info=DestroyMontageInfo(montage_info);
11921 if (image == (Image *) NULL)
11922 goto PerlException;
11923 if (transparent_color.alpha != TransparentAlpha)
11924 for (next=image; next; next=next->next)
11925 (void) TransparentPaintImage(next,&transparent_color,
11926 TransparentAlpha,MagickFalse,exception);
11927 for ( ; image; image=image->next)
11928 {
11929 AddImageToRegistry(sv,image);
11930 rv=newRV(sv);
11931 av_push(av,sv_bless(rv,hv));
11932 SvREFCNT_dec(sv);
11933 }
11934 exception=DestroyExceptionInfo(exception);
11935 ST(0)=av_reference;
11936 SvREFCNT_dec(perl_exception);
11937 XSRETURN(1);
11938
11939 PerlException:
11940 InheritPerlException(exception,perl_exception);
11941 exception=DestroyExceptionInfo(exception);
11942 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11943 SvPOK_on(perl_exception);
11944 ST(0)=sv_2mortal(perl_exception);
11945 XSRETURN(1);
11946 }
11947
11948#
11949###############################################################################
11950# #
11951# #
11952# #
11953# M o r p h #
11954# #
11955# #
11956# #
11957###############################################################################
11958#
11959#
11960void
11961Morph(ref,...)
11962 Image::Magick ref=NO_INIT
11963 ALIAS:
11964 MorphImage = 1
11965 morph = 2
11966 morphimage = 3
11967 PPCODE:
11968 {
11969 AV
11970 *av;
11971
11972 char
11973 *attribute;
11974
11975 ExceptionInfo
11976 *exception;
11977
11978 HV
11979 *hv;
11980
11981 Image
11982 *image;
11983
11984 register ssize_t
11985 i;
11986
11987 ssize_t
11988 number_frames;
11989
11990 struct PackageInfo
11991 *info;
11992
11993 SV
11994 *av_reference,
11995 *perl_exception,
11996 *reference,
11997 *rv,
11998 *sv;
11999
12000 PERL_UNUSED_VAR(ref);
12001 PERL_UNUSED_VAR(ix);
12002 exception=AcquireExceptionInfo();
12003 perl_exception=newSVpv("",0);
12004 sv=NULL;
12005 av=NULL;
12006 attribute=NULL;
12007 if (sv_isobject(ST(0)) == 0)
12008 {
12009 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12010 PackageName);
12011 goto PerlException;
12012 }
12013 reference=SvRV(ST(0));
12014 hv=SvSTASH(reference);
12015 av=newAV();
12016 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12017 SvREFCNT_dec(av);
12018 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12019 if (image == (Image *) NULL)
12020 {
12021 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12022 PackageName);
12023 goto PerlException;
12024 }
12025 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12026 /*
12027 Get attribute.
12028 */
12029 number_frames=30;
12030 for (i=2; i < items; i+=2)
12031 {
12032 attribute=(char *) SvPV(ST(i-1),na);
12033 switch (*attribute)
12034 {
12035 case 'F':
12036 case 'f':
12037 {
12038 if (LocaleCompare(attribute,"frames") == 0)
12039 {
12040 number_frames=SvIV(ST(i));
12041 break;
12042 }
12043 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12044 attribute);
12045 break;
12046 }
12047 default:
12048 {
12049 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12050 attribute);
12051 break;
12052 }
12053 }
12054 }
12055 image=MorphImages(image,number_frames,exception);
12056 if (image == (Image *) NULL)
12057 goto PerlException;
12058 for ( ; image; image=image->next)
12059 {
12060 AddImageToRegistry(sv,image);
12061 rv=newRV(sv);
12062 av_push(av,sv_bless(rv,hv));
12063 SvREFCNT_dec(sv);
12064 }
12065 exception=DestroyExceptionInfo(exception);
12066 ST(0)=av_reference;
12067 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12068 XSRETURN(1);
12069
12070 PerlException:
12071 InheritPerlException(exception,perl_exception);
12072 exception=DestroyExceptionInfo(exception);
12073 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12074 SvPOK_on(perl_exception);
12075 ST(0)=sv_2mortal(perl_exception);
12076 XSRETURN(1);
12077 }
12078
12079#
12080###############################################################################
12081# #
12082# #
12083# #
12084# M o s a i c #
12085# #
12086# #
12087# #
12088###############################################################################
12089#
12090#
12091void
12092Mosaic(ref)
12093 Image::Magick ref=NO_INIT
12094 ALIAS:
12095 MosaicImage = 1
12096 mosaic = 2
12097 mosaicimage = 3
12098 PPCODE:
12099 {
12100 AV
12101 *av;
12102
12103 ExceptionInfo
12104 *exception;
12105
12106 HV
12107 *hv;
12108
12109 Image
12110 *image;
12111
12112 struct PackageInfo
12113 *info;
12114
12115 SV
12116 *perl_exception,
12117 *reference,
12118 *rv,
12119 *sv;
12120
12121 PERL_UNUSED_VAR(ref);
12122 PERL_UNUSED_VAR(ix);
12123 exception=AcquireExceptionInfo();
12124 perl_exception=newSVpv("",0);
12125 sv=NULL;
12126 if (sv_isobject(ST(0)) == 0)
12127 {
12128 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12129 PackageName);
12130 goto PerlException;
12131 }
12132 reference=SvRV(ST(0));
12133 hv=SvSTASH(reference);
12134 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12135 if (image == (Image *) NULL)
12136 {
12137 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12138 PackageName);
12139 goto PerlException;
12140 }
12141 image=MergeImageLayers(image,MosaicLayer,exception);
12142 /*
12143 Create blessed Perl array for the returned image.
12144 */
12145 av=newAV();
12146 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12147 SvREFCNT_dec(av);
12148 AddImageToRegistry(sv,image);
12149 rv=newRV(sv);
12150 av_push(av,sv_bless(rv,hv));
12151 SvREFCNT_dec(sv);
cristy4a3ce0a2013-08-03 20:06:59 +000012152 (void) CopyMagickString(info->image_info->filename,image->filename,
cristy151b66d2015-04-15 10:50:31 +000012153 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012154 SetImageInfo(info->image_info,0,exception);
12155 exception=DestroyExceptionInfo(exception);
12156 SvREFCNT_dec(perl_exception);
12157 XSRETURN(1);
12158
12159 PerlException:
12160 InheritPerlException(exception,perl_exception);
12161 exception=DestroyExceptionInfo(exception);
12162 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12163 SvPOK_on(perl_exception); /* return messages in string context */
12164 ST(0)=sv_2mortal(perl_exception);
12165 XSRETURN(1);
12166 }
12167
12168#
12169###############################################################################
12170# #
12171# #
12172# #
12173# P i n g #
12174# #
12175# #
12176# #
12177###############################################################################
12178#
12179#
12180void
12181Ping(ref,...)
12182 Image::Magick ref=NO_INIT
12183 ALIAS:
12184 PingImage = 1
12185 ping = 2
12186 pingimage = 3
12187 PPCODE:
12188 {
12189 AV
12190 *av;
12191
12192 char
12193 **keep,
12194 **list;
12195
12196 ExceptionInfo
12197 *exception;
12198
12199 Image
12200 *image,
12201 *next;
12202
12203 int
12204 n;
12205
12206 MagickBooleanType
12207 status;
12208
12209 register char
12210 **p;
12211
12212 register ssize_t
12213 i;
12214
12215 ssize_t
12216 ac;
12217
12218 STRLEN
12219 *length;
12220
12221 struct PackageInfo
12222 *info,
12223 *package_info;
12224
12225 SV
12226 *perl_exception,
12227 *reference;
12228
12229 size_t
12230 count;
12231
12232 PERL_UNUSED_VAR(ref);
12233 PERL_UNUSED_VAR(ix);
12234 exception=AcquireExceptionInfo();
12235 perl_exception=newSVpv("",0);
12236 package_info=(struct PackageInfo *) NULL;
12237 ac=(items < 2) ? 1 : items-1;
12238 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12239 keep=list;
12240 length=(STRLEN *) NULL;
12241 if (list == (char **) NULL)
12242 {
12243 ThrowPerlException(exception,ResourceLimitError,
12244 "MemoryAllocationFailed",PackageName);
12245 goto PerlException;
12246 }
12247 keep=list;
12248 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12249 if (length == (STRLEN *) NULL)
12250 {
12251 ThrowPerlException(exception,ResourceLimitError,
12252 "MemoryAllocationFailed",PackageName);
12253 goto PerlException;
12254 }
12255 if (sv_isobject(ST(0)) == 0)
12256 {
12257 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12258 PackageName);
12259 goto PerlException;
12260 }
12261 reference=SvRV(ST(0));
12262 if (SvTYPE(reference) != SVt_PVAV)
12263 {
12264 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12265 PackageName);
12266 goto PerlException;
12267 }
12268 av=(AV *) reference;
12269 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12270 exception);
12271 package_info=ClonePackageInfo(info,exception);
12272 n=1;
12273 if (items <= 1)
12274 *list=(char *) (*package_info->image_info->filename ?
12275 package_info->image_info->filename : "XC:black");
12276 else
12277 for (n=0, i=0; i < ac; i++)
12278 {
12279 list[n]=(char *) SvPV(ST(i+1),length[n]);
12280 if ((items >= 3) && strEQcase(list[n],"blob"))
12281 {
12282 void
12283 *blob;
12284
12285 i++;
12286 blob=(void *) (SvPV(ST(i+1),length[n]));
12287 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12288 }
12289 if ((items >= 3) && strEQcase(list[n],"filename"))
12290 continue;
12291 if ((items >= 3) && strEQcase(list[n],"file"))
12292 {
12293 FILE
12294 *file;
12295
12296 PerlIO
12297 *io_info;
12298
12299 i++;
12300 io_info=IoIFP(sv_2io(ST(i+1)));
12301 if (io_info == (PerlIO *) NULL)
12302 {
12303 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12304 PackageName);
12305 continue;
12306 }
12307 file=PerlIO_findFILE(io_info);
12308 if (file == (FILE *) NULL)
12309 {
12310 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12311 PackageName);
12312 continue;
12313 }
12314 SetImageInfoFile(package_info->image_info,file);
12315 }
12316 if ((items >= 3) && strEQcase(list[n],"magick"))
12317 continue;
12318 n++;
12319 }
12320 list[n]=(char *) NULL;
12321 keep=list;
12322 status=ExpandFilenames(&n,&list);
12323 if (status == MagickFalse)
12324 {
12325 ThrowPerlException(exception,ResourceLimitError,
12326 "MemoryAllocationFailed",PackageName);
12327 goto PerlException;
12328 }
12329 count=0;
12330 for (i=0; i < n; i++)
12331 {
12332 (void) CopyMagickString(package_info->image_info->filename,list[i],
cristy151b66d2015-04-15 10:50:31 +000012333 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012334 image=PingImage(package_info->image_info,exception);
12335 if (image == (Image *) NULL)
12336 break;
12337 if ((package_info->image_info->file != (FILE *) NULL) ||
12338 (package_info->image_info->blob != (void *) NULL))
12339 DisassociateImageStream(image);
12340 count+=GetImageListLength(image);
12341 EXTEND(sp,4*count);
12342 for (next=image; next; next=next->next)
12343 {
12344 PUSHs(sv_2mortal(newSViv(next->columns)));
12345 PUSHs(sv_2mortal(newSViv(next->rows)));
12346 PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12347 PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12348 }
12349 image=DestroyImageList(image);
12350 }
12351 /*
12352 Free resources.
12353 */
12354 for (i=0; i < n; i++)
12355 if (list[i] != (char *) NULL)
12356 for (p=keep; list[i] != *p++; )
12357 if (*p == NULL)
12358 {
12359 list[i]=(char *) RelinquishMagickMemory(list[i]);
12360 break;
12361 }
12362
12363 PerlException:
12364 if (package_info != (struct PackageInfo *) NULL)
12365 DestroyPackageInfo(package_info);
12366 if (list && (list != keep))
12367 list=(char **) RelinquishMagickMemory(list);
12368 if (keep)
12369 keep=(char **) RelinquishMagickMemory(keep);
12370 if (length)
12371 length=(STRLEN *) RelinquishMagickMemory(length);
12372 InheritPerlException(exception,perl_exception);
12373 exception=DestroyExceptionInfo(exception);
12374 SvREFCNT_dec(perl_exception); /* throw away all errors */
12375 }
12376
12377#
12378###############################################################################
12379# #
12380# #
12381# #
12382# P r e v i e w #
12383# #
12384# #
12385# #
12386###############################################################################
12387#
12388#
12389void
12390Preview(ref,...)
12391 Image::Magick ref=NO_INIT
12392 ALIAS:
12393 PreviewImage = 1
12394 preview = 2
12395 previewimage = 3
12396 PPCODE:
12397 {
12398 AV
12399 *av;
12400
12401 ExceptionInfo
12402 *exception;
12403
12404 HV
12405 *hv;
12406
12407 Image
12408 *image,
12409 *preview_image;
12410
12411 PreviewType
12412 preview_type;
12413
12414 struct PackageInfo
12415 *info;
12416
12417 SV
12418 *av_reference,
12419 *perl_exception,
12420 *reference,
12421 *rv,
12422 *sv;
12423
12424 PERL_UNUSED_VAR(ref);
12425 PERL_UNUSED_VAR(ix);
12426 exception=AcquireExceptionInfo();
12427 perl_exception=newSVpv("",0);
12428 sv=NULL;
12429 av=NULL;
12430 if (sv_isobject(ST(0)) == 0)
12431 {
12432 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12433 PackageName);
12434 goto PerlException;
12435 }
12436 reference=SvRV(ST(0));
12437 hv=SvSTASH(reference);
12438 av=newAV();
12439 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12440 SvREFCNT_dec(av);
12441 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12442 if (image == (Image *) NULL)
12443 {
12444 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12445 PackageName);
12446 goto PerlException;
12447 }
12448 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12449 preview_type=GammaPreview;
12450 if (items > 1)
12451 preview_type=(PreviewType)
12452 ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12453 for ( ; image; image=image->next)
12454 {
12455 preview_image=PreviewImage(image,preview_type,exception);
12456 if (preview_image == (Image *) NULL)
12457 goto PerlException;
12458 AddImageToRegistry(sv,preview_image);
12459 rv=newRV(sv);
12460 av_push(av,sv_bless(rv,hv));
12461 SvREFCNT_dec(sv);
12462 }
12463 exception=DestroyExceptionInfo(exception);
12464 ST(0)=av_reference;
12465 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12466 XSRETURN(1);
12467
12468 PerlException:
12469 InheritPerlException(exception,perl_exception);
12470 exception=DestroyExceptionInfo(exception);
12471 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12472 SvPOK_on(perl_exception);
12473 ST(0)=sv_2mortal(perl_exception);
12474 XSRETURN(1);
12475 }
12476
12477#
12478###############################################################################
12479# #
12480# #
12481# #
12482# Q u e r y C o l o r #
12483# #
12484# #
12485# #
12486###############################################################################
12487#
12488#
12489void
12490QueryColor(ref,...)
12491 Image::Magick ref=NO_INIT
12492 ALIAS:
12493 querycolor = 1
12494 PPCODE:
12495 {
12496 char
12497 *name;
12498
12499 ExceptionInfo
12500 *exception;
12501
12502 PixelInfo
12503 color;
12504
12505 register ssize_t
12506 i;
12507
12508 SV
12509 *perl_exception;
12510
12511 PERL_UNUSED_VAR(ref);
12512 PERL_UNUSED_VAR(ix);
12513 exception=AcquireExceptionInfo();
12514 perl_exception=newSVpv("",0);
12515 if (items == 1)
12516 {
12517 const ColorInfo
12518 **colorlist;
12519
12520 size_t
12521 colors;
12522
12523 colorlist=GetColorInfoList("*",&colors,exception);
12524 EXTEND(sp,colors);
12525 for (i=0; i < (ssize_t) colors; i++)
12526 {
12527 PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12528 }
12529 colorlist=(const ColorInfo **)
12530 RelinquishMagickMemory((ColorInfo **) colorlist);
12531 goto PerlException;
12532 }
12533 EXTEND(sp,5*items);
12534 for (i=1; i < items; i++)
12535 {
12536 name=(char *) SvPV(ST(i),na);
12537 if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12538 {
12539 PUSHs(&sv_undef);
12540 continue;
12541 }
12542 PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12543 PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12544 PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12545 if (color.colorspace == CMYKColorspace)
12546 PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
cristy17f11b02014-12-20 19:37:04 +000012547 if (color.alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +000012548 PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12549 }
12550
12551 PerlException:
12552 InheritPerlException(exception,perl_exception);
12553 exception=DestroyExceptionInfo(exception);
12554 SvREFCNT_dec(perl_exception);
12555 }
12556
12557#
12558###############################################################################
12559# #
12560# #
12561# #
12562# Q u e r y C o l o r N a m e #
12563# #
12564# #
12565# #
12566###############################################################################
12567#
12568#
12569void
12570QueryColorname(ref,...)
12571 Image::Magick ref=NO_INIT
12572 ALIAS:
12573 querycolorname = 1
12574 PPCODE:
12575 {
12576 AV
12577 *av;
12578
12579 char
cristy151b66d2015-04-15 10:50:31 +000012580 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012581
12582 ExceptionInfo
12583 *exception;
12584
12585 Image
12586 *image;
12587
12588 PixelInfo
12589 target_color;
12590
12591 register ssize_t
12592 i;
12593
12594 struct PackageInfo
12595 *info;
12596
12597 SV
12598 *perl_exception,
12599 *reference; /* reference is the SV* of ref=SvIV(reference) */
12600
12601 PERL_UNUSED_VAR(ref);
12602 PERL_UNUSED_VAR(ix);
12603 exception=AcquireExceptionInfo();
12604 perl_exception=newSVpv("",0);
12605 reference=SvRV(ST(0));
12606 av=(AV *) reference;
12607 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12608 exception);
12609 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12610 if (image == (Image *) NULL)
12611 {
12612 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12613 PackageName);
12614 goto PerlException;
12615 }
12616 EXTEND(sp,items);
12617 for (i=1; i < items; i++)
12618 {
12619 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12620 exception);
12621 (void) QueryColorname(image,&target_color,SVGCompliance,message,
12622 exception);
12623 PUSHs(sv_2mortal(newSVpv(message,0)));
12624 }
12625
12626 PerlException:
12627 InheritPerlException(exception,perl_exception);
12628 exception=DestroyExceptionInfo(exception);
12629 SvREFCNT_dec(perl_exception);
12630 }
12631
12632#
12633###############################################################################
12634# #
12635# #
12636# #
12637# Q u e r y F o n t #
12638# #
12639# #
12640# #
12641###############################################################################
12642#
12643#
12644void
12645QueryFont(ref,...)
12646 Image::Magick ref=NO_INIT
12647 ALIAS:
12648 queryfont = 1
12649 PPCODE:
12650 {
12651 char
12652 *name,
cristy151b66d2015-04-15 10:50:31 +000012653 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012654
12655 ExceptionInfo
12656 *exception;
12657
12658 register ssize_t
12659 i;
12660
12661 SV
12662 *perl_exception;
12663
12664 volatile const TypeInfo
12665 *type_info;
12666
12667 PERL_UNUSED_VAR(ref);
12668 PERL_UNUSED_VAR(ix);
12669 exception=AcquireExceptionInfo();
12670 perl_exception=newSVpv("",0);
12671 if (items == 1)
12672 {
12673 const TypeInfo
12674 **typelist;
12675
12676 size_t
12677 types;
12678
12679 typelist=GetTypeInfoList("*",&types,exception);
12680 EXTEND(sp,types);
12681 for (i=0; i < (ssize_t) types; i++)
12682 {
12683 PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12684 }
12685 typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12686 typelist);
12687 goto PerlException;
12688 }
12689 EXTEND(sp,10*items);
12690 for (i=1; i < items; i++)
12691 {
12692 name=(char *) SvPV(ST(i),na);
12693 type_info=GetTypeInfo(name,exception);
12694 if (type_info == (TypeInfo *) NULL)
12695 {
12696 PUSHs(&sv_undef);
12697 continue;
12698 }
12699 if (type_info->name == (char *) NULL)
12700 PUSHs(&sv_undef);
12701 else
12702 PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12703 if (type_info->description == (char *) NULL)
12704 PUSHs(&sv_undef);
12705 else
12706 PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12707 if (type_info->family == (char *) NULL)
12708 PUSHs(&sv_undef);
12709 else
12710 PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12711 if (type_info->style == UndefinedStyle)
12712 PUSHs(&sv_undef);
12713 else
12714 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12715 type_info->style),0)));
12716 if (type_info->stretch == UndefinedStretch)
12717 PUSHs(&sv_undef);
12718 else
12719 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12720 type_info->stretch),0)));
cristy151b66d2015-04-15 10:50:31 +000012721 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
cristy4a3ce0a2013-08-03 20:06:59 +000012722 type_info->weight);
12723 PUSHs(sv_2mortal(newSVpv(message,0)));
12724 if (type_info->encoding == (char *) NULL)
12725 PUSHs(&sv_undef);
12726 else
12727 PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12728 if (type_info->foundry == (char *) NULL)
12729 PUSHs(&sv_undef);
12730 else
12731 PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12732 if (type_info->format == (char *) NULL)
12733 PUSHs(&sv_undef);
12734 else
12735 PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12736 if (type_info->metrics == (char *) NULL)
12737 PUSHs(&sv_undef);
12738 else
12739 PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12740 if (type_info->glyphs == (char *) NULL)
12741 PUSHs(&sv_undef);
12742 else
12743 PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12744 }
12745
12746 PerlException:
12747 InheritPerlException(exception,perl_exception);
12748 exception=DestroyExceptionInfo(exception);
12749 SvREFCNT_dec(perl_exception);
12750 }
12751
12752#
12753###############################################################################
12754# #
12755# #
12756# #
12757# Q u e r y F o n t M e t r i c s #
12758# #
12759# #
12760# #
12761###############################################################################
12762#
12763#
12764void
12765QueryFontMetrics(ref,...)
12766 Image::Magick ref=NO_INIT
12767 ALIAS:
12768 queryfontmetrics = 1
12769 PPCODE:
12770 {
12771 AffineMatrix
12772 affine,
12773 current;
12774
12775 AV
12776 *av;
12777
12778 char
12779 *attribute;
12780
12781 double
12782 x,
12783 y;
12784
12785 DrawInfo
12786 *draw_info;
12787
12788 ExceptionInfo
12789 *exception;
12790
12791 GeometryInfo
12792 geometry_info;
12793
12794 Image
12795 *image;
12796
12797 MagickBooleanType
12798 status;
12799
12800 MagickStatusType
12801 flags;
12802
12803 register ssize_t
12804 i;
12805
12806 ssize_t
12807 type;
12808
12809 struct PackageInfo
12810 *info,
12811 *package_info;
12812
12813 SV
12814 *perl_exception,
12815 *reference; /* reference is the SV* of ref=SvIV(reference) */
12816
12817 TypeMetric
12818 metrics;
12819
12820 PERL_UNUSED_VAR(ref);
12821 PERL_UNUSED_VAR(ix);
12822 exception=AcquireExceptionInfo();
12823 package_info=(struct PackageInfo *) NULL;
12824 perl_exception=newSVpv("",0);
12825 reference=SvRV(ST(0));
12826 av=(AV *) reference;
12827 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12828 exception);
12829 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12830 if (image == (Image *) NULL)
12831 {
12832 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12833 PackageName);
12834 goto PerlException;
12835 }
12836 package_info=ClonePackageInfo(info,exception);
12837 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12838 CloneString(&draw_info->text,"");
12839 current=draw_info->affine;
12840 GetAffineMatrix(&affine);
12841 x=0.0;
12842 y=0.0;
12843 EXTEND(sp,7*items);
12844 for (i=2; i < items; i+=2)
12845 {
12846 attribute=(char *) SvPV(ST(i-1),na);
12847 switch (*attribute)
12848 {
12849 case 'A':
12850 case 'a':
12851 {
12852 if (LocaleCompare(attribute,"antialias") == 0)
12853 {
12854 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12855 SvPV(ST(i),na));
12856 if (type < 0)
12857 {
12858 ThrowPerlException(exception,OptionError,"UnrecognizedType",
12859 SvPV(ST(i),na));
12860 break;
12861 }
12862 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12863 break;
12864 }
12865 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12866 attribute);
12867 break;
12868 }
12869 case 'd':
12870 case 'D':
12871 {
12872 if (LocaleCompare(attribute,"density") == 0)
12873 {
12874 CloneString(&draw_info->density,SvPV(ST(i),na));
12875 break;
12876 }
12877 if (LocaleCompare(attribute,"direction") == 0)
12878 {
12879 draw_info->direction=(DirectionType) ParseCommandOption(
12880 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12881 break;
12882 }
12883 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12884 attribute);
12885 break;
12886 }
12887 case 'e':
12888 case 'E':
12889 {
12890 if (LocaleCompare(attribute,"encoding") == 0)
12891 {
12892 CloneString(&draw_info->encoding,SvPV(ST(i),na));
12893 break;
12894 }
12895 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12896 attribute);
12897 break;
12898 }
12899 case 'f':
12900 case 'F':
12901 {
12902 if (LocaleCompare(attribute,"family") == 0)
12903 {
12904 CloneString(&draw_info->family,SvPV(ST(i),na));
12905 break;
12906 }
12907 if (LocaleCompare(attribute,"fill") == 0)
12908 {
12909 if (info)
12910 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12911 &draw_info->fill,exception);
12912 break;
12913 }
12914 if (LocaleCompare(attribute,"font") == 0)
12915 {
12916 CloneString(&draw_info->font,SvPV(ST(i),na));
12917 break;
12918 }
12919 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12920 attribute);
12921 break;
12922 }
12923 case 'g':
12924 case 'G':
12925 {
12926 if (LocaleCompare(attribute,"geometry") == 0)
12927 {
12928 CloneString(&draw_info->geometry,SvPV(ST(i),na));
12929 break;
12930 }
12931 if (LocaleCompare(attribute,"gravity") == 0)
12932 {
12933 draw_info->gravity=(GravityType) ParseCommandOption(
12934 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12935 break;
12936 }
12937 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12938 attribute);
12939 break;
12940 }
12941 case 'i':
12942 case 'I':
12943 {
12944 if (LocaleCompare(attribute,"interline-spacing") == 0)
12945 {
12946 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12947 draw_info->interline_spacing=geometry_info.rho;
12948 break;
12949 }
12950 if (LocaleCompare(attribute,"interword-spacing") == 0)
12951 {
12952 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12953 draw_info->interword_spacing=geometry_info.rho;
12954 break;
12955 }
12956 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12957 attribute);
12958 break;
12959 }
12960 case 'k':
12961 case 'K':
12962 {
12963 if (LocaleCompare(attribute,"kerning") == 0)
12964 {
12965 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12966 draw_info->kerning=geometry_info.rho;
12967 break;
12968 }
12969 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12970 attribute);
12971 break;
12972 }
12973 case 'p':
12974 case 'P':
12975 {
12976 if (LocaleCompare(attribute,"pointsize") == 0)
12977 {
12978 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12979 draw_info->pointsize=geometry_info.rho;
12980 break;
12981 }
12982 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12983 attribute);
12984 break;
12985 }
12986 case 'r':
12987 case 'R':
12988 {
12989 if (LocaleCompare(attribute,"rotate") == 0)
12990 {
12991 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12992 affine.rx=geometry_info.rho;
12993 affine.ry=geometry_info.sigma;
12994 if ((flags & SigmaValue) == 0)
12995 affine.ry=affine.rx;
12996 break;
12997 }
12998 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12999 attribute);
13000 break;
13001 }
13002 case 's':
13003 case 'S':
13004 {
13005 if (LocaleCompare(attribute,"scale") == 0)
13006 {
13007 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13008 affine.sx=geometry_info.rho;
13009 affine.sy=geometry_info.sigma;
13010 if ((flags & SigmaValue) == 0)
13011 affine.sy=affine.sx;
13012 break;
13013 }
13014 if (LocaleCompare(attribute,"skew") == 0)
13015 {
13016 double
13017 x_angle,
13018 y_angle;
13019
13020 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13021 x_angle=geometry_info.rho;
13022 y_angle=geometry_info.sigma;
13023 if ((flags & SigmaValue) == 0)
13024 y_angle=x_angle;
13025 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13026 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13027 break;
13028 }
13029 if (LocaleCompare(attribute,"stroke") == 0)
13030 {
13031 if (info)
13032 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13033 &draw_info->stroke,exception);
13034 break;
13035 }
13036 if (LocaleCompare(attribute,"style") == 0)
13037 {
13038 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13039 SvPV(ST(i),na));
13040 if (type < 0)
13041 {
13042 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13043 SvPV(ST(i),na));
13044 break;
13045 }
13046 draw_info->style=(StyleType) type;
13047 break;
13048 }
13049 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13050 attribute);
13051 break;
13052 }
13053 case 't':
13054 case 'T':
13055 {
13056 if (LocaleCompare(attribute,"text") == 0)
13057 {
13058 CloneString(&draw_info->text,SvPV(ST(i),na));
13059 break;
13060 }
13061 if (LocaleCompare(attribute,"translate") == 0)
13062 {
13063 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13064 affine.tx=geometry_info.rho;
13065 affine.ty=geometry_info.sigma;
13066 if ((flags & SigmaValue) == 0)
13067 affine.ty=affine.tx;
13068 break;
13069 }
13070 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13071 attribute);
13072 break;
13073 }
13074 case 'w':
13075 case 'W':
13076 {
13077 if (LocaleCompare(attribute,"weight") == 0)
13078 {
13079 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13080 draw_info->weight=(size_t) geometry_info.rho;
13081 break;
13082 }
13083 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13084 attribute);
13085 break;
13086 }
13087 case 'x':
13088 case 'X':
13089 {
13090 if (LocaleCompare(attribute,"x") == 0)
13091 {
13092 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13093 x=geometry_info.rho;
13094 break;
13095 }
13096 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13097 attribute);
13098 break;
13099 }
13100 case 'y':
13101 case 'Y':
13102 {
13103 if (LocaleCompare(attribute,"y") == 0)
13104 {
13105 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13106 y=geometry_info.rho;
13107 break;
13108 }
13109 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13110 attribute);
13111 break;
13112 }
13113 default:
13114 {
13115 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13116 attribute);
13117 break;
13118 }
13119 }
13120 }
13121 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13122 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13123 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13124 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13125 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13126 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13127 if (draw_info->geometry == (char *) NULL)
13128 {
13129 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013130 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013131 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013132 }
13133 status=GetTypeMetrics(image,draw_info,&metrics,exception);
13134 (void) CatchImageException(image);
13135 if (status == MagickFalse)
13136 PUSHs(&sv_undef);
13137 else
13138 {
13139 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13140 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13141 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13142 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13143 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13144 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13145 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13146 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13147 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13148 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13149 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13150 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13151 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13152 }
13153 draw_info=DestroyDrawInfo(draw_info);
13154
13155 PerlException:
13156 if (package_info != (struct PackageInfo *) NULL)
13157 DestroyPackageInfo(package_info);
13158 InheritPerlException(exception,perl_exception);
13159 exception=DestroyExceptionInfo(exception);
13160 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13161 }
13162
13163#
13164###############################################################################
13165# #
13166# #
13167# #
13168# 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 #
13169# #
13170# #
13171# #
13172###############################################################################
13173#
13174#
13175void
13176QueryMultilineFontMetrics(ref,...)
13177 Image::Magick ref=NO_INIT
13178 ALIAS:
13179 querymultilinefontmetrics = 1
13180 PPCODE:
13181 {
13182 AffineMatrix
13183 affine,
13184 current;
13185
13186 AV
13187 *av;
13188
13189 char
13190 *attribute;
13191
13192 double
13193 x,
13194 y;
13195
13196 DrawInfo
13197 *draw_info;
13198
13199 ExceptionInfo
13200 *exception;
13201
13202 GeometryInfo
13203 geometry_info;
13204
13205 Image
13206 *image;
13207
13208 MagickBooleanType
13209 status;
13210
13211 MagickStatusType
13212 flags;
13213
13214 register ssize_t
13215 i;
13216
13217 ssize_t
13218 type;
13219
13220 struct PackageInfo
13221 *info,
13222 *package_info;
13223
13224 SV
13225 *perl_exception,
13226 *reference; /* reference is the SV* of ref=SvIV(reference) */
13227
13228 TypeMetric
13229 metrics;
13230
13231 PERL_UNUSED_VAR(ref);
13232 PERL_UNUSED_VAR(ix);
13233 exception=AcquireExceptionInfo();
13234 package_info=(struct PackageInfo *) NULL;
13235 perl_exception=newSVpv("",0);
13236 reference=SvRV(ST(0));
13237 av=(AV *) reference;
13238 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13239 exception);
13240 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13241 if (image == (Image *) NULL)
13242 {
13243 ThrowPerlException(exception,OptionError,"NoImagesDefined",
13244 PackageName);
13245 goto PerlException;
13246 }
13247 package_info=ClonePackageInfo(info,exception);
13248 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13249 CloneString(&draw_info->text,"");
13250 current=draw_info->affine;
13251 GetAffineMatrix(&affine);
13252 x=0.0;
13253 y=0.0;
13254 EXTEND(sp,7*items);
13255 for (i=2; i < items; i+=2)
13256 {
13257 attribute=(char *) SvPV(ST(i-1),na);
13258 switch (*attribute)
13259 {
13260 case 'A':
13261 case 'a':
13262 {
13263 if (LocaleCompare(attribute,"antialias") == 0)
13264 {
13265 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13266 SvPV(ST(i),na));
13267 if (type < 0)
13268 {
13269 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13270 SvPV(ST(i),na));
13271 break;
13272 }
13273 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13274 break;
13275 }
13276 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13277 attribute);
13278 break;
13279 }
13280 case 'd':
13281 case 'D':
13282 {
13283 if (LocaleCompare(attribute,"density") == 0)
13284 {
13285 CloneString(&draw_info->density,SvPV(ST(i),na));
13286 break;
13287 }
13288 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13289 attribute);
13290 break;
13291 }
13292 case 'e':
13293 case 'E':
13294 {
13295 if (LocaleCompare(attribute,"encoding") == 0)
13296 {
13297 CloneString(&draw_info->encoding,SvPV(ST(i),na));
13298 break;
13299 }
13300 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13301 attribute);
13302 break;
13303 }
13304 case 'f':
13305 case 'F':
13306 {
13307 if (LocaleCompare(attribute,"family") == 0)
13308 {
13309 CloneString(&draw_info->family,SvPV(ST(i),na));
13310 break;
13311 }
13312 if (LocaleCompare(attribute,"fill") == 0)
13313 {
13314 if (info)
13315 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13316 &draw_info->fill,exception);
13317 break;
13318 }
13319 if (LocaleCompare(attribute,"font") == 0)
13320 {
13321 CloneString(&draw_info->font,SvPV(ST(i),na));
13322 break;
13323 }
13324 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13325 attribute);
13326 break;
13327 }
13328 case 'g':
13329 case 'G':
13330 {
13331 if (LocaleCompare(attribute,"geometry") == 0)
13332 {
13333 CloneString(&draw_info->geometry,SvPV(ST(i),na));
13334 break;
13335 }
13336 if (LocaleCompare(attribute,"gravity") == 0)
13337 {
13338 draw_info->gravity=(GravityType) ParseCommandOption(
13339 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13340 break;
13341 }
13342 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13343 attribute);
13344 break;
13345 }
13346 case 'p':
13347 case 'P':
13348 {
13349 if (LocaleCompare(attribute,"pointsize") == 0)
13350 {
13351 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13352 draw_info->pointsize=geometry_info.rho;
13353 break;
13354 }
13355 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13356 attribute);
13357 break;
13358 }
13359 case 'r':
13360 case 'R':
13361 {
13362 if (LocaleCompare(attribute,"rotate") == 0)
13363 {
13364 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13365 affine.rx=geometry_info.rho;
13366 affine.ry=geometry_info.sigma;
13367 if ((flags & SigmaValue) == 0)
13368 affine.ry=affine.rx;
13369 break;
13370 }
13371 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13372 attribute);
13373 break;
13374 }
13375 case 's':
13376 case 'S':
13377 {
13378 if (LocaleCompare(attribute,"scale") == 0)
13379 {
13380 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13381 affine.sx=geometry_info.rho;
13382 affine.sy=geometry_info.sigma;
13383 if ((flags & SigmaValue) == 0)
13384 affine.sy=affine.sx;
13385 break;
13386 }
13387 if (LocaleCompare(attribute,"skew") == 0)
13388 {
13389 double
13390 x_angle,
13391 y_angle;
13392
13393 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13394 x_angle=geometry_info.rho;
13395 y_angle=geometry_info.sigma;
13396 if ((flags & SigmaValue) == 0)
13397 y_angle=x_angle;
13398 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13399 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13400 break;
13401 }
13402 if (LocaleCompare(attribute,"stroke") == 0)
13403 {
13404 if (info)
13405 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13406 &draw_info->stroke,exception);
13407 break;
13408 }
13409 if (LocaleCompare(attribute,"style") == 0)
13410 {
13411 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13412 SvPV(ST(i),na));
13413 if (type < 0)
13414 {
13415 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13416 SvPV(ST(i),na));
13417 break;
13418 }
13419 draw_info->style=(StyleType) type;
13420 break;
13421 }
13422 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13423 attribute);
13424 break;
13425 }
13426 case 't':
13427 case 'T':
13428 {
13429 if (LocaleCompare(attribute,"text") == 0)
13430 {
13431 CloneString(&draw_info->text,SvPV(ST(i),na));
13432 break;
13433 }
13434 if (LocaleCompare(attribute,"translate") == 0)
13435 {
13436 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13437 affine.tx=geometry_info.rho;
13438 affine.ty=geometry_info.sigma;
13439 if ((flags & SigmaValue) == 0)
13440 affine.ty=affine.tx;
13441 break;
13442 }
13443 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13444 attribute);
13445 break;
13446 }
13447 case 'w':
13448 case 'W':
13449 {
13450 if (LocaleCompare(attribute,"weight") == 0)
13451 {
13452 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13453 draw_info->weight=(size_t) geometry_info.rho;
13454 break;
13455 }
13456 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13457 attribute);
13458 break;
13459 }
13460 case 'x':
13461 case 'X':
13462 {
13463 if (LocaleCompare(attribute,"x") == 0)
13464 {
13465 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13466 x=geometry_info.rho;
13467 break;
13468 }
13469 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13470 attribute);
13471 break;
13472 }
13473 case 'y':
13474 case 'Y':
13475 {
13476 if (LocaleCompare(attribute,"y") == 0)
13477 {
13478 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13479 y=geometry_info.rho;
13480 break;
13481 }
13482 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13483 attribute);
13484 break;
13485 }
13486 default:
13487 {
13488 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13489 attribute);
13490 break;
13491 }
13492 }
13493 }
13494 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13495 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13496 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13497 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13498 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13499 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13500 if (draw_info->geometry == (char *) NULL)
13501 {
13502 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013503 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013504 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013505 }
13506 status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13507 (void) CatchException(exception);
13508 if (status == MagickFalse)
13509 PUSHs(&sv_undef);
13510 else
13511 {
13512 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13513 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13514 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13515 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13516 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13517 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13518 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13519 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13520 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13521 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13522 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13523 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13524 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13525 }
13526 draw_info=DestroyDrawInfo(draw_info);
13527
13528 PerlException:
13529 if (package_info != (struct PackageInfo *) NULL)
13530 DestroyPackageInfo(package_info);
13531 InheritPerlException(exception,perl_exception);
13532 exception=DestroyExceptionInfo(exception);
13533 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13534 }
13535
13536#
13537###############################################################################
13538# #
13539# #
13540# #
13541# Q u e r y F o r m a t #
13542# #
13543# #
13544# #
13545###############################################################################
13546#
13547#
13548void
13549QueryFormat(ref,...)
13550 Image::Magick ref=NO_INIT
13551 ALIAS:
13552 queryformat = 1
13553 PPCODE:
13554 {
13555 char
13556 *name;
13557
13558 ExceptionInfo
13559 *exception;
13560
13561 register ssize_t
13562 i;
13563
13564 SV
13565 *perl_exception;
13566
13567 volatile const MagickInfo
13568 *magick_info;
13569
13570 PERL_UNUSED_VAR(ref);
13571 PERL_UNUSED_VAR(ix);
13572 exception=AcquireExceptionInfo();
13573 perl_exception=newSVpv("",0);
13574 if (items == 1)
13575 {
13576 char
cristy151b66d2015-04-15 10:50:31 +000013577 format[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000013578
13579 const MagickInfo
13580 **format_list;
13581
13582 size_t
13583 types;
13584
13585 format_list=GetMagickInfoList("*",&types,exception);
13586 EXTEND(sp,types);
13587 for (i=0; i < (ssize_t) types; i++)
13588 {
cristy151b66d2015-04-15 10:50:31 +000013589 (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000013590 LocaleLower(format);
13591 PUSHs(sv_2mortal(newSVpv(format,0)));
13592 }
13593 format_list=(const MagickInfo **)
13594 RelinquishMagickMemory((MagickInfo *) format_list);
13595 goto PerlException;
13596 }
13597 EXTEND(sp,8*items);
13598 for (i=1; i < items; i++)
13599 {
13600 name=(char *) SvPV(ST(i),na);
13601 magick_info=GetMagickInfo(name,exception);
13602 if (magick_info == (const MagickInfo *) NULL)
13603 {
13604 PUSHs(&sv_undef);
13605 continue;
13606 }
cristy4a3ce0a2013-08-03 20:06:59 +000013607 if (magick_info->description == (char *) NULL)
13608 PUSHs(&sv_undef);
13609 else
13610 PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13611 if (magick_info->module == (char *) NULL)
13612 PUSHs(&sv_undef);
13613 else
13614 PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13615 }
13616
13617 PerlException:
13618 InheritPerlException(exception,perl_exception);
13619 exception=DestroyExceptionInfo(exception);
13620 SvREFCNT_dec(perl_exception);
13621 }
13622
13623#
13624###############################################################################
13625# #
13626# #
13627# #
13628# Q u e r y O p t i o n #
13629# #
13630# #
13631# #
13632###############################################################################
13633#
13634#
13635void
13636QueryOption(ref,...)
13637 Image::Magick ref=NO_INIT
13638 ALIAS:
13639 queryoption = 1
13640 PPCODE:
13641 {
13642 char
13643 **options;
13644
13645 ExceptionInfo
13646 *exception;
13647
13648 register ssize_t
13649 i;
13650
13651 ssize_t
13652 j,
13653 option;
13654
13655 SV
13656 *perl_exception;
13657
13658 PERL_UNUSED_VAR(ref);
13659 PERL_UNUSED_VAR(ix);
13660 exception=AcquireExceptionInfo();
13661 perl_exception=newSVpv("",0);
13662 EXTEND(sp,8*items);
13663 for (i=1; i < items; i++)
13664 {
13665 option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13666 SvPV(ST(i),na));
13667 options=GetCommandOptions((CommandOption) option);
13668 if (options == (char **) NULL)
13669 PUSHs(&sv_undef);
13670 else
13671 {
13672 for (j=0; options[j] != (char *) NULL; j++)
13673 PUSHs(sv_2mortal(newSVpv(options[j],0)));
13674 options=DestroyStringList(options);
13675 }
13676 }
13677
13678 InheritPerlException(exception,perl_exception);
13679 exception=DestroyExceptionInfo(exception);
13680 SvREFCNT_dec(perl_exception);
13681 }
13682
13683#
13684###############################################################################
13685# #
13686# #
13687# #
13688# R e a d #
13689# #
13690# #
13691# #
13692###############################################################################
13693#
13694#
13695void
13696Read(ref,...)
13697 Image::Magick ref=NO_INIT
13698 ALIAS:
13699 ReadImage = 1
13700 read = 2
13701 readimage = 3
13702 PPCODE:
13703 {
13704 AV
13705 *av;
13706
13707 char
13708 **keep,
13709 **list;
13710
13711 ExceptionInfo
13712 *exception;
13713
13714 HV
13715 *hv;
13716
13717 Image
13718 *image;
13719
13720 int
13721 n;
13722
13723 MagickBooleanType
13724 status;
13725
13726 register char
13727 **p;
13728
13729 register ssize_t
13730 i;
13731
13732 ssize_t
13733 ac,
13734 number_images;
13735
13736 STRLEN
13737 *length;
13738
13739 struct PackageInfo
13740 *info,
13741 *package_info;
13742
13743 SV
13744 *perl_exception, /* Perl variable for storing messages */
13745 *reference,
13746 *rv,
13747 *sv;
13748
13749 PERL_UNUSED_VAR(ref);
13750 PERL_UNUSED_VAR(ix);
13751 exception=AcquireExceptionInfo();
13752 perl_exception=newSVpv("",0);
13753 sv=NULL;
13754 package_info=(struct PackageInfo *) NULL;
13755 number_images=0;
13756 ac=(items < 2) ? 1 : items-1;
13757 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13758 keep=list;
13759 length=(STRLEN *) NULL;
13760 if (list == (char **) NULL)
13761 {
13762 ThrowPerlException(exception,ResourceLimitError,
13763 "MemoryAllocationFailed",PackageName);
13764 goto PerlException;
13765 }
13766 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13767 if (length == (STRLEN *) NULL)
13768 {
13769 ThrowPerlException(exception,ResourceLimitError,
13770 "MemoryAllocationFailed",PackageName);
13771 goto PerlException;
13772 }
13773 if (sv_isobject(ST(0)) == 0)
13774 {
13775 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13776 PackageName);
13777 goto PerlException;
13778 }
13779 reference=SvRV(ST(0));
13780 hv=SvSTASH(reference);
13781 if (SvTYPE(reference) != SVt_PVAV)
13782 {
13783 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13784 PackageName);
13785 goto PerlException;
13786 }
13787 av=(AV *) reference;
13788 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13789 exception);
13790 package_info=ClonePackageInfo(info,exception);
13791 n=1;
13792 if (items <= 1)
13793 *list=(char *) (*package_info->image_info->filename ?
13794 package_info->image_info->filename : "XC:black");
13795 else
13796 for (n=0, i=0; i < ac; i++)
13797 {
13798 list[n]=(char *) SvPV(ST(i+1),length[n]);
13799 if ((items >= 3) && strEQcase(list[n],"blob"))
13800 {
13801 void
13802 *blob;
13803
13804 i++;
13805 blob=(void *) (SvPV(ST(i+1),length[n]));
13806 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13807 }
13808 if ((items >= 3) && strEQcase(list[n],"filename"))
13809 continue;
13810 if ((items >= 3) && strEQcase(list[n],"file"))
13811 {
13812 FILE
13813 *file;
13814
13815 PerlIO
13816 *io_info;
13817
13818 i++;
13819 io_info=IoIFP(sv_2io(ST(i+1)));
13820 if (io_info == (PerlIO *) NULL)
13821 {
13822 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13823 PackageName);
13824 continue;
13825 }
13826 file=PerlIO_findFILE(io_info);
13827 if (file == (FILE *) NULL)
13828 {
13829 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13830 PackageName);
13831 continue;
13832 }
13833 SetImageInfoFile(package_info->image_info,file);
13834 }
13835 if ((items >= 3) && strEQcase(list[n],"magick"))
13836 continue;
13837 n++;
13838 }
13839 list[n]=(char *) NULL;
13840 keep=list;
13841 status=ExpandFilenames(&n,&list);
13842 if (status == MagickFalse)
13843 {
13844 ThrowPerlException(exception,ResourceLimitError,
13845 "MemoryAllocationFailed",PackageName);
13846 goto PerlException;
13847 }
13848 number_images=0;
13849 for (i=0; i < n; i++)
13850 {
13851 if ((package_info->image_info->file == (FILE *) NULL) &&
13852 (package_info->image_info->blob == (void *) NULL))
13853 image=ReadImages(package_info->image_info,list[i],exception);
13854 else
13855 {
13856 image=ReadImages(package_info->image_info,
13857 package_info->image_info->filename,exception);
13858 if (image != (Image *) NULL)
13859 DisassociateImageStream(image);
13860 }
13861 if (image == (Image *) NULL)
13862 break;
13863 for ( ; image; image=image->next)
13864 {
13865 AddImageToRegistry(sv,image);
13866 rv=newRV(sv);
13867 av_push(av,sv_bless(rv,hv));
13868 SvREFCNT_dec(sv);
13869 number_images++;
13870 }
13871 }
13872 /*
13873 Free resources.
13874 */
13875 for (i=0; i < n; i++)
13876 if (list[i] != (char *) NULL)
13877 for (p=keep; list[i] != *p++; )
13878 if (*p == (char *) NULL)
13879 {
13880 list[i]=(char *) RelinquishMagickMemory(list[i]);
13881 break;
13882 }
13883
13884 PerlException:
13885 if (package_info != (struct PackageInfo *) NULL)
13886 DestroyPackageInfo(package_info);
13887 if (list && (list != keep))
13888 list=(char **) RelinquishMagickMemory(list);
13889 if (keep)
13890 keep=(char **) RelinquishMagickMemory(keep);
13891 if (length)
13892 length=(STRLEN *) RelinquishMagickMemory(length);
13893 InheritPerlException(exception,perl_exception);
13894 exception=DestroyExceptionInfo(exception);
13895 sv_setiv(perl_exception,(IV) number_images);
13896 SvPOK_on(perl_exception);
13897 ST(0)=sv_2mortal(perl_exception);
13898 XSRETURN(1);
13899 }
13900
13901#
13902###############################################################################
13903# #
13904# #
13905# #
13906# R e m o t e #
13907# #
13908# #
13909# #
13910###############################################################################
13911#
13912#
13913void
13914Remote(ref,...)
13915 Image::Magick ref=NO_INIT
13916 ALIAS:
13917 RemoteCommand = 1
13918 remote = 2
13919 remoteCommand = 3
13920 PPCODE:
13921 {
13922 AV
13923 *av;
13924
13925 ExceptionInfo
13926 *exception;
13927
13928 register ssize_t
13929 i;
13930
13931 SV
13932 *perl_exception,
13933 *reference;
13934
13935 struct PackageInfo
13936 *info;
13937
13938 PERL_UNUSED_VAR(ref);
13939 PERL_UNUSED_VAR(ix);
13940 exception=AcquireExceptionInfo();
13941 perl_exception=newSVpv("",0);
13942 reference=SvRV(ST(0));
13943 av=(AV *) reference;
13944 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13945 exception);
13946 for (i=1; i < items; i++)
13947 (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13948 SvPV(ST(i),na),exception);
13949 InheritPerlException(exception,perl_exception);
13950 exception=DestroyExceptionInfo(exception);
13951 SvREFCNT_dec(perl_exception); /* throw away all errors */
13952 }
13953
13954#
13955###############################################################################
13956# #
13957# #
13958# #
13959# S e t #
13960# #
13961# #
13962# #
13963###############################################################################
13964#
13965#
13966void
13967Set(ref,...)
13968 Image::Magick ref=NO_INIT
13969 ALIAS:
13970 SetAttributes = 1
13971 SetAttribute = 2
13972 set = 3
13973 setattributes = 4
13974 setattribute = 5
13975 PPCODE:
13976 {
13977 ExceptionInfo
13978 *exception;
13979
13980 Image
13981 *image;
13982
13983 register ssize_t
13984 i;
13985
13986 struct PackageInfo
13987 *info;
13988
13989 SV
13990 *perl_exception,
13991 *reference; /* reference is the SV* of ref=SvIV(reference) */
13992
13993 PERL_UNUSED_VAR(ref);
13994 PERL_UNUSED_VAR(ix);
13995 exception=AcquireExceptionInfo();
13996 perl_exception=newSVpv("",0);
13997 if (sv_isobject(ST(0)) == 0)
13998 {
13999 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14000 PackageName);
14001 goto PerlException;
14002 }
14003 reference=SvRV(ST(0));
14004 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14005 if (items == 2)
14006 SetAttribute(aTHX_ info,image,"size",ST(1),exception);
14007 else
14008 for (i=2; i < items; i+=2)
14009 SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
14010
14011 PerlException:
14012 InheritPerlException(exception,perl_exception);
14013 exception=DestroyExceptionInfo(exception);
14014 sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
14015 SvPOK_on(perl_exception);
14016 ST(0)=sv_2mortal(perl_exception);
14017 XSRETURN(1);
14018 }
14019
14020#
14021###############################################################################
14022# #
14023# #
14024# #
14025# S e t P i x e l #
14026# #
14027# #
14028# #
14029###############################################################################
14030#
14031#
14032void
14033SetPixel(ref,...)
14034 Image::Magick ref=NO_INIT
14035 ALIAS:
14036 setpixel = 1
14037 setPixel = 2
14038 PPCODE:
14039 {
14040 AV
14041 *av;
14042
14043 char
14044 *attribute;
14045
14046 ChannelType
14047 channel,
14048 channel_mask;
14049
14050 ExceptionInfo
14051 *exception;
14052
14053 Image
14054 *image;
14055
14056 MagickBooleanType
14057 normalize;
14058
14059 RectangleInfo
14060 region;
14061
14062 register ssize_t
14063 i;
14064
14065 register Quantum
14066 *q;
14067
14068 ssize_t
14069 option;
14070
14071 struct PackageInfo
14072 *info;
14073
14074 SV
14075 *perl_exception,
14076 *reference; /* reference is the SV* of ref=SvIV(reference) */
14077
14078 PERL_UNUSED_VAR(ref);
14079 PERL_UNUSED_VAR(ix);
14080 exception=AcquireExceptionInfo();
14081 perl_exception=newSVpv("",0);
14082 reference=SvRV(ST(0));
14083 av=(AV *) reference;
14084 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14085 exception);
14086 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14087 if (image == (Image *) NULL)
14088 {
14089 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14090 PackageName);
14091 goto PerlException;
14092 }
14093 av=(AV *) NULL;
14094 normalize=MagickTrue;
14095 region.x=0;
14096 region.y=0;
14097 region.width=image->columns;
14098 region.height=1;
14099 if (items == 1)
14100 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14101 channel=DefaultChannels;
14102 for (i=2; i < items; i+=2)
14103 {
14104 attribute=(char *) SvPV(ST(i-1),na);
14105 switch (*attribute)
14106 {
14107 case 'C':
14108 case 'c':
14109 {
14110 if (LocaleCompare(attribute,"channel") == 0)
14111 {
14112 ssize_t
14113 option;
14114
14115 option=ParseChannelOption(SvPV(ST(i),na));
14116 if (option < 0)
14117 {
14118 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14119 SvPV(ST(i),na));
14120 return;
14121 }
14122 channel=(ChannelType) option;
14123 break;
14124 }
14125 if (LocaleCompare(attribute,"color") == 0)
14126 {
14127 if (SvTYPE(ST(i)) != SVt_RV)
14128 {
14129 char
cristy151b66d2015-04-15 10:50:31 +000014130 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014131
cristy151b66d2015-04-15 10:50:31 +000014132 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +000014133 "invalid %.60s value",attribute);
14134 ThrowPerlException(exception,OptionError,message,
14135 SvPV(ST(i),na));
14136 }
14137 av=(AV *) SvRV(ST(i));
14138 break;
14139 }
14140 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14141 attribute);
14142 break;
14143 }
14144 case 'g':
14145 case 'G':
14146 {
14147 if (LocaleCompare(attribute,"geometry") == 0)
14148 {
14149 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14150 break;
14151 }
14152 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14153 attribute);
14154 break;
14155 }
14156 case 'N':
14157 case 'n':
14158 {
14159 if (LocaleCompare(attribute,"normalize") == 0)
14160 {
14161 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14162 SvPV(ST(i),na));
14163 if (option < 0)
14164 {
14165 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14166 SvPV(ST(i),na));
14167 break;
14168 }
14169 normalize=option != 0 ? MagickTrue : MagickFalse;
14170 break;
14171 }
14172 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14173 attribute);
14174 break;
14175 }
14176 case 'x':
14177 case 'X':
14178 {
14179 if (LocaleCompare(attribute,"x") == 0)
14180 {
14181 region.x=SvIV(ST(i));
14182 break;
14183 }
14184 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14185 attribute);
14186 break;
14187 }
14188 case 'y':
14189 case 'Y':
14190 {
14191 if (LocaleCompare(attribute,"y") == 0)
14192 {
14193 region.y=SvIV(ST(i));
14194 break;
14195 }
14196 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14197 attribute);
14198 break;
14199 }
14200 default:
14201 {
14202 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14203 attribute);
14204 break;
14205 }
14206 }
14207 }
14208 (void) SetImageStorageClass(image,DirectClass,exception);
14209 channel_mask=SetImageChannelMask(image,channel);
14210 q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14211 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14212 (SvTYPE(av) != SVt_PVAV))
14213 PUSHs(&sv_undef);
14214 else
14215 {
14216 double
14217 scale;
14218
14219 register ssize_t
14220 i;
14221
14222 i=0;
14223 scale=1.0;
14224 if (normalize != MagickFalse)
14225 scale=QuantumRange;
14226 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14227 (i <= av_len(av)))
14228 {
14229 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14230 av_fetch(av,i,0)))),q);
14231 i++;
14232 }
14233 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14234 (i <= av_len(av)))
14235 {
14236 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14237 av_fetch(av,i,0)))),q);
14238 i++;
14239 }
14240 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14241 (i <= av_len(av)))
14242 {
14243 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14244 av_fetch(av,i,0)))),q);
14245 i++;
14246 }
14247 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14248 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14249 {
14250 SetPixelBlack(image,ClampToQuantum(scale*
14251 SvNV(*(av_fetch(av,i,0)))),q);
14252 i++;
14253 }
14254 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14255 (i <= av_len(av)))
14256 {
14257 SetPixelAlpha(image,ClampToQuantum(scale*
14258 SvNV(*(av_fetch(av,i,0)))),q);
14259 i++;
14260 }
14261 (void) SyncAuthenticPixels(image,exception);
14262 }
14263 (void) SetImageChannelMask(image,channel_mask);
14264
14265 PerlException:
14266 InheritPerlException(exception,perl_exception);
14267 exception=DestroyExceptionInfo(exception);
14268 SvREFCNT_dec(perl_exception);
14269 }
14270
14271#
14272###############################################################################
14273# #
14274# #
14275# #
Cristybba545b2018-07-04 15:00:12 -040014276# S e t P i x e l s #
14277# #
14278# #
14279# #
14280###############################################################################
14281#
14282#
14283void
14284SetPixels(ref,...)
14285 Image::Magick ref=NO_INIT
14286 ALIAS:
14287 setpixels = 1
14288 setPixels = 2
14289 PPCODE:
14290 {
14291 AV
14292 *av;
14293
14294 char
14295 *attribute;
14296
14297 ChannelType
14298 channel,
14299 channel_mask;
14300
14301 ExceptionInfo
14302 *exception;
14303
14304 Image
14305 *image;
14306
14307 RectangleInfo
14308 region;
14309
14310 register ssize_t
14311 i;
14312
14313 register Quantum
14314 *q;
14315
14316 struct PackageInfo
14317 *info;
14318
14319 SV
14320 *perl_exception,
14321 *reference; /* reference is the SV* of ref=SvIV(reference) */
14322
14323 PERL_UNUSED_VAR(ref);
14324 PERL_UNUSED_VAR(ix);
14325 exception=AcquireExceptionInfo();
14326 perl_exception=newSVpv("",0);
14327 reference=SvRV(ST(0));
14328 av=(AV *) reference;
14329 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14330 exception);
14331 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14332 if (image == (Image *) NULL)
14333 {
14334 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14335 PackageName);
14336 goto PerlException;
14337 }
14338 av=(AV *) NULL;
14339 region.x=0;
14340 region.y=0;
14341 region.width=image->columns;
14342 region.height=1;
14343 if (items == 1)
14344 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14345 channel=DefaultChannels;
14346 for (i=2; i < items; i+=2)
14347 {
14348 attribute=(char *) SvPV(ST(i-1),na);
14349 switch (*attribute)
14350 {
14351 case 'C':
14352 case 'c':
14353 {
14354 if (LocaleCompare(attribute,"channel") == 0)
14355 {
14356 ssize_t
14357 option;
14358
14359 option=ParseChannelOption(SvPV(ST(i),na));
14360 if (option < 0)
14361 {
14362 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14363 SvPV(ST(i),na));
14364 return;
14365 }
14366 channel=(ChannelType) option;
14367 break;
14368 }
14369 if (LocaleCompare(attribute,"color") == 0)
14370 {
14371 if (SvTYPE(ST(i)) != SVt_RV)
14372 {
14373 char
14374 message[MagickPathExtent];
14375
14376 (void) FormatLocaleString(message,MagickPathExtent,
14377 "invalid %.60s value",attribute);
14378 ThrowPerlException(exception,OptionError,message,
14379 SvPV(ST(i),na));
14380 }
14381 av=(AV *) SvRV(ST(i));
14382 break;
14383 }
14384 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14385 attribute);
14386 break;
14387 }
14388 case 'g':
14389 case 'G':
14390 {
14391 if (LocaleCompare(attribute,"geometry") == 0)
14392 {
14393 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14394 break;
14395 }
14396 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14397 attribute);
14398 break;
14399 }
14400 case 'h':
14401 case 'H':
14402 {
14403 if (LocaleCompare(attribute,"height") == 0)
14404 {
14405 region.height=SvIV(ST(i));
14406 break;
14407 }
14408 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14409 attribute);
14410 break;
14411 }
14412 case 'w':
14413 case 'W':
14414 {
14415 if (LocaleCompare(attribute,"width") == 0)
14416 {
14417 region.width=SvIV(ST(i));
14418 break;
14419 }
14420 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14421 attribute);
14422 break;
14423 }
14424 case 'x':
14425 case 'X':
14426 {
14427 if (LocaleCompare(attribute,"x") == 0)
14428 {
14429 region.x=SvIV(ST(i));
14430 break;
14431 }
14432 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14433 attribute);
14434 break;
14435 }
14436 case 'y':
14437 case 'Y':
14438 {
14439 if (LocaleCompare(attribute,"y") == 0)
14440 {
14441 region.y=SvIV(ST(i));
14442 break;
14443 }
14444 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14445 attribute);
14446 break;
14447 }
14448 default:
14449 {
14450 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14451 attribute);
14452 break;
14453 }
14454 }
14455 }
14456 (void) SetImageStorageClass(image,DirectClass,exception);
14457 channel_mask=SetImageChannelMask(image,channel);
14458 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
14459 exception);
14460 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14461 (SvTYPE(av) != SVt_PVAV))
14462 PUSHs(&sv_undef);
14463 else
14464 {
14465 double
14466 scale;
14467
14468 register ssize_t
14469 i,
14470 n,
14471 number_pixels;
14472
14473 i=0;
14474 n=0;
14475 scale=(double) QuantumRange;
14476 number_pixels=region.width*region.height;
14477 while ((n < number_pixels) && (i < av_len(av)))
14478 {
14479 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14480 (i <= av_len(av)))
14481 {
14482 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14483 av_fetch(av,i,0)))),q);
14484 i++;
14485 }
14486 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14487 (i <= av_len(av)))
14488 {
14489 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14490 av_fetch(av,i,0)))),q);
14491 i++;
14492 }
14493 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14494 (i <= av_len(av)))
14495 {
14496 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14497 av_fetch(av,i,0)))),q);
14498 i++;
14499 }
14500 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14501 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14502 {
14503 SetPixelBlack(image,ClampToQuantum(scale*
14504 SvNV(*(av_fetch(av,i,0)))),q);
14505 i++;
14506 }
14507 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14508 (i <= av_len(av)))
14509 {
14510 SetPixelAlpha(image,ClampToQuantum(scale*
14511 SvNV(*(av_fetch(av,i,0)))),q);
14512 i++;
14513 }
14514 n++;
14515 q+=image->number_channels;
14516 }
14517 (void) SyncAuthenticPixels(image,exception);
14518 }
14519 (void) SetImageChannelMask(image,channel_mask);
14520
14521 PerlException:
14522 InheritPerlException(exception,perl_exception);
14523 exception=DestroyExceptionInfo(exception);
14524 SvREFCNT_dec(perl_exception);
14525 }
14526
14527#
14528###############################################################################
14529# #
14530# #
14531# #
cristy4a3ce0a2013-08-03 20:06:59 +000014532# S m u s h #
14533# #
14534# #
14535# #
14536###############################################################################
14537#
14538#
14539void
14540Smush(ref,...)
14541 Image::Magick ref=NO_INIT
14542 ALIAS:
14543 SmushImage = 1
14544 smush = 2
14545 smushimage = 3
14546 PPCODE:
14547 {
14548 AV
14549 *av;
14550
14551 char
14552 *attribute;
14553
14554 ExceptionInfo
14555 *exception;
14556
14557 HV
14558 *hv;
14559
14560 Image
14561 *image;
14562
14563 register ssize_t
14564 i;
14565
14566 ssize_t
14567 offset,
14568 stack;
14569
14570 struct PackageInfo
14571 *info;
14572
14573 SV
14574 *av_reference,
14575 *perl_exception,
14576 *reference,
14577 *rv,
14578 *sv;
14579
14580 PERL_UNUSED_VAR(ref);
14581 PERL_UNUSED_VAR(ix);
14582 exception=AcquireExceptionInfo();
14583 perl_exception=newSVpv("",0);
14584 sv=NULL;
14585 attribute=NULL;
14586 av=NULL;
14587 if (sv_isobject(ST(0)) == 0)
14588 {
14589 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14590 PackageName);
14591 goto PerlException;
14592 }
14593 reference=SvRV(ST(0));
14594 hv=SvSTASH(reference);
14595 av=newAV();
14596 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14597 SvREFCNT_dec(av);
14598 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14599 if (image == (Image *) NULL)
14600 {
14601 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14602 PackageName);
14603 goto PerlException;
14604 }
14605 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14606 /*
14607 Get options.
14608 */
14609 offset=0;
14610 stack=MagickTrue;
14611 for (i=2; i < items; i+=2)
14612 {
14613 attribute=(char *) SvPV(ST(i-1),na);
14614 switch (*attribute)
14615 {
14616 case 'O':
14617 case 'o':
14618 {
14619 if (LocaleCompare(attribute,"offset") == 0)
14620 {
14621 offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14622 break;
14623 }
14624 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14625 attribute);
14626 break;
14627 }
14628 case 'S':
14629 case 's':
14630 {
14631 if (LocaleCompare(attribute,"stack") == 0)
14632 {
14633 stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14634 SvPV(ST(i),na));
14635 if (stack < 0)
14636 {
14637 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14638 SvPV(ST(i),na));
14639 return;
14640 }
14641 break;
14642 }
14643 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14644 attribute);
14645 break;
14646 }
14647 default:
14648 {
14649 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14650 attribute);
14651 break;
14652 }
14653 }
14654 }
14655 image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14656 exception);
14657 if (image == (Image *) NULL)
14658 goto PerlException;
14659 for ( ; image; image=image->next)
14660 {
14661 AddImageToRegistry(sv,image);
14662 rv=newRV(sv);
14663 av_push(av,sv_bless(rv,hv));
14664 SvREFCNT_dec(sv);
14665 }
14666 exception=DestroyExceptionInfo(exception);
14667 ST(0)=av_reference;
14668 SvREFCNT_dec(perl_exception);
14669 XSRETURN(1);
14670
14671 PerlException:
14672 InheritPerlException(exception,perl_exception);
14673 exception=DestroyExceptionInfo(exception);
14674 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14675 SvPOK_on(perl_exception);
14676 ST(0)=sv_2mortal(perl_exception);
14677 XSRETURN(1);
14678 }
14679
14680#
14681###############################################################################
14682# #
14683# #
14684# #
14685# S t a t i s t i c s #
14686# #
14687# #
14688# #
14689###############################################################################
14690#
14691#
14692void
14693Statistics(ref,...)
14694 Image::Magick ref=NO_INIT
14695 ALIAS:
14696 StatisticsImage = 1
14697 statistics = 2
14698 statisticsimage = 3
14699 PPCODE:
14700 {
14701#define ChannelStatistics(channel) \
14702{ \
cristy151b66d2015-04-15 10:50:31 +000014703 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014704 (double) channel_statistics[channel].depth); \
14705 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014706 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014707 channel_statistics[channel].minima/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014708 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014709 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014710 channel_statistics[channel].maxima/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014711 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014712 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014713 channel_statistics[channel].mean/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014714 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014715 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014716 channel_statistics[channel].standard_deviation/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014717 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014718 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014719 channel_statistics[channel].kurtosis); \
14720 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014721 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014722 channel_statistics[channel].skewness); \
14723 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014724 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy275bdd92014-11-08 23:45:03 +000014725 channel_statistics[channel].entropy); \
14726 PUSHs(sv_2mortal(newSVpv(message,0))); \
cristy4a3ce0a2013-08-03 20:06:59 +000014727}
14728
14729 AV
14730 *av;
14731
14732 char
cristy151b66d2015-04-15 10:50:31 +000014733 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014734
14735 ChannelStatistics
14736 *channel_statistics;
14737
cristy4a3ce0a2013-08-03 20:06:59 +000014738 ExceptionInfo
14739 *exception;
14740
14741 Image
14742 *image;
14743
14744 ssize_t
14745 count;
14746
14747 struct PackageInfo
14748 *info;
14749
14750 SV
14751 *perl_exception,
14752 *reference;
14753
14754 PERL_UNUSED_VAR(ref);
14755 PERL_UNUSED_VAR(ix);
14756 exception=AcquireExceptionInfo();
14757 perl_exception=newSVpv("",0);
14758 av=NULL;
14759 if (sv_isobject(ST(0)) == 0)
14760 {
14761 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14762 PackageName);
14763 goto PerlException;
14764 }
14765 reference=SvRV(ST(0));
14766 av=newAV();
14767 SvREFCNT_dec(av);
14768 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14769 if (image == (Image *) NULL)
14770 {
14771 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14772 PackageName);
14773 goto PerlException;
14774 }
cristy4a3ce0a2013-08-03 20:06:59 +000014775 count=0;
14776 for ( ; image; image=image->next)
14777 {
Cristyb1710fe2017-02-11 13:51:48 -050014778 register size_t
14779 i;
14780
cristy4a3ce0a2013-08-03 20:06:59 +000014781 channel_statistics=GetImageStatistics(image,exception);
14782 if (channel_statistics == (ChannelStatistics *) NULL)
14783 continue;
14784 count++;
Cristyb1710fe2017-02-11 13:51:48 -050014785 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
14786 {
14787 PixelChannel channel=GetPixelChannelChannel(image,i);
14788 PixelTrait traits=GetPixelChannelTraits(image,channel);
Cristy5a854dc2017-02-11 15:43:46 -050014789 if (traits == UndefinedPixelTrait)
Cristyb1710fe2017-02-11 13:51:48 -050014790 continue;
Cristy5a854dc2017-02-11 15:43:46 -050014791 EXTEND(sp,8*(i+1)*count);
Cristyb1710fe2017-02-11 13:51:48 -050014792 ChannelStatistics(channel);
14793 }
Cristy25813902017-02-11 15:47:52 -050014794 EXTEND(sp,8*(i+1)*count);
14795 ChannelStatistics(CompositePixelChannel);
cristy4a3ce0a2013-08-03 20:06:59 +000014796 channel_statistics=(ChannelStatistics *)
14797 RelinquishMagickMemory(channel_statistics);
14798 }
14799
14800 PerlException:
14801 InheritPerlException(exception,perl_exception);
14802 exception=DestroyExceptionInfo(exception);
14803 SvREFCNT_dec(perl_exception);
14804 }
14805
14806#
14807###############################################################################
14808# #
14809# #
14810# #
14811# S y n c A u t h e n t i c P i x e l s #
14812# #
14813# #
14814# #
14815###############################################################################
14816#
14817#
14818void
14819SyncAuthenticPixels(ref,...)
14820 Image::Magick ref = NO_INIT
14821 ALIAS:
14822 Syncauthenticpixels = 1
14823 SyncImagePixels = 2
14824 syncimagepixels = 3
14825 CODE:
14826 {
14827 ExceptionInfo
14828 *exception;
14829
14830 Image
14831 *image;
14832
14833 MagickBooleanType
14834 status;
14835
14836 struct PackageInfo
14837 *info;
14838
14839 SV
14840 *perl_exception,
14841 *reference;
14842
14843 PERL_UNUSED_VAR(ref);
14844 PERL_UNUSED_VAR(ix);
14845 exception=AcquireExceptionInfo();
14846 perl_exception=newSVpv("",0);
14847 if (sv_isobject(ST(0)) == 0)
14848 {
14849 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14850 PackageName);
14851 goto PerlException;
14852 }
14853
14854 reference=SvRV(ST(0));
14855 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14856 if (image == (Image *) NULL)
14857 {
14858 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14859 PackageName);
14860 goto PerlException;
14861 }
14862
14863 status=SyncAuthenticPixels(image,exception);
14864 if (status != MagickFalse)
14865 return;
14866
14867 PerlException:
14868 InheritPerlException(exception,perl_exception);
14869 exception=DestroyExceptionInfo(exception);
14870 SvREFCNT_dec(perl_exception); /* throw away all errors */
14871 }
14872
14873#
14874###############################################################################
14875# #
14876# #
14877# #
cristy4a3ce0a2013-08-03 20:06:59 +000014878# W r i t e #
14879# #
14880# #
14881# #
14882###############################################################################
14883#
14884#
14885void
14886Write(ref,...)
14887 Image::Magick ref=NO_INIT
14888 ALIAS:
14889 WriteImage = 1
14890 write = 2
14891 writeimage = 3
14892 PPCODE:
14893 {
14894 char
cristy151b66d2015-04-15 10:50:31 +000014895 filename[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014896
14897 ExceptionInfo
14898 *exception;
14899
14900 Image
14901 *image,
14902 *next;
14903
14904 register ssize_t
14905 i;
14906
14907 ssize_t
14908 number_images,
14909 scene;
14910
14911 struct PackageInfo
14912 *info,
14913 *package_info;
14914
14915 SV
14916 *perl_exception,
14917 *reference;
14918
14919 PERL_UNUSED_VAR(ref);
14920 PERL_UNUSED_VAR(ix);
14921 exception=AcquireExceptionInfo();
14922 perl_exception=newSVpv("",0);
14923 number_images=0;
14924 package_info=(struct PackageInfo *) NULL;
14925 if (sv_isobject(ST(0)) == 0)
14926 {
14927 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14928 PackageName);
14929 goto PerlException;
14930 }
14931 reference=SvRV(ST(0));
14932 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14933 if (image == (Image *) NULL)
14934 {
14935 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14936 PackageName);
14937 goto PerlException;
14938 }
Cristyb4ee45c2017-09-27 17:58:55 -040014939 scene=0;
14940 for (next=image; next; next=next->next)
14941 next->scene=scene++;
cristy4a3ce0a2013-08-03 20:06:59 +000014942 package_info=ClonePackageInfo(info,exception);
14943 if (items == 2)
14944 SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14945 else
14946 if (items > 2)
14947 for (i=2; i < items; i+=2)
14948 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14949 exception);
14950 (void) CopyMagickString(filename,package_info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +000014951 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000014952 for (next=image; next; next=next->next)
cristy151b66d2015-04-15 10:50:31 +000014953 (void) CopyMagickString(next->filename,filename,MagickPathExtent);
cristy68bd79a2015-02-25 12:23:36 +000014954 *package_info->image_info->magick='\0';
cristy4a3ce0a2013-08-03 20:06:59 +000014955 SetImageInfo(package_info->image_info,(unsigned int)
14956 GetImageListLength(image),exception);
14957 for (next=image; next; next=next->next)
14958 {
14959 (void) WriteImage(package_info->image_info,next,exception);
14960 number_images++;
14961 if (package_info->image_info->adjoin)
14962 break;
14963 }
14964
14965 PerlException:
14966 if (package_info != (struct PackageInfo *) NULL)
14967 DestroyPackageInfo(package_info);
14968 InheritPerlException(exception,perl_exception);
14969 exception=DestroyExceptionInfo(exception);
14970 sv_setiv(perl_exception,(IV) number_images);
14971 SvPOK_on(perl_exception);
14972 ST(0)=sv_2mortal(perl_exception);
14973 XSRETURN(1);
14974 }