blob: df75d25cd45d5e2ccd4ec7e967e1a228a406c080 [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% %
Cristyf775a5c2019-11-26 14:27:47 -050026% Copyright 1999-2020 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
Cristy3d1de822019-02-15 18:06:30 -050078#define MaxArguments 34
cristy4a3ce0a2013-08-03 20:06:59 +000079#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},
Cristy3d1de822019-02-15 18:06:30 -0500291 {"direction", MagickDirectionOptions},
292 {"decorate", MagickDecorateOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000293 { "ColorFloodfill", { {"geometry", StringReference},
294 {"x", IntegerReference}, {"y", IntegerReference},
295 {"fill", StringReference}, {"bordercolor", StringReference},
296 {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
297 { "Composite", { {"image", ImageReference},
298 {"compose", MagickComposeOptions}, {"geometry", StringReference},
299 {"x", IntegerReference}, {"y", IntegerReference},
300 {"gravity", MagickGravityOptions}, {"opacity", StringReference},
301 {"tile", MagickBooleanOptions}, {"rotate", RealReference},
302 {"color", StringReference}, {"mask", ImageReference},
303 {"channel", MagickChannelOptions},
304 {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
Cristy74e39292018-07-08 13:13:20 -0400305 {"blend", StringReference}, {"clip-to-self", MagickBooleanOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000306 { "Contrast", { {"sharpen", MagickBooleanOptions} } },
307 { "CycleColormap", { {"display", IntegerReference} } },
308 { "Draw", { {"primitive", MagickPrimitiveOptions},
309 {"points", StringReference}, {"method", MagickMethodOptions},
310 {"stroke", StringReference}, {"fill", StringReference},
311 {"strokewidth", RealReference}, {"font", StringReference},
312 {"bordercolor", StringReference}, {"x", RealReference},
313 {"y", RealReference}, {"translate", StringReference},
314 {"scale", StringReference}, {"rotate", RealReference},
315 {"skewX", RealReference}, {"skewY", RealReference},
316 {"tile", ImageReference}, {"pointsize", RealReference},
317 {"antialias", MagickBooleanOptions}, {"density", StringReference},
318 {"linewidth", RealReference}, {"affine", ArrayReference},
319 {"stroke-dashoffset", RealReference},
320 {"stroke-dasharray", ArrayReference},
321 {"interpolate", MagickInterpolateOptions},
322 {"origin", StringReference}, {"text", StringReference},
323 {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
324 {"vector-graphics", StringReference}, {"kerning", RealReference},
325 {"interline-spacing", RealReference},
326 {"interword-spacing", RealReference},
327 {"direction", MagickDirectionOptions} } },
328 { "Equalize", { {"channel", MagickChannelOptions} } },
329 { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
330 {"red", RealReference}, {"green", RealReference},
331 {"blue", RealReference} } },
332 { "Map", { {"image", ImageReference},
333 {"dither-method", MagickDitherOptions} } },
334 { "MatteFloodfill", { {"geometry", StringReference},
335 {"x", IntegerReference}, {"y", IntegerReference},
336 {"opacity", StringReference}, {"bordercolor", StringReference},
337 {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
338 { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
339 {"saturation", RealReference}, {"whiteness", RealReference},
340 {"brightness", RealReference}, {"lightness", RealReference},
341 {"blackness", RealReference} } },
342 { "Negate", { {"gray", MagickBooleanOptions},
343 {"channel", MagickChannelOptions} } },
344 { "Normalize", { {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500345 { "NumberColors", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000346 { "Opaque", { {"color", StringReference}, {"fill", StringReference},
347 {"fuzz", StringReference}, {"channel", MagickChannelOptions},
348 {"invert", MagickBooleanOptions} } },
349 { "Quantize", { {"colors", IntegerReference},
350 {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
351 {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
352 {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
353 {"dither-method", MagickDitherOptions} } },
354 { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
355 {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
356 { "Segment", { {"geometry", StringReference},
357 {"cluster-threshold", RealReference},
358 {"smoothing-threshold", RealReference},
359 {"colorspace", MagickColorspaceOptions},
360 {"verbose", MagickBooleanOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500361 { "Signature", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000362 { "Solarize", { {"geometry", StringReference},
363 {"threshold", StringReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500364 { "Sync", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000365 { "Texture", { {"texture", ImageReference} } },
366 { "Evaluate", { {"value", RealReference},
367 {"operator", MagickEvaluateOptions},
368 {"channel", MagickChannelOptions} } },
369 { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
370 {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
371 { "Threshold", { {"threshold", StringReference},
372 {"channel", MagickChannelOptions} } },
373 { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
374 {"sigma", RealReference} } },
375 { "Trim", { {"fuzz", StringReference} } },
376 { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
377 {"wavelength", RealReference},
378 {"interpolate", MagickInterpolateOptions} } },
379 { "Separate", { {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500380 { "Condense", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000381 { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
382 {"y", IntegerReference} } },
383 { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500384 { "Deconstruct", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000385 { "GaussianBlur", { {"geometry", StringReference},
386 {"radius", RealReference}, {"sigma", RealReference},
387 {"channel", MagickChannelOptions} } },
388 { "Convolve", { {"coefficients", ArrayReference},
389 {"channel", MagickChannelOptions}, {"bias", StringReference},
390 {"kernel", StringReference} } },
391 { "Profile", { {"name", StringReference}, {"profile", StringReference},
392 { "rendering-intent", MagickIntentOptions},
393 { "black-point-compensation", MagickBooleanOptions} } },
394 { "UnsharpMask", { {"geometry", StringReference},
395 {"radius", RealReference}, {"sigma", RealReference},
396 {"gain", RealReference}, {"threshold", RealReference},
397 {"channel", MagickChannelOptions} } },
398 { "MotionBlur", { {"geometry", StringReference},
399 {"radius", RealReference}, {"sigma", RealReference},
400 {"angle", RealReference}, {"channel", MagickChannelOptions} } },
401 { "OrderedDither", { {"threshold", StringReference},
402 {"channel", MagickChannelOptions} } },
403 { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
404 {"height", IntegerReference} } },
405 { "Level", { {"levels", StringReference}, {"black-point", RealReference},
406 {"white-point", RealReference}, {"gamma", RealReference},
407 {"channel", MagickChannelOptions}, {"level", StringReference} } },
408 { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
409 { "AffineTransform", { {"affine", ArrayReference},
410 {"translate", StringReference}, {"scale", StringReference},
411 {"rotate", RealReference}, {"skewX", RealReference},
412 {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
413 {"background", StringReference} } },
414 { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
415 { "AdaptiveThreshold", { {"geometry", StringReference},
Cristy9f252542018-11-21 19:13:46 -0500416 {"width", IntegerReference}, {"height", IntegerReference},
417 {"bias", RealReference} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000418 { "Resample", { {"density", StringReference}, {"x", RealReference},
419 {"y", RealReference}, {"filter", MagickFilterOptions},
420 {"support", RealReference } } },
421 { "Describe", { {"file", FileReference} } },
422 { "BlackThreshold", { {"threshold", StringReference},
423 {"channel", MagickChannelOptions} } },
424 { "WhiteThreshold", { {"threshold", StringReference},
425 {"channel", MagickChannelOptions} } },
cristy60c73c02014-03-25 12:09:58 +0000426 { "RotationalBlur", { {"geometry", StringReference},
427 {"angle", RealReference}, {"channel", MagickChannelOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000428 { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
429 {"height", IntegerReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500430 { "Strip", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000431 { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
432 { "Channel", { {"channel", MagickChannelOptions} } },
433 { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
434 {"height", IntegerReference}, {"x", IntegerReference},
435 {"y", IntegerReference}, {"fuzz", StringReference},
436 {"background", StringReference}, {"gravity", MagickGravityOptions} } },
437 { "Posterize", { {"levels", IntegerReference},
438 {"dither", MagickBooleanOptions} } },
439 { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
440 {"sigma", RealReference}, {"x", IntegerReference},
441 {"y", IntegerReference} } },
442 { "Identify", { {"file", FileReference}, {"features", StringReference},
Cristy8b3ffe62020-02-17 12:36:53 -0500443 {"moments", MagickBooleanOptions}, {"unique", MagickBooleanOptions} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000444 { "SepiaTone", { {"threshold", RealReference} } },
445 { "SigmoidalContrast", { {"geometry", StringReference},
446 {"contrast", RealReference}, {"mid-point", RealReference},
447 {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
448 { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
449 {"height", IntegerReference}, {"x", IntegerReference},
450 {"y", IntegerReference}, {"fuzz", StringReference},
451 {"background", StringReference}, {"gravity", MagickGravityOptions} } },
452 { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
453 {"sigma", RealReference}, {"x", IntegerReference},
454 {"y", IntegerReference}, {"background", StringReference} } },
455 { "ContrastStretch", { {"levels", StringReference},
456 {"black-point", RealReference},{"white-point", RealReference},
457 {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500458 { "Sans0", { { (const char *) NULL, NullReference } } },
459 { "Sans1", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000460 { "AdaptiveSharpen", { {"geometry", StringReference},
461 {"radius", RealReference}, {"sigma", RealReference},
462 {"bias", RealReference}, {"channel", MagickChannelOptions} } },
Cristy8cb2e452018-01-14 14:46:31 -0500463 { "Transpose", { { (const char *) NULL, NullReference } } },
464 { "Transverse", { { (const char *) NULL, NullReference } } },
465 { "AutoOrient", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000466 { "AdaptiveBlur", { {"geometry", StringReference},
467 {"radius", RealReference}, {"sigma", RealReference},
468 {"channel", MagickChannelOptions} } },
469 { "Sketch", { {"geometry", StringReference},
470 {"radius", RealReference}, {"sigma", RealReference},
471 {"angle", RealReference} } },
Cristy8cb2e452018-01-14 14:46:31 -0500472 { "UniqueColors", { { (const char *) NULL, NullReference } } },
cristy4a3ce0a2013-08-03 20:06:59 +0000473 { "AdaptiveResize", { {"geometry", StringReference},
474 {"width", IntegerReference}, {"height", IntegerReference},
475 {"filter", MagickFilterOptions}, {"support", StringReference },
476 {"blur", RealReference } } },
477 { "ClipMask", { {"mask", ImageReference} } },
478 { "LinearStretch", { {"levels", StringReference},
479 {"black-point", RealReference},{"white-point", RealReference} } },
480 { "ColorMatrix", { {"matrix", ArrayReference} } },
481 { "Mask", { {"mask", ImageReference} } },
482 { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
483 {"font", StringReference}, {"stroke", StringReference},
484 {"fill", StringReference}, {"strokewidth", RealReference},
485 {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
486 {"background", StringReference},
487 {"interpolate", MagickInterpolateOptions} } },
488 { "FloodfillPaint", { {"geometry", StringReference},
489 {"x", IntegerReference}, {"y", IntegerReference},
490 {"fill", StringReference}, {"bordercolor", StringReference},
491 {"fuzz", StringReference}, {"channel", MagickChannelOptions},
492 {"invert", MagickBooleanOptions} } },
493 { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
494 {"virtual-pixel", MagickVirtualPixelOptions},
495 {"best-fit", MagickBooleanOptions} } },
496 { "Clut", { {"image", ImageReference},
497 {"interpolate", MagickInterpolateOptions},
498 {"channel", MagickChannelOptions} } },
499 { "LiquidRescale", { {"geometry", StringReference},
500 {"width", IntegerReference}, {"height", IntegerReference},
501 {"delta-x", RealReference}, {"rigidity", RealReference } } },
502 { "Encipher", { {"passphrase", StringReference} } },
503 { "Decipher", { {"passphrase", StringReference} } },
504 { "Deskew", { {"geometry", StringReference},
505 {"threshold", StringReference} } },
506 { "Remap", { {"image", ImageReference},
507 {"dither-method", MagickDitherOptions} } },
508 { "SparseColor", { {"points", ArrayReference},
509 {"method", MagickSparseColorOptions},
510 {"virtual-pixel", MagickVirtualPixelOptions},
511 {"channel", MagickChannelOptions} } },
512 { "Function", { {"parameters", ArrayReference},
513 {"function", MagickFunctionOptions},
514 {"virtual-pixel", MagickVirtualPixelOptions} } },
515 { "SelectiveBlur", { {"geometry", StringReference},
516 {"radius", RealReference}, {"sigma", RealReference},
517 {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
518 { "HaldClut", { {"image", ImageReference},
519 {"channel", MagickChannelOptions} } },
520 { "BlueShift", { {"factor", StringReference} } },
521 { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
522 { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
523 { "ColorDecisionList", {
524 {"color-correction-collection", StringReference} } },
525 { "AutoGamma", { {"channel", MagickChannelOptions} } },
526 { "AutoLevel", { {"channel", MagickChannelOptions} } },
527 { "LevelColors", { {"invert", MagickBooleanOptions},
528 {"black-point", StringReference}, {"white-point", StringReference},
529 {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
530 { "Clamp", { {"channel", MagickChannelOptions} } },
531 { "BrightnessContrast", { {"levels", StringReference},
532 {"brightness", RealReference},{"contrast", RealReference},
533 {"channel", MagickChannelOptions} } },
534 { "Morphology", { {"kernel", StringReference},
535 {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
536 {"iterations", IntegerReference} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000537 { "Mode", { {"geometry", StringReference},
538 {"width", IntegerReference},{"height", IntegerReference},
539 {"channel", MagickChannelOptions} } },
540 { "Statistic", { {"geometry", StringReference},
541 {"width", IntegerReference},{"height", IntegerReference},
542 {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
543 { "Perceptible", { {"epsilon", RealReference},
544 {"channel", MagickChannelOptions} } },
545 { "Poly", { {"terms", ArrayReference},
546 {"channel", MagickChannelOptions} } },
547 { "Grayscale", { {"method", MagickNoiseOptions} } },
cristy4ceadb82014-03-29 15:30:43 +0000548 { "CannyEdge", { {"geometry", StringReference},
549 {"radius", RealReference}, {"sigma", RealReference},
cristycfe7bf02014-04-04 15:31:52 +0000550 {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
cristy2fc10e52014-04-26 14:13:53 +0000551 { "HoughLine", { {"geometry", StringReference},
cristy4e215022014-04-19 18:02:35 +0000552 {"width", IntegerReference}, {"height", IntegerReference},
553 {"threshold", IntegerReference} } },
cristy2fc10e52014-04-26 14:13:53 +0000554 { "MeanShift", { {"geometry", StringReference},
555 {"width", IntegerReference}, {"height", IntegerReference},
cristy1309fc32014-04-26 18:48:37 +0000556 {"distance", RealReference} } },
cristy3b207f82014-09-27 14:21:20 +0000557 { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
558 {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
Cristy2ca0e9a2016-01-01 08:36:14 -0500559 { "ConnectedComponents", { {"connectivity", IntegerReference} } },
cristyf3a724a2015-06-25 13:02:53 +0000560 { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
561 {"width", IntegerReference}, {"height", IntegerReference},
562 {"x", IntegerReference}, {"y", IntegerReference},
Cristy532b3382018-08-05 17:56:56 -0400563 {"gravity", MagickGravityOptions}, {"offset", StringReference},
cristyf3a724a2015-06-25 13:02:53 +0000564 {"dx", IntegerReference}, {"dy", IntegerReference} } },
Cristy5488c982016-02-13 14:07:50 -0500565 { "Color", { {"color", StringReference} } },
Cristyc1759412016-02-27 12:17:58 -0500566 { "WaveletDenoise", { {"geometry", StringReference},
567 {"threshold", RealReference}, {"softness", RealReference},
Cristy2d830ed2016-02-21 10:54:16 -0500568 {"channel", MagickChannelOptions} } },
Cristy99a57162016-12-05 11:47:57 -0500569 { "Colorspace", { {"colorspace", MagickColorspaceOptions} } },
Cristy53353872017-07-02 12:24:24 -0400570 { "AutoThreshold", { {"method", MagickAutoThresholdOptions} } },
Cristy532b3382018-08-05 17:56:56 -0400571 { "RangeThreshold", { {"geometry", StringReference},
Cristy72f24752018-08-14 20:17:26 -0400572 {"low-black", RealReference}, {"low-white", RealReference},
573 {"high-white", RealReference}, {"high-black", RealReference},
Cristy532b3382018-08-05 17:56:56 -0400574 {"channel", MagickChannelOptions} } },
Cristy30263282018-12-11 16:40:25 -0500575 { "CLAHE", { {"geometry", StringReference}, {"width", IntegerReference},
576 {"height", IntegerReference}, {"number-bins", IntegerReference},
Cristy768e9002019-01-08 07:35:16 -0500577 {"clip-limit", RealReference} } },
Cristyb4ab5192019-12-19 06:53:46 -0500578 { "Kmeans", { {"geometry", StringReference}, {"colors", IntegerReference},
Cristy1fce5c52019-12-31 09:51:14 -0500579 {"iterations", IntegerReference}, {"tolerance", RealReference} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000580 };
581
582static SplayTreeInfo
583 *magick_registry = (SplayTreeInfo *) NULL;
584
585/*
586 Forward declarations.
587*/
588static Image
589 *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
590
591static ssize_t
592 strEQcase(const char *,const char *);
593
594/*
595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
596% %
597% %
598% %
599% C l o n e P a c k a g e I n f o %
600% %
601% %
602% %
603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604%
605% ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
606% a new one.
607%
608% The format of the ClonePackageInfo routine is:
609%
610% struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
611% exception)
612%
613% A description of each parameter follows:
614%
615% o info: a structure of type info.
616%
617% o exception: Return any errors or warnings in this structure.
618%
619*/
620static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
621 ExceptionInfo *exception)
622{
623 struct PackageInfo
624 *clone_info;
625
626 clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
627 if (clone_info == (struct PackageInfo *) NULL)
628 {
629 ThrowPerlException(exception,ResourceLimitError,
630 "UnableToClonePackageInfo",PackageName);
631 return((struct PackageInfo *) NULL);
632 }
633 if (info == (struct PackageInfo *) NULL)
634 {
635 clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
636 return(clone_info);
637 }
638 *clone_info=(*info);
639 clone_info->image_info=CloneImageInfo(info->image_info);
640 return(clone_info);
641}
642
643/*
644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645% %
646% %
647% %
648% c o n s t a n t %
649% %
650% %
651% %
652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
653%
654% constant() returns a double value for the specified name.
655%
656% The format of the constant routine is:
657%
658% double constant(char *name,ssize_t sans)
659%
660% A description of each parameter follows:
661%
662% o value: Method constant returns a double value for the specified name.
663%
664% o name: The name of the constant.
665%
666% o sans: This integer value is not used.
667%
668*/
669static double constant(char *name,ssize_t sans)
670{
671 (void) sans;
672 errno=0;
673 switch (*name)
674 {
675 case 'B':
676 {
677 if (strEQ(name,"BlobError"))
678 return(BlobError);
679 if (strEQ(name,"BlobWarning"))
680 return(BlobWarning);
681 break;
682 }
683 case 'C':
684 {
685 if (strEQ(name,"CacheError"))
686 return(CacheError);
687 if (strEQ(name,"CacheWarning"))
688 return(CacheWarning);
689 if (strEQ(name,"CoderError"))
690 return(CoderError);
691 if (strEQ(name,"CoderWarning"))
692 return(CoderWarning);
693 if (strEQ(name,"ConfigureError"))
694 return(ConfigureError);
695 if (strEQ(name,"ConfigureWarning"))
696 return(ConfigureWarning);
697 if (strEQ(name,"CorruptImageError"))
698 return(CorruptImageError);
699 if (strEQ(name,"CorruptImageWarning"))
700 return(CorruptImageWarning);
701 break;
702 }
703 case 'D':
704 {
705 if (strEQ(name,"DelegateError"))
706 return(DelegateError);
707 if (strEQ(name,"DelegateWarning"))
708 return(DelegateWarning);
709 if (strEQ(name,"DrawError"))
710 return(DrawError);
711 if (strEQ(name,"DrawWarning"))
712 return(DrawWarning);
713 break;
714 }
715 case 'E':
716 {
717 if (strEQ(name,"ErrorException"))
718 return(ErrorException);
719 if (strEQ(name,"ExceptionError"))
720 return(CoderError);
721 if (strEQ(name,"ExceptionWarning"))
722 return(CoderWarning);
723 break;
724 }
725 case 'F':
726 {
727 if (strEQ(name,"FatalErrorException"))
728 return(FatalErrorException);
729 if (strEQ(name,"FileOpenError"))
730 return(FileOpenError);
731 if (strEQ(name,"FileOpenWarning"))
732 return(FileOpenWarning);
733 break;
734 }
735 case 'I':
736 {
737 if (strEQ(name,"ImageError"))
738 return(ImageError);
739 if (strEQ(name,"ImageWarning"))
740 return(ImageWarning);
741 break;
742 }
743 case 'M':
744 {
745 if (strEQ(name,"MaxRGB"))
746 return(QuantumRange);
747 if (strEQ(name,"MissingDelegateError"))
748 return(MissingDelegateError);
749 if (strEQ(name,"MissingDelegateWarning"))
750 return(MissingDelegateWarning);
751 if (strEQ(name,"ModuleError"))
752 return(ModuleError);
753 if (strEQ(name,"ModuleWarning"))
754 return(ModuleWarning);
755 break;
756 }
757 case 'O':
758 {
759 if (strEQ(name,"Opaque"))
760 return(OpaqueAlpha);
761 if (strEQ(name,"OptionError"))
762 return(OptionError);
763 if (strEQ(name,"OptionWarning"))
764 return(OptionWarning);
765 break;
766 }
767 case 'Q':
768 {
769 if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
770 return(MAGICKCORE_QUANTUM_DEPTH);
771 if (strEQ(name,"QuantumDepth"))
772 return(MAGICKCORE_QUANTUM_DEPTH);
773 if (strEQ(name,"QuantumRange"))
774 return(QuantumRange);
775 break;
776 }
777 case 'R':
778 {
779 if (strEQ(name,"ResourceLimitError"))
780 return(ResourceLimitError);
781 if (strEQ(name,"ResourceLimitWarning"))
782 return(ResourceLimitWarning);
783 if (strEQ(name,"RegistryError"))
784 return(RegistryError);
785 if (strEQ(name,"RegistryWarning"))
786 return(RegistryWarning);
787 break;
788 }
789 case 'S':
790 {
791 if (strEQ(name,"StreamError"))
792 return(StreamError);
793 if (strEQ(name,"StreamWarning"))
794 return(StreamWarning);
795 if (strEQ(name,"Success"))
796 return(0);
797 break;
798 }
799 case 'T':
800 {
801 if (strEQ(name,"Transparent"))
802 return(TransparentAlpha);
803 if (strEQ(name,"TypeError"))
804 return(TypeError);
805 if (strEQ(name,"TypeWarning"))
806 return(TypeWarning);
807 break;
808 }
809 case 'W':
810 {
811 if (strEQ(name,"WarningException"))
812 return(WarningException);
813 break;
814 }
815 case 'X':
816 {
817 if (strEQ(name,"XServerError"))
818 return(XServerError);
819 if (strEQ(name,"XServerWarning"))
820 return(XServerWarning);
821 break;
822 }
823 }
824 errno=EINVAL;
825 return(0);
826}
827
828/*
829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830% %
831% %
832% %
833% D e s t r o y P a c k a g e I n f o %
834% %
835% %
836% %
837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838%
839% Method DestroyPackageInfo frees a previously created info structure.
840%
841% The format of the DestroyPackageInfo routine is:
842%
843% DestroyPackageInfo(struct PackageInfo *info)
844%
845% A description of each parameter follows:
846%
847% o info: a structure of type info.
848%
849*/
850static void DestroyPackageInfo(struct PackageInfo *info)
851{
852 info->image_info=DestroyImageInfo(info->image_info);
853 info=(struct PackageInfo *) RelinquishMagickMemory(info);
854}
855
856/*
857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858% %
859% %
860% %
861% G e t L i s t %
862% %
863% %
864% %
865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866%
867% Method GetList is recursively called by SetupList to traverse the
868% Image__Magick reference. If building an reference_vector (see SetupList),
869% *current is the current position in *reference_vector and *last is the final
870% entry in *reference_vector.
871%
872% The format of the GetList routine is:
873%
874% GetList(info)
875%
876% A description of each parameter follows:
877%
878% o info: a structure of type info.
879%
880*/
881static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
882 ssize_t *current,ssize_t *last,ExceptionInfo *exception)
883{
884 Image
885 *image;
886
887 if (reference == (SV *) NULL)
888 return(NULL);
889 switch (SvTYPE(reference))
890 {
891 case SVt_PVAV:
892 {
893 AV
894 *av;
895
896 Image
897 *head,
898 *previous;
899
900 register ssize_t
901 i;
902
903 ssize_t
904 n;
905
906 /*
907 Array of images.
908 */
909 previous=(Image *) NULL;
910 head=(Image *) NULL;
911 av=(AV *) reference;
912 n=av_len(av);
913 for (i=0; i <= n; i++)
914 {
915 SV
916 **rv;
917
918 rv=av_fetch(av,i,0);
919 if (rv && *rv && sv_isobject(*rv))
920 {
921 image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
922 exception);
923 if (image == (Image *) NULL)
924 continue;
925 if (image == previous)
926 {
927 image=CloneImage(image,0,0,MagickTrue,exception);
928 if (image == (Image *) NULL)
929 return(NULL);
930 }
931 image->previous=previous;
932 *(previous ? &previous->next : &head)=image;
933 for (previous=image; previous->next; previous=previous->next) ;
934 }
935 }
936 return(head);
937 }
938 case SVt_PVMG:
939 {
940 /*
941 Blessed scalar, one image.
942 */
943 image=INT2PTR(Image *,SvIV(reference));
944 if (image == (Image *) NULL)
945 return(NULL);
946 image->previous=(Image *) NULL;
947 image->next=(Image *) NULL;
948 if (reference_vector)
949 {
950 if (*current == *last)
951 {
952 *last+=256;
953 if (*reference_vector == (SV **) NULL)
954 *reference_vector=(SV **) AcquireQuantumMemory(*last,
955 sizeof(*reference_vector));
956 else
957 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
958 *last,sizeof(*reference_vector));
959 }
960 if (*reference_vector == (SV **) NULL)
961 {
962 ThrowPerlException(exception,ResourceLimitError,
963 "MemoryAllocationFailed",PackageName);
964 return((Image *) NULL);
965 }
966 (*reference_vector)[*current]=reference;
967 (*reference_vector)[++(*current)]=NULL;
968 }
969 return(image);
970 }
971 default:
972 break;
973 }
974 (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
975 (double) SvTYPE(reference));
976 return((Image *) NULL);
977}
978
979/*
980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
981% %
982% %
983% %
984% G e t P a c k a g e I n f o %
985% %
986% %
987% %
988%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
989%
990% Method GetPackageInfo looks up or creates an info structure for the given
991% Image__Magick reference. If it does create a new one, the information in
992% package_info is used to initialize it.
993%
994% The format of the GetPackageInfo routine is:
995%
996% struct PackageInfo *GetPackageInfo(void *reference,
997% struct PackageInfo *package_info,ExceptionInfo *exception)
998%
999% A description of each parameter follows:
1000%
1001% o info: a structure of type info.
1002%
1003% o exception: Return any errors or warnings in this structure.
1004%
1005*/
1006static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
1007 struct PackageInfo *package_info,ExceptionInfo *exception)
1008{
1009 char
cristy151b66d2015-04-15 10:50:31 +00001010 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00001011
1012 struct PackageInfo
1013 *clone_info;
1014
1015 SV
1016 *sv;
1017
cristy151b66d2015-04-15 10:50:31 +00001018 (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
cristy4a3ce0a2013-08-03 20:06:59 +00001019 PackageName,XS_VERSION,reference);
1020 sv=perl_get_sv(message,(TRUE | 0x02));
1021 if (sv == (SV *) NULL)
1022 {
1023 ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1024 message);
1025 return(package_info);
1026 }
1027 if (SvREFCNT(sv) == 0)
1028 (void) SvREFCNT_inc(sv);
1029 if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1030 return(clone_info);
1031 clone_info=ClonePackageInfo(package_info,exception);
1032 sv_setiv(sv,PTR2IV(clone_info));
1033 return(clone_info);
1034}
1035
1036/*
1037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038% %
1039% %
1040% %
1041% S e t A t t r i b u t e %
1042% %
1043% %
1044% %
1045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046%
1047% SetAttribute() sets the attribute to the value in sval. This can change
1048% either or both of image or info.
1049%
1050% The format of the SetAttribute routine is:
1051%
1052% SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1053% SV *sval,ExceptionInfo *exception)
1054%
1055% A description of each parameter follows:
1056%
1057% o list: a list of strings.
1058%
1059% o string: a character string.
1060%
1061*/
1062
1063static double SiPrefixToDoubleInterval(const char *string,const double interval)
1064{
1065 char
1066 *q;
1067
1068 double
1069 value;
1070
1071 value=InterpretSiPrefixValue(string,&q);
1072 if (*q == '%')
1073 value*=interval/100.0;
1074 return(value);
1075}
1076
1077static inline double StringToDouble(const char *string,char **sentinal)
1078{
1079 return(InterpretLocaleValue(string,sentinal));
1080}
1081
1082static double StringToDoubleInterval(const char *string,const double interval)
1083{
1084 char
1085 *q;
1086
1087 double
1088 value;
1089
1090 value=InterpretLocaleValue(string,&q);
1091 if (*q == '%')
1092 value*=interval/100.0;
1093 return(value);
1094}
1095
1096static inline ssize_t StringToLong(const char *value)
1097{
1098 return(strtol(value,(char **) NULL,10));
1099}
1100
1101static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1102 const char *attribute,SV *sval,ExceptionInfo *exception)
1103{
1104 GeometryInfo
1105 geometry_info;
1106
1107 long
1108 x,
1109 y;
1110
1111 PixelInfo
1112 pixel;
1113
1114 MagickStatusType
1115 flags;
1116
1117 PixelInfo
1118 *color,
1119 target_color;
1120
1121 ssize_t
1122 sp;
1123
1124 switch (*attribute)
1125 {
1126 case 'A':
1127 case 'a':
1128 {
1129 if (LocaleCompare(attribute,"adjoin") == 0)
1130 {
1131 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1132 SvPV(sval,na)) : SvIV(sval);
1133 if (sp < 0)
1134 {
1135 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1136 SvPV(sval,na));
1137 break;
1138 }
1139 if (info)
1140 info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1141 break;
1142 }
1143 if (LocaleCompare(attribute,"alpha") == 0)
1144 {
1145 sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1146 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1147 if (sp < 0)
1148 {
1149 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1150 SvPV(sval,na));
1151 break;
1152 }
1153 for ( ; image; image=image->next)
1154 (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1155 exception);
1156 break;
1157 }
1158 if (LocaleCompare(attribute,"antialias") == 0)
1159 {
1160 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1161 SvPV(sval,na)) : SvIV(sval);
1162 if (sp < 0)
1163 {
1164 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1165 SvPV(sval,na));
1166 break;
1167 }
1168 if (info)
1169 info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1170 break;
1171 }
1172 if (LocaleCompare(attribute,"area-limit") == 0)
1173 {
1174 MagickSizeType
1175 limit;
1176
1177 limit=MagickResourceInfinity;
1178 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1179 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1180 100.0);
1181 (void) SetMagickResourceLimit(AreaResource,limit);
1182 break;
1183 }
1184 if (LocaleCompare(attribute,"attenuate") == 0)
1185 {
1186 if (info)
1187 (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1188 break;
1189 }
1190 if (LocaleCompare(attribute,"authenticate") == 0)
1191 {
1192 if (info)
1193 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1194 break;
1195 }
1196 if (info)
1197 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1198 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001199 {
1200 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstra337c9bc2017-04-03 16:04:21 +02001201 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001202 }
cristy4a3ce0a2013-08-03 20:06:59 +00001203 break;
1204 }
1205 case 'B':
1206 case 'b':
1207 {
1208 if (LocaleCompare(attribute,"background") == 0)
1209 {
1210 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1211 exception);
1212 if (info)
1213 info->image_info->background_color=target_color;
1214 for ( ; image; image=image->next)
1215 image->background_color=target_color;
1216 break;
1217 }
1218 if (LocaleCompare(attribute,"blue-primary") == 0)
1219 {
1220 for ( ; image; image=image->next)
1221 {
1222 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1223 image->chromaticity.blue_primary.x=geometry_info.rho;
1224 image->chromaticity.blue_primary.y=geometry_info.sigma;
1225 if ((flags & SigmaValue) == 0)
1226 image->chromaticity.blue_primary.y=
1227 image->chromaticity.blue_primary.x;
1228 }
1229 break;
1230 }
1231 if (LocaleCompare(attribute,"bordercolor") == 0)
1232 {
1233 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1234 exception);
1235 if (info)
1236 info->image_info->border_color=target_color;
1237 for ( ; image; image=image->next)
1238 image->border_color=target_color;
1239 break;
1240 }
1241 if (info)
1242 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1243 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001244 {
1245 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001246 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001247 }
cristy4a3ce0a2013-08-03 20:06:59 +00001248 break;
1249 }
1250 case 'C':
1251 case 'c':
1252 {
1253 if (LocaleCompare(attribute,"cache-threshold") == 0)
1254 {
1255 (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1256 SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1257 (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1258 (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1259 break;
1260 }
1261 if (LocaleCompare(attribute,"clip-mask") == 0)
1262 {
1263 Image
1264 *clip_mask;
1265
1266 clip_mask=(Image *) NULL;
1267 if (SvPOK(sval))
1268 clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1269 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001270 SetImageMask(image,ReadPixelMask,clip_mask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001271 break;
1272 }
1273 if (LocaleNCompare(attribute,"colormap",8) == 0)
1274 {
1275 for ( ; image; image=image->next)
1276 {
1277 int
1278 items;
1279
1280 long
1281 i;
1282
1283 if (image->storage_class == DirectClass)
1284 continue;
1285 i=0;
1286 items=sscanf(attribute,"%*[^[][%ld",&i);
1287 (void) items;
1288 if (i > (ssize_t) image->colors)
1289 i%=image->colors;
1290 if ((strchr(SvPV(sval,na),',') == 0) ||
1291 (strchr(SvPV(sval,na),')') != 0))
1292 QueryColorCompliance(SvPV(sval,na),AllCompliance,
1293 image->colormap+i,exception);
1294 else
1295 {
1296 color=image->colormap+i;
1297 pixel.red=color->red;
1298 pixel.green=color->green;
1299 pixel.blue=color->blue;
1300 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1301 pixel.red=geometry_info.rho;
1302 pixel.green=geometry_info.sigma;
1303 pixel.blue=geometry_info.xi;
1304 color->red=ClampToQuantum(pixel.red);
1305 color->green=ClampToQuantum(pixel.green);
1306 color->blue=ClampToQuantum(pixel.blue);
1307 }
1308 }
1309 break;
1310 }
1311 if (LocaleCompare(attribute,"colorspace") == 0)
1312 {
1313 sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1314 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1315 if (sp < 0)
1316 {
1317 ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1318 SvPV(sval,na));
1319 break;
1320 }
1321 for ( ; image; image=image->next)
Cristy59262d92016-12-05 15:21:50 -05001322 (void) SetImageColorspace(image,(ColorspaceType) sp,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001323 break;
1324 }
1325 if (LocaleCompare(attribute,"comment") == 0)
1326 {
1327 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001328 (void) SetImageProperty(image,"Comment",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00001329 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04001330 SvPV(sval,na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001331 break;
1332 }
1333 if (LocaleCompare(attribute,"compression") == 0)
1334 {
1335 sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1336 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1337 if (sp < 0)
1338 {
1339 ThrowPerlException(exception,OptionError,
1340 "UnrecognizedImageCompression",SvPV(sval,na));
1341 break;
1342 }
1343 if (info)
1344 info->image_info->compression=(CompressionType) sp;
1345 for ( ; image; image=image->next)
1346 image->compression=(CompressionType) sp;
1347 break;
1348 }
1349 if (info)
1350 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1351 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001352 {
1353 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001354 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001355 }
cristy4a3ce0a2013-08-03 20:06:59 +00001356 break;
1357 }
1358 case 'D':
1359 case 'd':
1360 {
1361 if (LocaleCompare(attribute,"debug") == 0)
1362 {
1363 SetLogEventMask(SvPV(sval,na));
1364 break;
1365 }
1366 if (LocaleCompare(attribute,"delay") == 0)
1367 {
1368 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1369 for ( ; image; image=image->next)
1370 {
1371 image->delay=(size_t) floor(geometry_info.rho+0.5);
1372 if ((flags & SigmaValue) != 0)
1373 image->ticks_per_second=(ssize_t)
1374 floor(geometry_info.sigma+0.5);
1375 }
1376 break;
1377 }
1378 if (LocaleCompare(attribute,"disk-limit") == 0)
1379 {
1380 MagickSizeType
1381 limit;
1382
1383 limit=MagickResourceInfinity;
1384 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1385 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1386 100.0);
1387 (void) SetMagickResourceLimit(DiskResource,limit);
1388 break;
1389 }
1390 if (LocaleCompare(attribute,"density") == 0)
1391 {
1392 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1393 {
1394 ThrowPerlException(exception,OptionError,"MissingGeometry",
1395 SvPV(sval,na));
1396 break;
1397 }
1398 if (info)
1399 (void) CloneString(&info->image_info->density,SvPV(sval,na));
1400 for ( ; image; image=image->next)
1401 {
1402 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1403 image->resolution.x=geometry_info.rho;
1404 image->resolution.y=geometry_info.sigma;
1405 if ((flags & SigmaValue) == 0)
1406 image->resolution.y=image->resolution.x;
1407 }
1408 break;
1409 }
1410 if (LocaleCompare(attribute,"depth") == 0)
1411 {
1412 if (info)
1413 info->image_info->depth=SvIV(sval);
1414 for ( ; image; image=image->next)
1415 (void) SetImageDepth(image,SvIV(sval),exception);
1416 break;
1417 }
1418 if (LocaleCompare(attribute,"dispose") == 0)
1419 {
1420 sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1421 SvPV(sval,na)) : SvIV(sval);
1422 if (sp < 0)
1423 {
1424 ThrowPerlException(exception,OptionError,
1425 "UnrecognizedDisposeMethod",SvPV(sval,na));
1426 break;
1427 }
1428 for ( ; image; image=image->next)
1429 image->dispose=(DisposeType) sp;
1430 break;
1431 }
1432 if (LocaleCompare(attribute,"dither") == 0)
1433 {
1434 if (info)
1435 {
1436 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1437 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1438 if (sp < 0)
1439 {
1440 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1441 SvPV(sval,na));
1442 break;
1443 }
1444 info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1445 }
1446 break;
1447 }
1448 if (LocaleCompare(attribute,"display") == 0)
1449 {
1450 display:
1451 if (info)
1452 (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1453 break;
1454 }
1455 if (info)
1456 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1457 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001458 {
1459 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001460 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001461 }
cristy4a3ce0a2013-08-03 20:06:59 +00001462 break;
1463 }
1464 case 'E':
1465 case 'e':
1466 {
1467 if (LocaleCompare(attribute,"endian") == 0)
1468 {
1469 sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1470 SvPV(sval,na)) : SvIV(sval);
1471 if (sp < 0)
1472 {
1473 ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1474 SvPV(sval,na));
1475 break;
1476 }
1477 if (info)
1478 info->image_info->endian=(EndianType) sp;
1479 for ( ; image; image=image->next)
1480 image->endian=(EndianType) sp;
1481 break;
1482 }
1483 if (LocaleCompare(attribute,"extract") == 0)
1484 {
1485 /*
1486 Set image extract geometry.
1487 */
1488 (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1489 break;
1490 }
1491 if (info)
1492 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1493 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001494 {
1495 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001496 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001497 }
cristy4a3ce0a2013-08-03 20:06:59 +00001498 break;
1499 }
1500 case 'F':
1501 case 'f':
1502 {
1503 if (LocaleCompare(attribute,"filename") == 0)
1504 {
1505 if (info)
1506 (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
cristy151b66d2015-04-15 10:50:31 +00001507 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001508 for ( ; image; image=image->next)
1509 (void) CopyMagickString(image->filename,SvPV(sval,na),
cristy151b66d2015-04-15 10:50:31 +00001510 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001511 break;
1512 }
1513 if (LocaleCompare(attribute,"file") == 0)
1514 {
1515 FILE
1516 *file;
1517
1518 PerlIO
1519 *io_info;
1520
1521 if (info == (struct PackageInfo *) NULL)
1522 break;
1523 io_info=IoIFP(sv_2io(sval));
1524 if (io_info == (PerlIO *) NULL)
1525 {
1526 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1527 PackageName);
1528 break;
1529 }
1530 file=PerlIO_findFILE(io_info);
1531 if (file == (FILE *) NULL)
1532 {
1533 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1534 PackageName);
1535 break;
1536 }
1537 SetImageInfoFile(info->image_info,file);
1538 break;
1539 }
1540 if (LocaleCompare(attribute,"fill") == 0)
1541 {
1542 if (info)
1543 (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1544 break;
1545 }
1546 if (LocaleCompare(attribute,"font") == 0)
1547 {
1548 if (info)
1549 (void) CloneString(&info->image_info->font,SvPV(sval,na));
1550 break;
1551 }
1552 if (LocaleCompare(attribute,"foreground") == 0)
1553 break;
1554 if (LocaleCompare(attribute,"fuzz") == 0)
1555 {
1556 if (info)
1557 info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1558 QuantumRange+1.0);
1559 for ( ; image; image=image->next)
1560 image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1561 QuantumRange+1.0);
1562 break;
1563 }
1564 if (info)
1565 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1566 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001567 {
1568 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001569 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001570 }
cristy4a3ce0a2013-08-03 20:06:59 +00001571 break;
1572 }
1573 case 'G':
1574 case 'g':
1575 {
1576 if (LocaleCompare(attribute,"gamma") == 0)
1577 {
1578 for ( ; image; image=image->next)
1579 image->gamma=SvNV(sval);
1580 break;
1581 }
1582 if (LocaleCompare(attribute,"gravity") == 0)
1583 {
1584 sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1585 SvPV(sval,na)) : SvIV(sval);
1586 if (sp < 0)
1587 {
1588 ThrowPerlException(exception,OptionError,
1589 "UnrecognizedGravityType",SvPV(sval,na));
1590 break;
1591 }
1592 if (info)
1593 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1594 for ( ; image; image=image->next)
1595 image->gravity=(GravityType) sp;
1596 break;
1597 }
1598 if (LocaleCompare(attribute,"green-primary") == 0)
1599 {
1600 for ( ; image; image=image->next)
1601 {
1602 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1603 image->chromaticity.green_primary.x=geometry_info.rho;
1604 image->chromaticity.green_primary.y=geometry_info.sigma;
1605 if ((flags & SigmaValue) == 0)
1606 image->chromaticity.green_primary.y=
1607 image->chromaticity.green_primary.x;
1608 }
1609 break;
1610 }
1611 if (info)
1612 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1613 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001614 {
1615 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001616 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001617 }
cristy4a3ce0a2013-08-03 20:06:59 +00001618 break;
1619 }
1620 case 'I':
1621 case 'i':
1622 {
1623 if (LocaleNCompare(attribute,"index",5) == 0)
1624 {
1625 int
1626 items;
1627
1628 long
1629 index;
1630
1631 register Quantum
1632 *q;
1633
1634 CacheView
1635 *image_view;
1636
1637 for ( ; image; image=image->next)
1638 {
1639 if (image->storage_class != PseudoClass)
1640 continue;
1641 x=0;
1642 y=0;
1643 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1644 (void) items;
1645 image_view=AcquireAuthenticCacheView(image,exception);
1646 q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1647 if (q != (Quantum *) NULL)
1648 {
1649 items=sscanf(SvPV(sval,na),"%ld",&index);
1650 if ((index >= 0) && (index < (ssize_t) image->colors))
1651 SetPixelIndex(image,index,q);
1652 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1653 }
1654 image_view=DestroyCacheView(image_view);
1655 }
1656 break;
1657 }
1658 if (LocaleCompare(attribute,"iterations") == 0)
1659 {
1660 iterations:
1661 for ( ; image; image=image->next)
1662 image->iterations=SvIV(sval);
1663 break;
1664 }
1665 if (LocaleCompare(attribute,"interlace") == 0)
1666 {
1667 sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1668 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1669 if (sp < 0)
1670 {
1671 ThrowPerlException(exception,OptionError,
1672 "UnrecognizedInterlaceType",SvPV(sval,na));
1673 break;
1674 }
1675 if (info)
1676 info->image_info->interlace=(InterlaceType) sp;
1677 for ( ; image; image=image->next)
1678 image->interlace=(InterlaceType) sp;
1679 break;
1680 }
1681 if (info)
1682 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1683 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001684 {
1685 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001686 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001687 }
cristy4a3ce0a2013-08-03 20:06:59 +00001688 break;
1689 }
1690 case 'L':
1691 case 'l':
1692 {
1693 if (LocaleCompare(attribute,"label") == 0)
1694 {
1695 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001696 (void) SetImageProperty(image,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00001697 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04001698 SvPV(sval,na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001699 break;
1700 }
1701 if (LocaleCompare(attribute,"loop") == 0)
1702 goto iterations;
1703 if (info)
1704 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1705 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001706 {
1707 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001708 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001709 }
cristy4a3ce0a2013-08-03 20:06:59 +00001710 break;
1711 }
1712 case 'M':
1713 case 'm':
1714 {
1715 if (LocaleCompare(attribute,"magick") == 0)
1716 {
1717 if (info)
Cristyb5b1f5d2017-03-31 16:42:35 -04001718 (void) FormatLocaleString(info->image_info->filename,
1719 MagickPathExtent,"%s:",SvPV(sval,na));
cristy4a3ce0a2013-08-03 20:06:59 +00001720 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001721 (void) CopyMagickString(image->magick,SvPV(sval,na),
1722 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001723 break;
1724 }
1725 if (LocaleCompare(attribute,"map-limit") == 0)
1726 {
1727 MagickSizeType
1728 limit;
1729
1730 limit=MagickResourceInfinity;
1731 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1732 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1733 100.0);
1734 (void) SetMagickResourceLimit(MapResource,limit);
1735 break;
1736 }
1737 if (LocaleCompare(attribute,"mask") == 0)
1738 {
1739 Image
1740 *mask;
1741
1742 mask=(Image *) NULL;
1743 if (SvPOK(sval))
1744 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1745 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001746 SetImageMask(image,ReadPixelMask,mask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001747 break;
1748 }
1749 if (LocaleCompare(attribute,"mattecolor") == 0)
1750 {
1751 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1752 exception);
1753 if (info)
Cristy8645e042016-02-03 16:35:29 -05001754 info->image_info->alpha_color=target_color;
cristy4a3ce0a2013-08-03 20:06:59 +00001755 for ( ; image; image=image->next)
Cristy8645e042016-02-03 16:35:29 -05001756 image->alpha_color=target_color;
cristy4a3ce0a2013-08-03 20:06:59 +00001757 break;
1758 }
1759 if (LocaleCompare(attribute,"matte") == 0)
1760 {
1761 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1762 SvPV(sval,na)) : SvIV(sval);
1763 if (sp < 0)
1764 {
1765 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1766 SvPV(sval,na));
1767 break;
1768 }
1769 for ( ; image; image=image->next)
1770 image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1771 break;
1772 }
1773 if (LocaleCompare(attribute,"memory-limit") == 0)
1774 {
1775 MagickSizeType
1776 limit;
1777
1778 limit=MagickResourceInfinity;
1779 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1780 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1781 100.0);
1782 (void) SetMagickResourceLimit(MemoryResource,limit);
1783 break;
1784 }
1785 if (LocaleCompare(attribute,"monochrome") == 0)
1786 {
1787 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1788 SvPV(sval,na)) : SvIV(sval);
1789 if (sp < 0)
1790 {
1791 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1792 SvPV(sval,na));
1793 break;
1794 }
1795 if (info)
1796 info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1797 for ( ; image; image=image->next)
1798 (void) SetImageType(image,BilevelType,exception);
1799 break;
1800 }
1801 if (info)
1802 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1803 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001804 {
1805 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001806 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001807 }
cristy4a3ce0a2013-08-03 20:06:59 +00001808 break;
1809 }
1810 case 'O':
1811 case 'o':
1812 {
1813 if (LocaleCompare(attribute,"option") == 0)
1814 {
1815 if (info)
1816 DefineImageOption(info->image_info,SvPV(sval,na));
1817 break;
1818 }
1819 if (LocaleCompare(attribute,"orientation") == 0)
1820 {
1821 sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1822 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1823 if (sp < 0)
1824 {
1825 ThrowPerlException(exception,OptionError,
1826 "UnrecognizedOrientationType",SvPV(sval,na));
1827 break;
1828 }
1829 if (info)
1830 info->image_info->orientation=(OrientationType) sp;
1831 for ( ; image; image=image->next)
1832 image->orientation=(OrientationType) sp;
1833 break;
1834 }
1835 if (info)
1836 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1837 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001838 {
1839 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001840 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001841 }
cristy4a3ce0a2013-08-03 20:06:59 +00001842 break;
1843 }
1844 case 'P':
1845 case 'p':
1846 {
1847 if (LocaleCompare(attribute,"page") == 0)
1848 {
1849 char
1850 *geometry;
1851
1852 geometry=GetPageGeometry(SvPV(sval,na));
1853 if (info)
1854 (void) CloneString(&info->image_info->page,geometry);
1855 for ( ; image; image=image->next)
1856 (void) ParsePageGeometry(image,geometry,&image->page,exception);
1857 geometry=(char *) RelinquishMagickMemory(geometry);
1858 break;
1859 }
1860 if (LocaleNCompare(attribute,"pixel",5) == 0)
1861 {
1862 int
1863 items;
1864
1865 PixelInfo
1866 pixel;
1867
1868 register Quantum
1869 *q;
1870
1871 CacheView
1872 *image_view;
1873
1874 for ( ; image; image=image->next)
1875 {
1876 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1877 break;
1878 x=0;
1879 y=0;
1880 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1881 (void) items;
1882 image_view=AcquireVirtualCacheView(image,exception);
1883 q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1884 if (q != (Quantum *) NULL)
1885 {
1886 if ((strchr(SvPV(sval,na),',') == 0) ||
1887 (strchr(SvPV(sval,na),')') != 0))
1888 QueryColorCompliance(SvPV(sval,na),AllCompliance,
1889 &pixel,exception);
1890 else
1891 {
1892 GetPixelInfo(image,&pixel);
1893 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1894 pixel.red=geometry_info.rho;
1895 if ((flags & SigmaValue) != 0)
1896 pixel.green=geometry_info.sigma;
1897 if ((flags & XiValue) != 0)
1898 pixel.blue=geometry_info.xi;
1899 if ((flags & PsiValue) != 0)
1900 pixel.alpha=geometry_info.psi;
1901 if ((flags & ChiValue) != 0)
1902 pixel.black=geometry_info.chi;
1903 }
1904 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1905 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1906 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1907 if (image->colorspace == CMYKColorspace)
1908 SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1909 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1910 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1911 }
1912 image_view=DestroyCacheView(image_view);
1913 }
1914 break;
1915 }
1916 if (LocaleCompare(attribute,"pointsize") == 0)
1917 {
1918 if (info)
1919 {
1920 (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1921 info->image_info->pointsize=geometry_info.rho;
1922 }
1923 break;
1924 }
Cristy798981a2020-02-17 12:07:15 -05001925 if (LocaleCompare(attribute,"precision") == 0)
1926 {
1927 (void) SetMagickPrecision(SvIV(sval));
1928 break;
1929 }
cristy4a3ce0a2013-08-03 20:06:59 +00001930 if (info)
1931 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1932 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001933 {
1934 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001935 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001936 }
cristy4a3ce0a2013-08-03 20:06:59 +00001937 break;
1938 }
1939 case 'Q':
1940 case 'q':
1941 {
1942 if (LocaleCompare(attribute,"quality") == 0)
1943 {
1944 if (info)
1945 info->image_info->quality=SvIV(sval);
1946 for ( ; image; image=image->next)
1947 image->quality=SvIV(sval);
1948 break;
1949 }
1950 if (info)
1951 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1952 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001953 {
1954 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001955 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001956 }
cristy4a3ce0a2013-08-03 20:06:59 +00001957 break;
1958 }
1959 case 'R':
1960 case 'r':
1961 {
cristyc0fe4752015-07-27 18:02:39 +00001962 if (LocaleCompare(attribute,"read-mask") == 0)
1963 {
1964 Image
1965 *mask;
1966
1967 mask=(Image *) NULL;
1968 if (SvPOK(sval))
1969 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1970 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001971 SetImageMask(image,ReadPixelMask,mask,exception);
cristyc0fe4752015-07-27 18:02:39 +00001972 break;
1973 }
cristy4a3ce0a2013-08-03 20:06:59 +00001974 if (LocaleCompare(attribute,"red-primary") == 0)
1975 {
1976 for ( ; image; image=image->next)
1977 {
1978 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1979 image->chromaticity.red_primary.x=geometry_info.rho;
1980 image->chromaticity.red_primary.y=geometry_info.sigma;
1981 if ((flags & SigmaValue) == 0)
1982 image->chromaticity.red_primary.y=
1983 image->chromaticity.red_primary.x;
1984 }
1985 break;
1986 }
1987 if (LocaleCompare(attribute,"render") == 0)
1988 {
1989 sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1990 SvPV(sval,na)) : SvIV(sval);
1991 if (sp < 0)
1992 {
1993 ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1994 SvPV(sval,na));
1995 break;
1996 }
1997 for ( ; image; image=image->next)
1998 image->rendering_intent=(RenderingIntent) sp;
1999 break;
2000 }
2001 if (LocaleCompare(attribute,"repage") == 0)
2002 {
2003 RectangleInfo
2004 geometry;
2005
2006 for ( ; image; image=image->next)
2007 {
2008 flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
2009 if ((flags & WidthValue) != 0)
2010 {
2011 if ((flags & HeightValue) == 0)
2012 geometry.height=geometry.width;
2013 image->page.width=geometry.width;
2014 image->page.height=geometry.height;
2015 }
2016 if ((flags & AspectValue) != 0)
2017 {
2018 if ((flags & XValue) != 0)
2019 image->page.x+=geometry.x;
2020 if ((flags & YValue) != 0)
2021 image->page.y+=geometry.y;
2022 }
2023 else
2024 {
2025 if ((flags & XValue) != 0)
2026 {
2027 image->page.x=geometry.x;
2028 if (((flags & WidthValue) != 0) && (geometry.x > 0))
2029 image->page.width=image->columns+geometry.x;
2030 }
2031 if ((flags & YValue) != 0)
2032 {
2033 image->page.y=geometry.y;
2034 if (((flags & HeightValue) != 0) && (geometry.y > 0))
2035 image->page.height=image->rows+geometry.y;
2036 }
2037 }
2038 }
2039 break;
2040 }
2041 if (info)
2042 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2043 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002044 {
2045 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002046 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002047 }
cristy4a3ce0a2013-08-03 20:06:59 +00002048 break;
2049 }
2050 case 'S':
2051 case 's':
2052 {
2053 if (LocaleCompare(attribute,"sampling-factor") == 0)
2054 {
2055 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2056 {
2057 ThrowPerlException(exception,OptionError,"MissingGeometry",
2058 SvPV(sval,na));
2059 break;
2060 }
2061 if (info)
2062 (void) CloneString(&info->image_info->sampling_factor,
2063 SvPV(sval,na));
2064 break;
2065 }
2066 if (LocaleCompare(attribute,"scene") == 0)
2067 {
2068 for ( ; image; image=image->next)
2069 image->scene=SvIV(sval);
2070 break;
2071 }
2072 if (LocaleCompare(attribute,"server") == 0)
2073 goto display;
2074 if (LocaleCompare(attribute,"size") == 0)
2075 {
2076 if (info)
2077 {
2078 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2079 {
2080 ThrowPerlException(exception,OptionError,"MissingGeometry",
2081 SvPV(sval,na));
2082 break;
2083 }
2084 (void) CloneString(&info->image_info->size,SvPV(sval,na));
2085 }
2086 break;
2087 }
2088 if (LocaleCompare(attribute,"stroke") == 0)
2089 {
2090 if (info)
2091 (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2092 break;
2093 }
2094 if (info)
2095 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2096 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002097 {
2098 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002099 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002100 }
cristy4a3ce0a2013-08-03 20:06:59 +00002101 break;
2102 }
2103 case 'T':
2104 case 't':
2105 {
2106 if (LocaleCompare(attribute,"texture") == 0)
2107 {
2108 if (info)
2109 (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2110 break;
2111 }
2112 if (LocaleCompare(attribute,"thread-limit") == 0)
2113 {
2114 MagickSizeType
2115 limit;
2116
2117 limit=MagickResourceInfinity;
2118 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2119 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2120 100.0);
2121 (void) SetMagickResourceLimit(ThreadResource,limit);
2122 break;
2123 }
2124 if (LocaleCompare(attribute,"tile-offset") == 0)
2125 {
2126 char
2127 *geometry;
2128
2129 geometry=GetPageGeometry(SvPV(sval,na));
2130 if (info)
2131 (void) CloneString(&info->image_info->page,geometry);
2132 for ( ; image; image=image->next)
2133 (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2134 exception);
2135 geometry=(char *) RelinquishMagickMemory(geometry);
2136 break;
2137 }
2138 if (LocaleCompare(attribute,"time-limit") == 0)
2139 {
2140 MagickSizeType
2141 limit;
2142
2143 limit=MagickResourceInfinity;
2144 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2145 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2146 100.0);
2147 (void) SetMagickResourceLimit(TimeResource,limit);
2148 break;
2149 }
2150 if (LocaleCompare(attribute,"transparent-color") == 0)
2151 {
2152 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2153 exception);
2154 if (info)
2155 info->image_info->transparent_color=target_color;
2156 for ( ; image; image=image->next)
2157 image->transparent_color=target_color;
2158 break;
2159 }
2160 if (LocaleCompare(attribute,"type") == 0)
2161 {
2162 sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2163 SvPV(sval,na)) : SvIV(sval);
2164 if (sp < 0)
2165 {
2166 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2167 SvPV(sval,na));
2168 break;
2169 }
2170 if (info)
2171 info->image_info->type=(ImageType) sp;
2172 for ( ; image; image=image->next)
2173 SetImageType(image,(ImageType) sp,exception);
2174 break;
2175 }
2176 if (info)
2177 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2178 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002179 {
2180 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002181 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002182 }
cristy4a3ce0a2013-08-03 20:06:59 +00002183 break;
2184 }
2185 case 'U':
2186 case 'u':
2187 {
2188 if (LocaleCompare(attribute,"units") == 0)
2189 {
2190 sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2191 MagickFalse,SvPV(sval,na)) : SvIV(sval);
2192 if (sp < 0)
2193 {
2194 ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2195 SvPV(sval,na));
2196 break;
2197 }
2198 if (info)
2199 info->image_info->units=(ResolutionType) sp;
2200 for ( ; image; image=image->next)
2201 {
2202 ResolutionType
2203 units;
2204
2205 units=(ResolutionType) sp;
2206 if (image->units != units)
2207 switch (image->units)
2208 {
2209 case UndefinedResolution:
2210 case PixelsPerInchResolution:
2211 {
2212 if (units == PixelsPerCentimeterResolution)
2213 {
2214 image->resolution.x*=2.54;
2215 image->resolution.y*=2.54;
2216 }
2217 break;
2218 }
2219 case PixelsPerCentimeterResolution:
2220 {
2221 if (units == PixelsPerInchResolution)
2222 {
2223 image->resolution.x/=2.54;
2224 image->resolution.y/=2.54;
2225 }
2226 break;
2227 }
2228 }
2229 image->units=units;
2230 }
2231 break;
2232 }
2233 if (info)
2234 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2235 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002236 {
2237 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002238 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002239 }
cristy4a3ce0a2013-08-03 20:06:59 +00002240 break;
2241 }
2242 case 'V':
2243 case 'v':
2244 {
2245 if (LocaleCompare(attribute,"verbose") == 0)
2246 {
2247 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2248 SvPV(sval,na)) : SvIV(sval);
2249 if (sp < 0)
2250 {
2251 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2252 SvPV(sval,na));
2253 break;
2254 }
2255 if (info)
2256 info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2257 break;
2258 }
cristy4a3ce0a2013-08-03 20:06:59 +00002259 if (LocaleCompare(attribute,"virtual-pixel") == 0)
2260 {
2261 sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2262 MagickFalse,SvPV(sval,na)) : SvIV(sval);
2263 if (sp < 0)
2264 {
2265 ThrowPerlException(exception,OptionError,
2266 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2267 break;
2268 }
2269 for ( ; image; image=image->next)
2270 SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2271 break;
2272 }
2273 if (info)
2274 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2275 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002276 {
2277 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002278 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002279 }
cristy4a3ce0a2013-08-03 20:06:59 +00002280 break;
2281 }
2282 case 'W':
2283 case 'w':
2284 {
2285 if (LocaleCompare(attribute,"white-point") == 0)
2286 {
2287 for ( ; image; image=image->next)
2288 {
2289 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2290 image->chromaticity.white_point.x=geometry_info.rho;
2291 image->chromaticity.white_point.y=geometry_info.sigma;
2292 if ((flags & SigmaValue) == 0)
2293 image->chromaticity.white_point.y=
2294 image->chromaticity.white_point.x;
2295 }
2296 break;
2297 }
cristyc0fe4752015-07-27 18:02:39 +00002298 if (LocaleCompare(attribute,"write-mask") == 0)
2299 {
2300 Image
2301 *mask;
2302
2303 mask=(Image *) NULL;
2304 if (SvPOK(sval))
2305 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2306 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00002307 SetImageMask(image,WritePixelMask,mask,exception);
cristyc0fe4752015-07-27 18:02:39 +00002308 break;
2309 }
cristy4a3ce0a2013-08-03 20:06:59 +00002310 if (info)
2311 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2312 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002313 {
2314 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002315 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002316 }
cristy4a3ce0a2013-08-03 20:06:59 +00002317 break;
2318 }
2319 default:
2320 {
2321 if (info)
2322 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2323 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002324 {
2325 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002326 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002327 }
cristy4a3ce0a2013-08-03 20:06:59 +00002328 break;
2329 }
2330 }
2331}
2332
2333/*
2334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2335% %
2336% %
2337% %
2338% S e t u p L i s t %
2339% %
2340% %
2341% %
2342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2343%
2344% Method SetupList returns the list of all the images linked by their
2345% image->next and image->previous link lists for use with ImageMagick. If
2346% info is non-NULL, an info structure is returned in *info. If
2347% reference_vector is non-NULL,an array of SV* are returned in
2348% *reference_vector. Reference_vector is used when the images are going to be
2349% replaced with new Image*'s.
2350%
2351% The format of the SetupList routine is:
2352%
2353% Image *SetupList(SV *reference,struct PackageInfo **info,
2354% SV ***reference_vector,ExceptionInfo *exception)
2355%
2356% A description of each parameter follows:
2357%
2358% o list: a list of strings.
2359%
2360% o string: a character string.
2361%
2362% o exception: Return any errors or warnings in this structure.
2363%
2364*/
2365static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2366 SV ***reference_vector,ExceptionInfo *exception)
2367{
2368 Image
2369 *image;
2370
2371 ssize_t
2372 current,
2373 last;
2374
2375 if (reference_vector)
2376 *reference_vector=NULL;
2377 if (info)
2378 *info=NULL;
2379 current=0;
2380 last=0;
2381 image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2382 if (info && (SvTYPE(reference) == SVt_PVAV))
2383 *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2384 exception);
2385 return(image);
2386}
2387
2388/*
2389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2390% %
2391% %
2392% %
2393% s t r E Q c a s e %
2394% %
2395% %
2396% %
2397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2398%
2399% strEQcase() compares two strings and returns 0 if they are the
2400% same or if the second string runs out first. The comparison is case
2401% insensitive.
2402%
2403% The format of the strEQcase routine is:
2404%
2405% ssize_t strEQcase(const char *p,const char *q)
2406%
2407% A description of each parameter follows:
2408%
2409% o p: a character string.
2410%
2411% o q: a character string.
2412%
2413%
2414*/
2415static ssize_t strEQcase(const char *p,const char *q)
2416{
2417 char
2418 c;
2419
2420 register ssize_t
2421 i;
2422
2423 for (i=0 ; (c=(*q)) != 0; i++)
2424 {
2425 if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2426 (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2427 return(0);
2428 p++;
2429 q++;
2430 }
2431 return(((*q == 0) && (*p == 0)) ? i : 0);
2432}
2433
2434/*
2435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2436% %
2437% %
2438% %
2439% I m a g e : : M a g i c k %
2440% %
2441% %
2442% %
2443%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2444%
2445%
2446*/
2447MODULE = Image::Magick PACKAGE = Image::Magick
2448
2449PROTOTYPES: ENABLE
2450
2451BOOT:
2452 MagickCoreGenesis("PerlMagick",MagickFalse);
2453 SetWarningHandler(NULL);
2454 SetErrorHandler(NULL);
2455 magick_registry=NewSplayTree((int (*)(const void *,const void *))
2456 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2457
2458void
2459UNLOAD()
2460 PPCODE:
2461 {
2462 if (magick_registry != (SplayTreeInfo *) NULL)
2463 magick_registry=DestroySplayTree(magick_registry);
2464 MagickCoreTerminus();
2465 }
2466
2467double
2468constant(name,argument)
2469 char *name
2470 ssize_t argument
2471
2472#
2473###############################################################################
2474# #
2475# #
2476# #
2477# A n i m a t e #
2478# #
2479# #
2480# #
2481###############################################################################
2482#
2483#
2484void
2485Animate(ref,...)
2486 Image::Magick ref=NO_INIT
2487 ALIAS:
2488 AnimateImage = 1
2489 animate = 2
2490 animateimage = 3
2491 PPCODE:
2492 {
2493 ExceptionInfo
2494 *exception;
2495
2496 Image
2497 *image;
2498
2499 register ssize_t
2500 i;
2501
2502 struct PackageInfo
2503 *info,
2504 *package_info;
2505
2506 SV
2507 *perl_exception,
2508 *reference;
2509
2510 PERL_UNUSED_VAR(ref);
2511 PERL_UNUSED_VAR(ix);
2512 exception=AcquireExceptionInfo();
2513 perl_exception=newSVpv("",0);
2514 package_info=(struct PackageInfo *) NULL;
2515 if (sv_isobject(ST(0)) == 0)
2516 {
2517 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2518 PackageName);
2519 goto PerlException;
2520 }
2521 reference=SvRV(ST(0));
2522 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2523 if (image == (Image *) NULL)
2524 {
2525 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2526 PackageName);
2527 goto PerlException;
2528 }
2529 package_info=ClonePackageInfo(info,exception);
2530 if (items == 2)
2531 SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2532 else
2533 if (items > 2)
2534 for (i=2; i < items; i+=2)
2535 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2536 exception);
2537 (void) AnimateImages(package_info->image_info,image,exception);
2538 (void) CatchImageException(image);
2539
2540 PerlException:
2541 if (package_info != (struct PackageInfo *) NULL)
2542 DestroyPackageInfo(package_info);
2543 InheritPerlException(exception,perl_exception);
2544 exception=DestroyExceptionInfo(exception);
2545 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2546 SvPOK_on(perl_exception);
2547 ST(0)=sv_2mortal(perl_exception);
2548 XSRETURN(1);
2549 }
2550
2551#
2552###############################################################################
2553# #
2554# #
2555# #
2556# A p p e n d #
2557# #
2558# #
2559# #
2560###############################################################################
2561#
2562#
2563void
2564Append(ref,...)
2565 Image::Magick ref=NO_INIT
2566 ALIAS:
2567 AppendImage = 1
2568 append = 2
2569 appendimage = 3
2570 PPCODE:
2571 {
2572 AV
2573 *av;
2574
2575 char
2576 *attribute;
2577
2578 ExceptionInfo
2579 *exception;
2580
2581 HV
2582 *hv;
2583
2584 Image
2585 *image;
2586
2587 register ssize_t
2588 i;
2589
2590 ssize_t
2591 stack;
2592
2593 struct PackageInfo
2594 *info;
2595
2596 SV
2597 *av_reference,
2598 *perl_exception,
2599 *reference,
2600 *rv,
2601 *sv;
2602
2603 PERL_UNUSED_VAR(ref);
2604 PERL_UNUSED_VAR(ix);
2605 exception=AcquireExceptionInfo();
2606 perl_exception=newSVpv("",0);
2607 sv=NULL;
2608 attribute=NULL;
2609 av=NULL;
2610 if (sv_isobject(ST(0)) == 0)
2611 {
2612 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2613 PackageName);
2614 goto PerlException;
2615 }
2616 reference=SvRV(ST(0));
2617 hv=SvSTASH(reference);
2618 av=newAV();
2619 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2620 SvREFCNT_dec(av);
2621 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2622 if (image == (Image *) NULL)
2623 {
2624 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2625 PackageName);
2626 goto PerlException;
2627 }
2628 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2629 /*
2630 Get options.
2631 */
2632 stack=MagickTrue;
2633 for (i=2; i < items; i+=2)
2634 {
2635 attribute=(char *) SvPV(ST(i-1),na);
2636 switch (*attribute)
2637 {
2638 case 'S':
2639 case 's':
2640 {
2641 if (LocaleCompare(attribute,"stack") == 0)
2642 {
2643 stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2644 SvPV(ST(i),na));
2645 if (stack < 0)
2646 {
2647 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2648 SvPV(ST(i),na));
2649 return;
2650 }
2651 break;
2652 }
2653 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2654 attribute);
2655 break;
2656 }
2657 default:
2658 {
2659 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2660 attribute);
2661 break;
2662 }
2663 }
2664 }
2665 image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2666 if (image == (Image *) NULL)
2667 goto PerlException;
2668 for ( ; image; image=image->next)
2669 {
2670 AddImageToRegistry(sv,image);
2671 rv=newRV(sv);
2672 av_push(av,sv_bless(rv,hv));
2673 SvREFCNT_dec(sv);
2674 }
2675 exception=DestroyExceptionInfo(exception);
2676 ST(0)=av_reference;
2677 SvREFCNT_dec(perl_exception);
2678 XSRETURN(1);
2679
2680 PerlException:
2681 InheritPerlException(exception,perl_exception);
2682 exception=DestroyExceptionInfo(exception);
2683 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2684 SvPOK_on(perl_exception);
2685 ST(0)=sv_2mortal(perl_exception);
2686 XSRETURN(1);
2687 }
2688
2689#
2690###############################################################################
2691# #
2692# #
2693# #
2694# A v e r a g e #
2695# #
2696# #
2697# #
2698###############################################################################
2699#
2700#
2701void
2702Average(ref)
2703 Image::Magick ref=NO_INIT
2704 ALIAS:
2705 AverageImage = 1
2706 average = 2
2707 averageimage = 3
2708 PPCODE:
2709 {
2710 AV
2711 *av;
2712
2713 char
2714 *p;
2715
2716 ExceptionInfo
2717 *exception;
2718
2719 HV
2720 *hv;
2721
2722 Image
2723 *image;
2724
2725 struct PackageInfo
2726 *info;
2727
2728 SV
2729 *perl_exception,
2730 *reference,
2731 *rv,
2732 *sv;
2733
2734 PERL_UNUSED_VAR(ref);
2735 PERL_UNUSED_VAR(ix);
2736 exception=AcquireExceptionInfo();
2737 perl_exception=newSVpv("",0);
2738 sv=NULL;
2739 if (sv_isobject(ST(0)) == 0)
2740 {
2741 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2742 PackageName);
2743 goto PerlException;
2744 }
2745 reference=SvRV(ST(0));
2746 hv=SvSTASH(reference);
2747 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2748 if (image == (Image *) NULL)
2749 {
2750 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2751 PackageName);
2752 goto PerlException;
2753 }
2754 image=EvaluateImages(image,MeanEvaluateOperator,exception);
2755 if (image == (Image *) NULL)
2756 goto PerlException;
2757 /*
2758 Create blessed Perl array for the returned image.
2759 */
2760 av=newAV();
2761 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2762 SvREFCNT_dec(av);
2763 AddImageToRegistry(sv,image);
2764 rv=newRV(sv);
2765 av_push(av,sv_bless(rv,hv));
2766 SvREFCNT_dec(sv);
2767 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00002768 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2769 "average-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00002770 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2771 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00002772 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00002773 SetImageInfo(info->image_info,0,exception);
2774 exception=DestroyExceptionInfo(exception);
2775 SvREFCNT_dec(perl_exception);
2776 XSRETURN(1);
2777
2778 PerlException:
2779 InheritPerlException(exception,perl_exception);
2780 exception=DestroyExceptionInfo(exception);
2781 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2782 SvPOK_on(perl_exception);
2783 ST(0)=sv_2mortal(perl_exception);
2784 XSRETURN(1);
2785 }
2786
2787#
2788###############################################################################
2789# #
2790# #
2791# #
2792# B l o b T o I m a g e #
2793# #
2794# #
2795# #
2796###############################################################################
2797#
2798#
2799void
2800BlobToImage(ref,...)
2801 Image::Magick ref=NO_INIT
2802 ALIAS:
2803 BlobToImage = 1
2804 blobtoimage = 2
2805 blobto = 3
2806 PPCODE:
2807 {
2808 AV
2809 *av;
2810
2811 char
2812 **keep,
2813 **list;
2814
2815 ExceptionInfo
2816 *exception;
2817
2818 HV
2819 *hv;
2820
2821 Image
2822 *image;
2823
2824 register char
2825 **p;
2826
2827 register ssize_t
2828 i;
2829
2830 ssize_t
2831 ac,
2832 n,
2833 number_images;
2834
2835 STRLEN
2836 *length;
2837
2838 struct PackageInfo
2839 *info;
2840
2841 SV
2842 *perl_exception,
2843 *reference,
2844 *rv,
2845 *sv;
2846
2847 PERL_UNUSED_VAR(ref);
2848 PERL_UNUSED_VAR(ix);
2849 exception=AcquireExceptionInfo();
2850 perl_exception=newSVpv("",0);
2851 sv=NULL;
2852 number_images=0;
2853 ac=(items < 2) ? 1 : items-1;
2854 length=(STRLEN *) NULL;
2855 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2856 if (list == (char **) NULL)
2857 {
2858 ThrowPerlException(exception,ResourceLimitError,
2859 "MemoryAllocationFailed",PackageName);
2860 goto PerlException;
2861 }
2862 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2863 if (length == (STRLEN *) NULL)
2864 {
2865 ThrowPerlException(exception,ResourceLimitError,
2866 "MemoryAllocationFailed",PackageName);
2867 goto PerlException;
2868 }
2869 if (sv_isobject(ST(0)) == 0)
2870 {
2871 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2872 PackageName);
2873 goto PerlException;
2874 }
2875 reference=SvRV(ST(0));
2876 hv=SvSTASH(reference);
2877 if (SvTYPE(reference) != SVt_PVAV)
2878 {
2879 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2880 PackageName);
2881 goto PerlException;
2882 }
2883 av=(AV *) reference;
2884 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2885 exception);
2886 n=1;
2887 if (items <= 1)
2888 {
2889 ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2890 goto PerlException;
2891 }
2892 for (n=0, i=0; i < ac; i++)
2893 {
2894 list[n]=(char *) (SvPV(ST(i+1),length[n]));
2895 if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2896 {
2897 list[n]=(char *) (SvPV(ST(i+2),length[n]));
2898 continue;
2899 }
2900 n++;
2901 }
2902 list[n]=(char *) NULL;
2903 keep=list;
2904 for (i=number_images=0; i < n; i++)
2905 {
2906 image=BlobToImage(info->image_info,list[i],length[i],exception);
2907 if (image == (Image *) NULL)
2908 break;
2909 for ( ; image; image=image->next)
2910 {
2911 AddImageToRegistry(sv,image);
2912 rv=newRV(sv);
2913 av_push(av,sv_bless(rv,hv));
2914 SvREFCNT_dec(sv);
2915 number_images++;
2916 }
2917 }
2918 /*
2919 Free resources.
2920 */
2921 for (i=0; i < n; i++)
2922 if (list[i] != (char *) NULL)
2923 for (p=keep; list[i] != *p++; )
2924 if (*p == (char *) NULL)
2925 {
2926 list[i]=(char *) RelinquishMagickMemory(list[i]);
2927 break;
2928 }
2929
2930 PerlException:
2931 if (list)
2932 list=(char **) RelinquishMagickMemory(list);
2933 if (length)
2934 length=(STRLEN *) RelinquishMagickMemory(length);
2935 InheritPerlException(exception,perl_exception);
2936 exception=DestroyExceptionInfo(exception);
2937 sv_setiv(perl_exception,(IV) number_images);
2938 SvPOK_on(perl_exception);
2939 ST(0)=sv_2mortal(perl_exception);
2940 XSRETURN(1);
2941 }
2942
2943#
2944###############################################################################
2945# #
2946# #
2947# #
2948# C h a n n e l F x #
2949# #
2950# #
2951# #
2952###############################################################################
2953#
2954#
2955void
2956ChannelFx(ref,...)
2957 Image::Magick ref=NO_INIT
2958 ALIAS:
2959 ChannelFxImage = 1
2960 channelfx = 2
2961 channelfximage = 3
2962 PPCODE:
2963 {
2964 AV
2965 *av;
2966
2967 char
2968 *attribute,
cristy151b66d2015-04-15 10:50:31 +00002969 expression[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00002970
2971 ChannelType
2972 channel,
2973 channel_mask;
2974
2975 ExceptionInfo
2976 *exception;
2977
2978 HV
2979 *hv;
2980
2981 Image
2982 *image;
2983
2984 register ssize_t
2985 i;
2986
2987 struct PackageInfo
2988 *info;
2989
2990 SV
2991 *av_reference,
2992 *perl_exception,
2993 *reference,
2994 *rv,
2995 *sv;
2996
2997 PERL_UNUSED_VAR(ref);
2998 PERL_UNUSED_VAR(ix);
2999 exception=AcquireExceptionInfo();
3000 perl_exception=newSVpv("",0);
3001 sv=NULL;
3002 attribute=NULL;
3003 av=NULL;
3004 if (sv_isobject(ST(0)) == 0)
3005 {
3006 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3007 PackageName);
3008 goto PerlException;
3009 }
3010 reference=SvRV(ST(0));
3011 hv=SvSTASH(reference);
3012 av=newAV();
3013 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3014 SvREFCNT_dec(av);
3015 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3016 if (image == (Image *) NULL)
3017 {
3018 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3019 PackageName);
3020 goto PerlException;
3021 }
3022 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3023 /*
3024 Get options.
3025 */
3026 channel=DefaultChannels;
cristy151b66d2015-04-15 10:50:31 +00003027 (void) CopyMagickString(expression,"u",MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003028 if (items == 2)
cristy151b66d2015-04-15 10:50:31 +00003029 (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003030 else
3031 for (i=2; i < items; i+=2)
3032 {
3033 attribute=(char *) SvPV(ST(i-1),na);
3034 switch (*attribute)
3035 {
3036 case 'C':
3037 case 'c':
3038 {
3039 if (LocaleCompare(attribute,"channel") == 0)
3040 {
3041 ssize_t
3042 option;
3043
3044 option=ParseChannelOption(SvPV(ST(i),na));
3045 if (option < 0)
3046 {
3047 ThrowPerlException(exception,OptionError,
3048 "UnrecognizedType",SvPV(ST(i),na));
3049 return;
3050 }
3051 channel=(ChannelType) option;
3052 break;
3053 }
3054 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3055 attribute);
3056 break;
3057 }
3058 case 'E':
3059 case 'e':
3060 {
3061 if (LocaleCompare(attribute,"expression") == 0)
3062 {
3063 (void) CopyMagickString(expression,SvPV(ST(i),na),
cristy151b66d2015-04-15 10:50:31 +00003064 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003065 break;
3066 }
3067 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3068 attribute);
3069 break;
3070 }
3071 default:
3072 {
3073 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3074 attribute);
3075 break;
3076 }
3077 }
3078 }
3079 channel_mask=SetImageChannelMask(image,channel);
3080 image=ChannelFxImage(image,expression,exception);
3081 if (image != (Image *) NULL)
3082 (void) SetImageChannelMask(image,channel_mask);
3083 if (image == (Image *) NULL)
3084 goto PerlException;
3085 for ( ; image; image=image->next)
3086 {
3087 AddImageToRegistry(sv,image);
3088 rv=newRV(sv);
3089 av_push(av,sv_bless(rv,hv));
3090 SvREFCNT_dec(sv);
3091 }
3092 exception=DestroyExceptionInfo(exception);
3093 ST(0)=av_reference;
3094 SvREFCNT_dec(perl_exception); /* can't return warning messages */
3095 XSRETURN(1);
3096
3097 PerlException:
3098 InheritPerlException(exception,perl_exception);
3099 exception=DestroyExceptionInfo(exception);
3100 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3101 SvPOK_on(perl_exception);
3102 ST(0)=sv_2mortal(perl_exception);
3103 XSRETURN(1);
3104 }
3105
3106#
3107###############################################################################
3108# #
3109# #
3110# #
3111# C l o n e #
3112# #
3113# #
3114# #
3115###############################################################################
3116#
3117#
3118void
3119Clone(ref)
3120 Image::Magick ref=NO_INIT
3121 ALIAS:
3122 CopyImage = 1
3123 copy = 2
3124 copyimage = 3
3125 CloneImage = 4
3126 clone = 5
3127 cloneimage = 6
3128 Clone = 7
3129 PPCODE:
3130 {
3131 AV
3132 *av;
3133
3134 ExceptionInfo
3135 *exception;
3136
3137 HV
3138 *hv;
3139
3140 Image
3141 *clone,
3142 *image;
3143
3144 struct PackageInfo
3145 *info;
3146
3147 SV
3148 *perl_exception,
3149 *reference,
3150 *rv,
3151 *sv;
3152
3153 PERL_UNUSED_VAR(ref);
3154 PERL_UNUSED_VAR(ix);
3155 exception=AcquireExceptionInfo();
3156 perl_exception=newSVpv("",0);
3157 sv=NULL;
3158 if (sv_isobject(ST(0)) == 0)
3159 {
3160 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3161 PackageName);
3162 goto PerlException;
3163 }
3164 reference=SvRV(ST(0));
3165 hv=SvSTASH(reference);
3166 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3167 if (image == (Image *) NULL)
3168 {
3169 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3170 PackageName);
3171 goto PerlException;
3172 }
3173 /*
3174 Create blessed Perl array for the returned image.
3175 */
3176 av=newAV();
3177 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3178 SvREFCNT_dec(av);
3179 for ( ; image; image=image->next)
3180 {
3181 clone=CloneImage(image,0,0,MagickTrue,exception);
3182 if (clone == (Image *) NULL)
3183 break;
3184 AddImageToRegistry(sv,clone);
3185 rv=newRV(sv);
3186 av_push(av,sv_bless(rv,hv));
3187 SvREFCNT_dec(sv);
3188 }
3189 exception=DestroyExceptionInfo(exception);
3190 SvREFCNT_dec(perl_exception);
3191 XSRETURN(1);
3192
3193 PerlException:
3194 InheritPerlException(exception,perl_exception);
3195 exception=DestroyExceptionInfo(exception);
3196 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3197 SvPOK_on(perl_exception);
3198 ST(0)=sv_2mortal(perl_exception);
3199 XSRETURN(1);
3200 }
3201
3202#
3203###############################################################################
3204# #
3205# #
3206# #
3207# C L O N E #
3208# #
3209# #
3210# #
3211###############################################################################
3212#
3213#
3214void
3215CLONE(ref,...)
3216 SV *ref;
3217 CODE:
3218 {
3219 PERL_UNUSED_VAR(ref);
3220 if (magick_registry != (SplayTreeInfo *) NULL)
3221 {
3222 register Image
3223 *p;
3224
3225 ResetSplayTreeIterator(magick_registry);
3226 p=(Image *) GetNextKeyInSplayTree(magick_registry);
3227 while (p != (Image *) NULL)
3228 {
3229 ReferenceImage(p);
3230 p=(Image *) GetNextKeyInSplayTree(magick_registry);
3231 }
3232 }
3233 }
3234
3235#
3236###############################################################################
3237# #
3238# #
3239# #
3240# C o a l e s c e #
3241# #
3242# #
3243# #
3244###############################################################################
3245#
3246#
3247void
3248Coalesce(ref)
3249 Image::Magick ref=NO_INIT
3250 ALIAS:
3251 CoalesceImage = 1
3252 coalesce = 2
3253 coalesceimage = 3
3254 PPCODE:
3255 {
3256 AV
3257 *av;
3258
3259 ExceptionInfo
3260 *exception;
3261
3262 HV
3263 *hv;
3264
3265 Image
3266 *image;
3267
3268 struct PackageInfo
3269 *info;
3270
3271 SV
3272 *av_reference,
3273 *perl_exception,
3274 *reference,
3275 *rv,
3276 *sv;
3277
3278 PERL_UNUSED_VAR(ref);
3279 PERL_UNUSED_VAR(ix);
3280 exception=AcquireExceptionInfo();
3281 perl_exception=newSVpv("",0);
3282 sv=NULL;
3283 if (sv_isobject(ST(0)) == 0)
3284 {
3285 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3286 PackageName);
3287 goto PerlException;
3288 }
3289 reference=SvRV(ST(0));
3290 hv=SvSTASH(reference);
3291 av=newAV();
3292 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3293 SvREFCNT_dec(av);
3294 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3295 if (image == (Image *) NULL)
3296 {
3297 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3298 PackageName);
3299 goto PerlException;
3300 }
3301 image=CoalesceImages(image,exception);
3302 if (image == (Image *) NULL)
3303 goto PerlException;
3304 for ( ; image; image=image->next)
3305 {
3306 AddImageToRegistry(sv,image);
3307 rv=newRV(sv);
3308 av_push(av,sv_bless(rv,hv));
3309 SvREFCNT_dec(sv);
3310 }
3311 exception=DestroyExceptionInfo(exception);
3312 ST(0)=av_reference;
3313 SvREFCNT_dec(perl_exception);
3314 XSRETURN(1);
3315
3316 PerlException:
3317 InheritPerlException(exception,perl_exception);
3318 exception=DestroyExceptionInfo(exception);
3319 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3320 SvPOK_on(perl_exception);
3321 ST(0)=sv_2mortal(perl_exception);
3322 XSRETURN(1);
3323 }
3324
3325#
3326###############################################################################
3327# #
3328# #
3329# #
3330# C o m p a r e #
3331# #
3332# #
3333# #
3334###############################################################################
3335#
3336#
3337void
3338Compare(ref,...)
3339 Image::Magick ref=NO_INIT
3340 ALIAS:
3341 CompareImages = 1
3342 compare = 2
3343 compareimage = 3
3344 PPCODE:
3345 {
3346 AV
3347 *av;
3348
3349 char
3350 *attribute;
3351
3352 double
3353 distortion;
3354
3355 ExceptionInfo
3356 *exception;
3357
3358 HV
3359 *hv;
3360
3361 Image
3362 *difference_image,
3363 *image,
3364 *reconstruct_image;
3365
3366 MetricType
3367 metric;
3368
3369 register ssize_t
3370 i;
3371
3372 ssize_t
3373 option;
3374
3375 struct PackageInfo
3376 *info;
3377
3378 SV
3379 *av_reference,
3380 *perl_exception,
3381 *reference,
3382 *rv,
3383 *sv;
3384
3385 PERL_UNUSED_VAR(ref);
3386 PERL_UNUSED_VAR(ix);
3387 exception=AcquireExceptionInfo();
3388 perl_exception=newSVpv("",0);
3389 sv=NULL;
3390 av=NULL;
3391 attribute=NULL;
3392 if (sv_isobject(ST(0)) == 0)
3393 {
3394 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3395 PackageName);
3396 goto PerlException;
3397 }
3398 reference=SvRV(ST(0));
3399 hv=SvSTASH(reference);
3400 av=newAV();
3401 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3402 SvREFCNT_dec(av);
3403 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3404 if (image == (Image *) NULL)
3405 {
3406 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3407 PackageName);
3408 goto PerlException;
3409 }
3410 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3411 /*
3412 Get attribute.
3413 */
3414 reconstruct_image=image;
3415 metric=RootMeanSquaredErrorMetric;
3416 for (i=2; i < items; i+=2)
3417 {
3418 attribute=(char *) SvPV(ST(i-1),na);
3419 switch (*attribute)
3420 {
3421 case 'C':
3422 case 'c':
3423 {
3424 if (LocaleCompare(attribute,"channel") == 0)
3425 {
3426 ssize_t
3427 option;
3428
3429 option=ParseChannelOption(SvPV(ST(i),na));
3430 if (option < 0)
3431 {
3432 ThrowPerlException(exception,OptionError,
3433 "UnrecognizedType",SvPV(ST(i),na));
3434 return;
3435 }
cristybcd59342015-06-07 14:07:19 +00003436 (void) SetPixelChannelMask(image,(ChannelType) option);
cristy4a3ce0a2013-08-03 20:06:59 +00003437 break;
3438 }
3439 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3440 attribute);
3441 break;
3442 }
3443 case 'F':
3444 case 'f':
3445 {
3446 if (LocaleCompare(attribute,"fuzz") == 0)
3447 {
3448 image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3449 break;
3450 }
3451 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3452 attribute);
3453 break;
3454 }
3455 case 'I':
3456 case 'i':
3457 {
3458 if (LocaleCompare(attribute,"image") == 0)
3459 {
3460 reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3461 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3462 break;
3463 }
3464 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3465 attribute);
3466 break;
3467 }
3468 case 'M':
3469 case 'm':
3470 {
3471 if (LocaleCompare(attribute,"metric") == 0)
3472 {
3473 option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3474 SvPV(ST(i),na));
3475 if (option < 0)
3476 {
3477 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3478 SvPV(ST(i),na));
3479 break;
3480 }
3481 metric=(MetricType) option;
3482 break;
3483 }
3484 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3485 attribute);
3486 break;
3487 }
3488 default:
3489 {
3490 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3491 attribute);
3492 break;
3493 }
3494 }
3495 }
3496 difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3497 exception);
3498 if (difference_image != (Image *) NULL)
3499 {
3500 difference_image->error.mean_error_per_pixel=distortion;
3501 AddImageToRegistry(sv,difference_image);
3502 rv=newRV(sv);
3503 av_push(av,sv_bless(rv,hv));
3504 SvREFCNT_dec(sv);
3505 }
3506 exception=DestroyExceptionInfo(exception);
3507 ST(0)=av_reference;
3508 SvREFCNT_dec(perl_exception); /* can't return warning messages */
3509 XSRETURN(1);
3510
3511 PerlException:
3512 InheritPerlException(exception,perl_exception);
3513 exception=DestroyExceptionInfo(exception);
3514 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3515 SvPOK_on(perl_exception);
3516 ST(0)=sv_2mortal(perl_exception);
3517 XSRETURN(1);
3518 }
3519
3520#
3521###############################################################################
3522# #
3523# #
3524# #
cristy15655332013-10-06 00:27:33 +00003525# C o m p l e x I m a g e s #
3526# #
3527# #
3528# #
3529###############################################################################
3530#
3531#
3532void
3533ComplexImages(ref)
3534 Image::Magick ref=NO_INIT
3535 ALIAS:
3536 ComplexImages = 1
3537 compleximages = 2
3538 PPCODE:
3539 {
3540 AV
3541 *av;
3542
3543 char
3544 *attribute,
3545 *p;
3546
cristyfa21e9e2013-10-07 10:37:38 +00003547 ComplexOperator
3548 op;
3549
cristy15655332013-10-06 00:27:33 +00003550 ExceptionInfo
3551 *exception;
3552
3553 HV
3554 *hv;
3555
3556 Image
3557 *image;
3558
cristy15655332013-10-06 00:27:33 +00003559 register ssize_t
3560 i;
3561
3562 struct PackageInfo
3563 *info;
3564
3565 SV
3566 *perl_exception,
3567 *reference,
3568 *rv,
3569 *sv;
3570
3571 PERL_UNUSED_VAR(ref);
3572 PERL_UNUSED_VAR(ix);
3573 exception=AcquireExceptionInfo();
3574 perl_exception=newSVpv("",0);
3575 sv=NULL;
3576 if (sv_isobject(ST(0)) == 0)
3577 {
3578 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3579 PackageName);
3580 goto PerlException;
3581 }
3582 reference=SvRV(ST(0));
3583 hv=SvSTASH(reference);
3584 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3585 if (image == (Image *) NULL)
3586 {
3587 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3588 PackageName);
3589 goto PerlException;
3590 }
cristyfd168722013-10-07 15:59:31 +00003591 op=UndefinedComplexOperator;
cristy15655332013-10-06 00:27:33 +00003592 if (items == 2)
3593 {
3594 ssize_t
3595 in;
3596
3597 in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3598 SvPV(ST(1),na));
3599 if (in < 0)
3600 {
3601 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3602 SvPV(ST(1),na));
3603 return;
3604 }
cristyfa21e9e2013-10-07 10:37:38 +00003605 op=(ComplexOperator) in;
cristy15655332013-10-06 00:27:33 +00003606 }
3607 else
3608 for (i=2; i < items; i+=2)
3609 {
3610 attribute=(char *) SvPV(ST(i-1),na);
3611 switch (*attribute)
3612 {
3613 case 'O':
3614 case 'o':
3615 {
3616 if (LocaleCompare(attribute,"operator") == 0)
3617 {
3618 ssize_t
3619 in;
3620
3621 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3622 MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3623 if (in < 0)
3624 {
3625 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3626 SvPV(ST(i),na));
3627 return;
3628 }
cristyfa21e9e2013-10-07 10:37:38 +00003629 op=(ComplexOperator) in;
cristy15655332013-10-06 00:27:33 +00003630 break;
3631 }
3632 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3633 attribute);
3634 break;
3635 }
3636 default:
3637 {
3638 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3639 attribute);
3640 break;
3641 }
3642 }
3643 }
3644 image=ComplexImages(image,op,exception);
3645 if (image == (Image *) NULL)
3646 goto PerlException;
3647 /*
3648 Create blessed Perl array for the returned image.
3649 */
3650 av=newAV();
3651 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3652 SvREFCNT_dec(av);
3653 AddImageToRegistry(sv,image);
3654 rv=newRV(sv);
3655 av_push(av,sv_bless(rv,hv));
3656 SvREFCNT_dec(sv);
3657 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00003658 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3659 "complex-%.*s",(int) (MagickPathExtent-9),
cristy15655332013-10-06 00:27:33 +00003660 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3661 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00003662 MagickPathExtent);
cristy15655332013-10-06 00:27:33 +00003663 SetImageInfo(info->image_info,0,exception);
3664 exception=DestroyExceptionInfo(exception);
3665 SvREFCNT_dec(perl_exception);
3666 XSRETURN(1);
3667
3668 PerlException:
3669 InheritPerlException(exception,perl_exception);
3670 exception=DestroyExceptionInfo(exception);
3671 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3672 SvPOK_on(perl_exception);
3673 ST(0)=sv_2mortal(perl_exception);
3674 XSRETURN(1);
3675 }
3676
3677#
3678###############################################################################
3679# #
3680# #
3681# #
cristy4a3ce0a2013-08-03 20:06:59 +00003682# C o m p a r e L a y e r s #
3683# #
3684# #
3685# #
3686###############################################################################
3687#
3688#
3689void
3690CompareLayers(ref)
3691 Image::Magick ref=NO_INIT
3692 ALIAS:
3693 CompareImagesLayers = 1
3694 comparelayers = 2
3695 compareimagelayers = 3
3696 PPCODE:
3697 {
3698 AV
3699 *av;
3700
3701 char
3702 *attribute;
3703
3704 ExceptionInfo
3705 *exception;
3706
3707 HV
3708 *hv;
3709
3710 Image
3711 *image;
3712
3713 LayerMethod
3714 method;
3715
3716 register ssize_t
3717 i;
3718
3719 ssize_t
3720 option;
3721
3722 struct PackageInfo
3723 *info;
3724
3725 SV
3726 *av_reference,
3727 *perl_exception,
3728 *reference,
3729 *rv,
3730 *sv;
3731
3732 PERL_UNUSED_VAR(ref);
3733 PERL_UNUSED_VAR(ix);
3734 exception=AcquireExceptionInfo();
3735 perl_exception=newSVpv("",0);
3736 sv=NULL;
3737 if (sv_isobject(ST(0)) == 0)
3738 {
3739 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3740 PackageName);
3741 goto PerlException;
3742 }
3743 reference=SvRV(ST(0));
3744 hv=SvSTASH(reference);
3745 av=newAV();
3746 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3747 SvREFCNT_dec(av);
3748 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3749 if (image == (Image *) NULL)
3750 {
3751 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3752 PackageName);
3753 goto PerlException;
3754 }
3755 method=CompareAnyLayer;
3756 for (i=2; i < items; i+=2)
3757 {
3758 attribute=(char *) SvPV(ST(i-1),na);
3759 switch (*attribute)
3760 {
3761 case 'M':
3762 case 'm':
3763 {
3764 if (LocaleCompare(attribute,"method") == 0)
3765 {
3766 option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3767 SvPV(ST(i),na));
3768 if (option < 0)
3769 {
3770 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3771 SvPV(ST(i),na));
3772 break;
3773 }
3774 method=(LayerMethod) option;
3775 break;
3776 }
3777 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3778 attribute);
3779 break;
3780 }
3781 default:
3782 {
3783 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3784 attribute);
3785 break;
3786 }
3787 }
3788 }
3789 image=CompareImagesLayers(image,method,exception);
3790 if (image == (Image *) NULL)
3791 goto PerlException;
3792 for ( ; image; image=image->next)
3793 {
3794 AddImageToRegistry(sv,image);
3795 rv=newRV(sv);
3796 av_push(av,sv_bless(rv,hv));
3797 SvREFCNT_dec(sv);
3798 }
3799 exception=DestroyExceptionInfo(exception);
3800 ST(0)=av_reference;
3801 SvREFCNT_dec(perl_exception);
3802 XSRETURN(1);
3803
3804 PerlException:
3805 InheritPerlException(exception,perl_exception);
3806 exception=DestroyExceptionInfo(exception);
3807 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3808 SvPOK_on(perl_exception);
3809 ST(0)=sv_2mortal(perl_exception);
3810 XSRETURN(1);
3811 }
3812
3813#
3814###############################################################################
3815# #
3816# #
3817# #
3818# D e s t r o y #
3819# #
3820# #
3821# #
3822###############################################################################
3823#
3824#
3825void
3826DESTROY(ref)
3827 Image::Magick ref=NO_INIT
3828 PPCODE:
3829 {
3830 SV
3831 *reference;
3832
3833 PERL_UNUSED_VAR(ref);
3834 if (sv_isobject(ST(0)) == 0)
3835 croak("ReferenceIsNotMyType");
3836 reference=SvRV(ST(0));
3837 switch (SvTYPE(reference))
3838 {
3839 case SVt_PVAV:
3840 {
3841 char
cristy151b66d2015-04-15 10:50:31 +00003842 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00003843
3844 const SV
3845 *key;
3846
3847 HV
3848 *hv;
3849
3850 GV
3851 **gvp;
3852
3853 struct PackageInfo
3854 *info;
3855
3856 SV
3857 *sv;
3858
3859 /*
3860 Array (AV *) reference
3861 */
cristy151b66d2015-04-15 10:50:31 +00003862 (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
cristy4a3ce0a2013-08-03 20:06:59 +00003863 XS_VERSION,reference);
3864 hv=gv_stashpv(PackageName, FALSE);
3865 if (!hv)
3866 break;
3867 gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3868 if (!gvp)
3869 break;
3870 sv=GvSV(*gvp);
3871 if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3872 {
3873 info=INT2PTR(struct PackageInfo *,SvIV(sv));
3874 DestroyPackageInfo(info);
3875 }
3876 key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3877 (void) key;
3878 break;
3879 }
3880 case SVt_PVMG:
3881 {
3882 Image
3883 *image;
3884
3885 /*
3886 Blessed scalar = (Image *) SvIV(reference)
3887 */
3888 image=INT2PTR(Image *,SvIV(reference));
3889 if (image != (Image *) NULL)
3890 DeleteImageFromRegistry(reference,image);
3891 break;
3892 }
3893 default:
3894 break;
3895 }
3896 }
3897
3898#
3899###############################################################################
3900# #
3901# #
3902# #
3903# D i s p l a y #
3904# #
3905# #
3906# #
3907###############################################################################
3908#
3909#
3910void
3911Display(ref,...)
3912 Image::Magick ref=NO_INIT
3913 ALIAS:
3914 DisplayImage = 1
3915 display = 2
3916 displayimage = 3
3917 PPCODE:
3918 {
3919 ExceptionInfo
3920 *exception;
3921
3922 Image
3923 *image;
3924
3925 register ssize_t
3926 i;
3927
3928 struct PackageInfo
3929 *info,
3930 *package_info;
3931
3932 SV
3933 *perl_exception,
3934 *reference;
3935
3936 PERL_UNUSED_VAR(ref);
3937 PERL_UNUSED_VAR(ix);
3938 exception=AcquireExceptionInfo();
3939 perl_exception=newSVpv("",0);
3940 package_info=(struct PackageInfo *) NULL;
3941 if (sv_isobject(ST(0)) == 0)
3942 {
3943 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3944 PackageName);
3945 goto PerlException;
3946 }
3947 reference=SvRV(ST(0));
3948 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3949 if (image == (Image *) NULL)
3950 {
3951 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3952 PackageName);
3953 goto PerlException;
3954 }
3955 package_info=ClonePackageInfo(info,exception);
3956 if (items == 2)
3957 SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3958 else
3959 if (items > 2)
3960 for (i=2; i < items; i+=2)
3961 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3962 exception);
3963 (void) DisplayImages(package_info->image_info,image,exception);
3964 (void) CatchImageException(image);
3965
3966 PerlException:
3967 if (package_info != (struct PackageInfo *) NULL)
3968 DestroyPackageInfo(package_info);
3969 InheritPerlException(exception,perl_exception);
3970 exception=DestroyExceptionInfo(exception);
3971 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3972 SvPOK_on(perl_exception);
3973 ST(0)=sv_2mortal(perl_exception);
3974 XSRETURN(1);
3975 }
3976
3977#
3978###############################################################################
3979# #
3980# #
3981# #
3982# E v a l u a t e I m a g e s #
3983# #
3984# #
3985# #
3986###############################################################################
3987#
3988#
3989void
3990EvaluateImages(ref)
3991 Image::Magick ref=NO_INIT
3992 ALIAS:
3993 EvaluateImages = 1
3994 evaluateimages = 2
3995 PPCODE:
3996 {
3997 AV
3998 *av;
3999
4000 char
4001 *attribute,
4002 *p;
4003
4004 ExceptionInfo
4005 *exception;
4006
4007 HV
4008 *hv;
4009
4010 Image
4011 *image;
4012
4013 MagickEvaluateOperator
4014 op;
4015
4016 register ssize_t
4017 i;
4018
4019 struct PackageInfo
4020 *info;
4021
4022 SV
4023 *perl_exception,
4024 *reference,
4025 *rv,
4026 *sv;
4027
4028 PERL_UNUSED_VAR(ref);
4029 PERL_UNUSED_VAR(ix);
4030 exception=AcquireExceptionInfo();
4031 perl_exception=newSVpv("",0);
4032 sv=NULL;
4033 if (sv_isobject(ST(0)) == 0)
4034 {
4035 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4036 PackageName);
4037 goto PerlException;
4038 }
4039 reference=SvRV(ST(0));
4040 hv=SvSTASH(reference);
4041 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4042 if (image == (Image *) NULL)
4043 {
4044 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4045 PackageName);
4046 goto PerlException;
4047 }
4048 op=MeanEvaluateOperator;
4049 if (items == 2)
4050 {
4051 ssize_t
4052 in;
4053
4054 in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
4055 SvPV(ST(1),na));
4056 if (in < 0)
4057 {
4058 ThrowPerlException(exception,OptionError,"UnrecognizedType",
4059 SvPV(ST(1),na));
4060 return;
4061 }
4062 op=(MagickEvaluateOperator) in;
4063 }
4064 else
4065 for (i=2; i < items; i+=2)
4066 {
4067 attribute=(char *) SvPV(ST(i-1),na);
4068 switch (*attribute)
4069 {
4070 case 'O':
4071 case 'o':
4072 {
4073 if (LocaleCompare(attribute,"operator") == 0)
4074 {
4075 ssize_t
4076 in;
4077
4078 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4079 MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4080 if (in < 0)
4081 {
4082 ThrowPerlException(exception,OptionError,"UnrecognizedType",
4083 SvPV(ST(i),na));
4084 return;
4085 }
4086 op=(MagickEvaluateOperator) in;
4087 break;
4088 }
4089 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4090 attribute);
4091 break;
4092 }
4093 default:
4094 {
4095 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4096 attribute);
4097 break;
4098 }
4099 }
4100 }
4101 image=EvaluateImages(image,op,exception);
4102 if (image == (Image *) NULL)
4103 goto PerlException;
4104 /*
4105 Create blessed Perl array for the returned image.
4106 */
4107 av=newAV();
4108 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4109 SvREFCNT_dec(av);
4110 AddImageToRegistry(sv,image);
4111 rv=newRV(sv);
4112 av_push(av,sv_bless(rv,hv));
4113 SvREFCNT_dec(sv);
4114 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00004115 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4116 "evaluate-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00004117 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4118 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00004119 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004120 SetImageInfo(info->image_info,0,exception);
4121 exception=DestroyExceptionInfo(exception);
4122 SvREFCNT_dec(perl_exception);
4123 XSRETURN(1);
4124
4125 PerlException:
4126 InheritPerlException(exception,perl_exception);
4127 exception=DestroyExceptionInfo(exception);
4128 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4129 SvPOK_on(perl_exception);
4130 ST(0)=sv_2mortal(perl_exception);
4131 XSRETURN(1);
4132 }
4133
4134#
4135###############################################################################
4136# #
4137# #
4138# #
4139# F e a t u r e s #
4140# #
4141# #
4142# #
4143###############################################################################
4144#
4145#
4146void
4147Features(ref,...)
4148 Image::Magick ref=NO_INIT
4149 ALIAS:
4150 FeaturesImage = 1
4151 features = 2
4152 featuresimage = 3
4153 PPCODE:
4154 {
4155#define ChannelFeatures(channel,direction) \
4156{ \
Cristyb1710fe2017-02-11 13:51:48 -05004157 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004158 channel_features[channel].angular_second_moment[direction]); \
4159 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004160 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004161 channel_features[channel].contrast[direction]); \
4162 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004163 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004164 channel_features[channel].contrast[direction]); \
4165 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004166 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004167 channel_features[channel].variance_sum_of_squares[direction]); \
4168 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004169 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004170 channel_features[channel].inverse_difference_moment[direction]); \
4171 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004172 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004173 channel_features[channel].sum_average[direction]); \
4174 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004175 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004176 channel_features[channel].sum_variance[direction]); \
4177 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004178 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004179 channel_features[channel].sum_entropy[direction]); \
4180 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004181 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004182 channel_features[channel].entropy[direction]); \
4183 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004184 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004185 channel_features[channel].difference_variance[direction]); \
4186 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004187 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004188 channel_features[channel].difference_entropy[direction]); \
4189 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004190 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004191 channel_features[channel].measure_of_correlation_1[direction]); \
4192 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004193 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004194 channel_features[channel].measure_of_correlation_2[direction]); \
4195 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004196 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004197 channel_features[channel].maximum_correlation_coefficient[direction]); \
4198 PUSHs(sv_2mortal(newSVpv(message,0))); \
4199}
4200
4201 AV
4202 *av;
4203
4204 char
4205 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004206 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004207
4208 ChannelFeatures
4209 *channel_features;
4210
4211 double
4212 distance;
4213
4214 ExceptionInfo
4215 *exception;
4216
4217 Image
4218 *image;
4219
4220 register ssize_t
4221 i;
4222
4223 ssize_t
4224 count;
4225
4226 struct PackageInfo
4227 *info;
4228
4229 SV
4230 *perl_exception,
4231 *reference;
4232
4233 PERL_UNUSED_VAR(ref);
4234 PERL_UNUSED_VAR(ix);
4235 exception=AcquireExceptionInfo();
4236 perl_exception=newSVpv("",0);
4237 av=NULL;
4238 if (sv_isobject(ST(0)) == 0)
4239 {
4240 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4241 PackageName);
4242 goto PerlException;
4243 }
4244 reference=SvRV(ST(0));
4245 av=newAV();
4246 SvREFCNT_dec(av);
4247 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4248 if (image == (Image *) NULL)
4249 {
4250 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4251 PackageName);
4252 goto PerlException;
4253 }
cristy7dbd9262014-07-02 17:53:42 +00004254 distance=1.0;
cristy4a3ce0a2013-08-03 20:06:59 +00004255 for (i=2; i < items; i+=2)
4256 {
4257 attribute=(char *) SvPV(ST(i-1),na);
4258 switch (*attribute)
4259 {
4260 case 'D':
4261 case 'd':
4262 {
4263 if (LocaleCompare(attribute,"distance") == 0)
4264 {
4265 distance=StringToLong((char *) SvPV(ST(1),na));
4266 break;
4267 }
4268 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4269 attribute);
4270 break;
4271 }
4272 default:
4273 {
4274 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4275 attribute);
4276 break;
4277 }
4278 }
4279 }
4280 count=0;
4281 for ( ; image; image=image->next)
4282 {
Cristy5a854dc2017-02-11 15:43:46 -05004283 register ssize_t
4284 j;
4285
cristy4a3ce0a2013-08-03 20:06:59 +00004286 channel_features=GetImageFeatures(image,distance,exception);
4287 if (channel_features == (ChannelFeatures *) NULL)
4288 continue;
4289 count++;
Cristy5a854dc2017-02-11 15:43:46 -05004290 for (j=0; j < 4; j++)
cristy4a3ce0a2013-08-03 20:06:59 +00004291 {
Cristy5a854dc2017-02-11 15:43:46 -05004292 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
4293 {
4294 PixelChannel channel=GetPixelChannelChannel(image,i);
4295 PixelTrait traits=GetPixelChannelTraits(image,channel);
4296 if (traits == UndefinedPixelTrait)
4297 continue;
4298 EXTEND(sp,14*(i+1)*count);
4299 ChannelFeatures(channel,j);
4300 }
cristy4a3ce0a2013-08-03 20:06:59 +00004301 }
4302 channel_features=(ChannelFeatures *)
4303 RelinquishMagickMemory(channel_features);
4304 }
4305
4306 PerlException:
4307 InheritPerlException(exception,perl_exception);
4308 exception=DestroyExceptionInfo(exception);
4309 SvREFCNT_dec(perl_exception);
4310 }
4311
4312#
4313###############################################################################
4314# #
4315# #
4316# #
4317# F l a t t e n #
4318# #
4319# #
4320# #
4321###############################################################################
4322#
4323#
4324void
4325Flatten(ref)
4326 Image::Magick ref=NO_INIT
4327 ALIAS:
4328 FlattenImage = 1
4329 flatten = 2
4330 flattenimage = 3
4331 PPCODE:
4332 {
4333 AV
4334 *av;
4335
4336 char
4337 *attribute,
4338 *p;
4339
4340 ExceptionInfo
4341 *exception;
4342
4343 HV
4344 *hv;
4345
4346 Image
4347 *image;
4348
4349 PixelInfo
4350 background_color;
4351
4352 register ssize_t
4353 i;
4354
4355 struct PackageInfo
4356 *info;
4357
4358 SV
4359 *perl_exception,
4360 *reference,
4361 *rv,
4362 *sv;
4363
4364 PERL_UNUSED_VAR(ref);
4365 PERL_UNUSED_VAR(ix);
4366 exception=AcquireExceptionInfo();
4367 perl_exception=newSVpv("",0);
4368 sv=NULL;
4369 if (sv_isobject(ST(0)) == 0)
4370 {
4371 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4372 PackageName);
4373 goto PerlException;
4374 }
4375 reference=SvRV(ST(0));
4376 hv=SvSTASH(reference);
4377 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4378 if (image == (Image *) NULL)
4379 {
4380 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4381 PackageName);
4382 goto PerlException;
4383 }
4384 background_color=image->background_color;
4385 if (items == 2)
4386 (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4387 &background_color,exception);
4388 else
4389 for (i=2; i < items; i+=2)
4390 {
4391 attribute=(char *) SvPV(ST(i-1),na);
4392 switch (*attribute)
4393 {
4394 case 'B':
4395 case 'b':
4396 {
4397 if (LocaleCompare(attribute,"background") == 0)
4398 {
4399 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4400 AllCompliance,&background_color,exception);
4401 break;
4402 }
4403 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4404 attribute);
4405 break;
4406 }
4407 default:
4408 {
4409 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4410 attribute);
4411 break;
4412 }
4413 }
4414 }
4415 image->background_color=background_color;
4416 image=MergeImageLayers(image,FlattenLayer,exception);
4417 if (image == (Image *) NULL)
4418 goto PerlException;
4419 /*
4420 Create blessed Perl array for the returned image.
4421 */
4422 av=newAV();
4423 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4424 SvREFCNT_dec(av);
4425 AddImageToRegistry(sv,image);
4426 rv=newRV(sv);
4427 av_push(av,sv_bless(rv,hv));
4428 SvREFCNT_dec(sv);
4429 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00004430 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4431 "flatten-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00004432 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4433 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00004434 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004435 SetImageInfo(info->image_info,0,exception);
4436 exception=DestroyExceptionInfo(exception);
4437 SvREFCNT_dec(perl_exception);
4438 XSRETURN(1);
4439
4440 PerlException:
4441 InheritPerlException(exception,perl_exception);
4442 exception=DestroyExceptionInfo(exception);
4443 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4444 SvPOK_on(perl_exception); /* return messages in string context */
4445 ST(0)=sv_2mortal(perl_exception);
4446 XSRETURN(1);
4447 }
4448
4449#
4450###############################################################################
4451# #
4452# #
4453# #
4454# F x #
4455# #
4456# #
4457# #
4458###############################################################################
4459#
4460#
4461void
4462Fx(ref,...)
4463 Image::Magick ref=NO_INIT
4464 ALIAS:
4465 FxImage = 1
4466 fx = 2
4467 fximage = 3
4468 PPCODE:
4469 {
4470 AV
4471 *av;
4472
4473 char
4474 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004475 expression[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004476
4477 ChannelType
4478 channel,
4479 channel_mask;
4480
4481 ExceptionInfo
4482 *exception;
4483
4484 HV
4485 *hv;
4486
4487 Image
4488 *image;
4489
4490 register ssize_t
4491 i;
4492
4493 struct PackageInfo
4494 *info;
4495
4496 SV
4497 *av_reference,
4498 *perl_exception,
4499 *reference,
4500 *rv,
4501 *sv;
4502
4503 PERL_UNUSED_VAR(ref);
4504 PERL_UNUSED_VAR(ix);
4505 exception=AcquireExceptionInfo();
4506 perl_exception=newSVpv("",0);
4507 sv=NULL;
4508 attribute=NULL;
4509 av=NULL;
4510 if (sv_isobject(ST(0)) == 0)
4511 {
4512 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4513 PackageName);
4514 goto PerlException;
4515 }
4516 reference=SvRV(ST(0));
4517 hv=SvSTASH(reference);
4518 av=newAV();
4519 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4520 SvREFCNT_dec(av);
4521 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4522 if (image == (Image *) NULL)
4523 {
4524 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4525 PackageName);
4526 goto PerlException;
4527 }
4528 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4529 /*
4530 Get options.
4531 */
4532 channel=DefaultChannels;
cristy151b66d2015-04-15 10:50:31 +00004533 (void) CopyMagickString(expression,"u",MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004534 if (items == 2)
cristy151b66d2015-04-15 10:50:31 +00004535 (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004536 else
4537 for (i=2; i < items; i+=2)
4538 {
4539 attribute=(char *) SvPV(ST(i-1),na);
4540 switch (*attribute)
4541 {
4542 case 'C':
4543 case 'c':
4544 {
4545 if (LocaleCompare(attribute,"channel") == 0)
4546 {
4547 ssize_t
4548 option;
4549
4550 option=ParseChannelOption(SvPV(ST(i),na));
4551 if (option < 0)
4552 {
4553 ThrowPerlException(exception,OptionError,
4554 "UnrecognizedType",SvPV(ST(i),na));
4555 return;
4556 }
4557 channel=(ChannelType) option;
4558 break;
4559 }
4560 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4561 attribute);
4562 break;
4563 }
4564 case 'E':
4565 case 'e':
4566 {
4567 if (LocaleCompare(attribute,"expression") == 0)
4568 {
4569 (void) CopyMagickString(expression,SvPV(ST(i),na),
cristy151b66d2015-04-15 10:50:31 +00004570 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004571 break;
4572 }
4573 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4574 attribute);
4575 break;
4576 }
4577 default:
4578 {
4579 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4580 attribute);
4581 break;
4582 }
4583 }
4584 }
4585 channel_mask=SetImageChannelMask(image,channel);
4586 image=FxImage(image,expression,exception);
4587 if (image != (Image *) NULL)
4588 (void) SetImageChannelMask(image,channel_mask);
4589 if (image == (Image *) NULL)
4590 goto PerlException;
4591 for ( ; image; image=image->next)
4592 {
4593 AddImageToRegistry(sv,image);
4594 rv=newRV(sv);
4595 av_push(av,sv_bless(rv,hv));
4596 SvREFCNT_dec(sv);
4597 }
4598 exception=DestroyExceptionInfo(exception);
4599 ST(0)=av_reference;
4600 SvREFCNT_dec(perl_exception); /* can't return warning messages */
4601 XSRETURN(1);
4602
4603 PerlException:
4604 InheritPerlException(exception,perl_exception);
4605 exception=DestroyExceptionInfo(exception);
4606 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4607 SvPOK_on(perl_exception);
4608 ST(0)=sv_2mortal(perl_exception);
4609 XSRETURN(1);
4610 }
4611
4612#
4613###############################################################################
4614# #
4615# #
4616# #
4617# G e t #
4618# #
4619# #
4620# #
4621###############################################################################
4622#
4623#
4624void
4625Get(ref,...)
4626 Image::Magick ref=NO_INIT
4627 ALIAS:
4628 GetAttributes = 1
4629 GetAttribute = 2
4630 get = 3
4631 getattributes = 4
4632 getattribute = 5
4633 PPCODE:
4634 {
4635 char
4636 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004637 color[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004638
4639 const char
4640 *value;
4641
4642 ExceptionInfo
4643 *exception;
4644
4645 Image
4646 *image;
4647
4648 long
4649 j;
4650
4651 register ssize_t
4652 i;
4653
4654 struct PackageInfo
4655 *info;
4656
4657 SV
4658 *perl_exception,
4659 *reference,
4660 *s;
4661
4662 PERL_UNUSED_VAR(ref);
4663 PERL_UNUSED_VAR(ix);
4664 exception=AcquireExceptionInfo();
4665 perl_exception=newSVpv("",0);
4666 if (sv_isobject(ST(0)) == 0)
4667 {
4668 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4669 PackageName);
4670 XSRETURN_EMPTY;
4671 }
4672 reference=SvRV(ST(0));
4673 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4674 if (image == (Image *) NULL && !info)
4675 XSRETURN_EMPTY;
4676 EXTEND(sp,items);
4677 for (i=1; i < items; i++)
4678 {
4679 attribute=(char *) SvPV(ST(i),na);
4680 s=NULL;
4681 switch (*attribute)
4682 {
4683 case 'A':
4684 case 'a':
4685 {
4686 if (LocaleCompare(attribute,"adjoin") == 0)
4687 {
4688 if (info)
4689 s=newSViv((ssize_t) info->image_info->adjoin);
4690 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4691 continue;
4692 }
4693 if (LocaleCompare(attribute,"antialias") == 0)
4694 {
4695 if (info)
4696 s=newSViv((ssize_t) info->image_info->antialias);
4697 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4698 continue;
4699 }
4700 if (LocaleCompare(attribute,"area") == 0)
4701 {
4702 s=newSViv(GetMagickResource(AreaResource));
4703 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4704 continue;
4705 }
4706 if (LocaleCompare(attribute,"attenuate") == 0)
4707 {
4708 const char
4709 *value;
4710
4711 value=GetImageProperty(image,attribute,exception);
4712 if (value != (const char *) NULL)
4713 s=newSVpv(value,0);
4714 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4715 continue;
4716 }
4717 if (LocaleCompare(attribute,"authenticate") == 0)
4718 {
4719 if (info)
4720 {
4721 const char
4722 *option;
4723
4724 option=GetImageOption(info->image_info,attribute);
4725 if (option != (const char *) NULL)
4726 s=newSVpv(option,0);
4727 }
4728 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4729 continue;
4730 }
4731 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4732 attribute);
4733 break;
4734 }
4735 case 'B':
4736 case 'b':
4737 {
4738 if (LocaleCompare(attribute,"background") == 0)
4739 {
4740 if (image == (Image *) NULL)
4741 break;
cristy151b66d2015-04-15 10:50:31 +00004742 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004743 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4744 (double) image->background_color.green,
4745 (double) image->background_color.blue,
4746 (double) image->background_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004747 s=newSVpv(color,0);
4748 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4749 continue;
4750 }
4751 if (LocaleCompare(attribute,"base-columns") == 0)
4752 {
4753 if (image != (Image *) NULL)
4754 s=newSViv((ssize_t) image->magick_columns);
4755 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4756 continue;
4757 }
4758 if (LocaleCompare(attribute,"base-filename") == 0)
4759 {
4760 if (image != (Image *) NULL)
4761 s=newSVpv(image->magick_filename,0);
4762 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4763 continue;
4764 }
4765 if (LocaleCompare(attribute,"base-height") == 0)
4766 {
4767 if (image != (Image *) NULL)
4768 s=newSViv((ssize_t) image->magick_rows);
4769 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4770 continue;
4771 }
4772 if (LocaleCompare(attribute,"base-rows") == 0)
4773 {
4774 if (image != (Image *) NULL)
4775 s=newSViv((ssize_t) image->magick_rows);
4776 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4777 continue;
4778 }
4779 if (LocaleCompare(attribute,"base-width") == 0)
4780 {
4781 if (image != (Image *) NULL)
4782 s=newSViv((ssize_t) image->magick_columns);
4783 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4784 continue;
4785 }
4786 if (LocaleCompare(attribute,"blue-primary") == 0)
4787 {
4788 if (image == (Image *) NULL)
4789 break;
Cristyb1710fe2017-02-11 13:51:48 -05004790 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00004791 image->chromaticity.blue_primary.x,
4792 image->chromaticity.blue_primary.y);
4793 s=newSVpv(color,0);
4794 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4795 continue;
4796 }
4797 if (LocaleCompare(attribute,"bordercolor") == 0)
4798 {
4799 if (image == (Image *) NULL)
4800 break;
cristy151b66d2015-04-15 10:50:31 +00004801 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004802 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4803 (double) image->border_color.green,
4804 (double) image->border_color.blue,
4805 (double) image->border_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004806 s=newSVpv(color,0);
4807 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4808 continue;
4809 }
4810 if (LocaleCompare(attribute,"bounding-box") == 0)
4811 {
4812 char
cristy151b66d2015-04-15 10:50:31 +00004813 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004814
4815 RectangleInfo
4816 page;
4817
4818 if (image == (Image *) NULL)
4819 break;
4820 page=GetImageBoundingBox(image,exception);
cristy151b66d2015-04-15 10:50:31 +00004821 (void) FormatLocaleString(geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00004822 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4823 page.height,(double) page.x,(double) page.y);
4824 s=newSVpv(geometry,0);
4825 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4826 continue;
4827 }
4828 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4829 attribute);
4830 break;
4831 }
4832 case 'C':
4833 case 'c':
4834 {
4835 if (LocaleCompare(attribute,"class") == 0)
4836 {
4837 if (image == (Image *) NULL)
4838 break;
4839 s=newSViv(image->storage_class);
4840 (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4841 image->storage_class));
4842 SvIOK_on(s);
4843 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4844 continue;
4845 }
4846 if (LocaleCompare(attribute,"clip-mask") == 0)
4847 {
4848 if (image != (Image *) NULL)
4849 {
4850 Image
4851 *mask_image;
4852
4853 SV
4854 *sv;
4855
4856 sv=NULL;
4857 if (image->read_mask == MagickFalse)
4858 ClipImage(image,exception);
Cristyda6b91a2016-01-11 16:05:27 -05004859 mask_image=GetImageMask(image,ReadPixelMask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004860 if (mask_image != (Image *) NULL)
4861 {
4862 AddImageToRegistry(sv,mask_image);
4863 s=sv_bless(newRV(sv),SvSTASH(reference));
4864 }
4865 }
4866 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4867 continue;
4868 }
4869 if (LocaleCompare(attribute,"clip-path") == 0)
4870 {
4871 if (image != (Image *) NULL)
4872 {
4873 Image
4874 *mask_image;
4875
4876 SV
4877 *sv;
4878
4879 sv=NULL;
4880 if (image->read_mask != MagickFalse)
4881 ClipImage(image,exception);
Cristyda6b91a2016-01-11 16:05:27 -05004882 mask_image=GetImageMask(image,ReadPixelMask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004883 if (mask_image != (Image *) NULL)
4884 {
4885 AddImageToRegistry(sv,mask_image);
4886 s=sv_bless(newRV(sv),SvSTASH(reference));
4887 }
4888 }
4889 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4890 continue;
4891 }
4892 if (LocaleCompare(attribute,"compression") == 0)
4893 {
4894 j=info ? info->image_info->compression : image ?
4895 image->compression : UndefinedCompression;
4896 if (info)
4897 if (info->image_info->compression == UndefinedCompression)
4898 j=image->compression;
4899 s=newSViv(j);
4900 (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4901 j));
4902 SvIOK_on(s);
4903 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4904 continue;
4905 }
4906 if (LocaleCompare(attribute,"colorspace") == 0)
4907 {
4908 j=image ? image->colorspace : RGBColorspace;
4909 s=newSViv(j);
4910 (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4911 j));
4912 SvIOK_on(s);
4913 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4914 continue;
4915 }
4916 if (LocaleCompare(attribute,"colors") == 0)
4917 {
4918 if (image != (Image *) NULL)
4919 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4920 exception));
4921 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4922 continue;
4923 }
4924 if (LocaleNCompare(attribute,"colormap",8) == 0)
4925 {
4926 int
4927 items;
4928
4929 if (image == (Image *) NULL || !image->colormap)
4930 break;
4931 j=0;
4932 items=sscanf(attribute,"%*[^[][%ld",&j);
4933 (void) items;
4934 if (j > (ssize_t) image->colors)
4935 j%=image->colors;
cristy151b66d2015-04-15 10:50:31 +00004936 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004937 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4938 (double) image->colormap[j].green,
4939 (double) image->colormap[j].blue,
4940 (double) image->colormap[j].alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004941 s=newSVpv(color,0);
4942 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4943 continue;
4944 }
4945 if (LocaleCompare(attribute,"columns") == 0)
4946 {
4947 if (image != (Image *) NULL)
4948 s=newSViv((ssize_t) image->columns);
4949 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4950 continue;
4951 }
4952 if (LocaleCompare(attribute,"comment") == 0)
4953 {
4954 const char
4955 *value;
4956
Cristy935a4052017-03-31 17:45:37 -04004957 value=GetImageProperty(image,attribute,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004958 if (value != (const char *) NULL)
4959 s=newSVpv(value,0);
4960 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4961 continue;
4962 }
4963 if (LocaleCompare(attribute,"copyright") == 0)
4964 {
4965 s=newSVpv(GetMagickCopyright(),0);
4966 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4967 continue;
4968 }
4969 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4970 attribute);
4971 break;
4972 }
4973 case 'D':
4974 case 'd':
4975 {
4976 if (LocaleCompare(attribute,"density") == 0)
4977 {
4978 char
cristy151b66d2015-04-15 10:50:31 +00004979 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004980
4981 if (image == (Image *) NULL)
4982 break;
Cristyb1710fe2017-02-11 13:51:48 -05004983 (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00004984 image->resolution.x,image->resolution.y);
4985 s=newSVpv(geometry,0);
4986 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4987 continue;
4988 }
4989 if (LocaleCompare(attribute,"delay") == 0)
4990 {
4991 if (image != (Image *) NULL)
4992 s=newSViv((ssize_t) image->delay);
4993 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4994 continue;
4995 }
4996 if (LocaleCompare(attribute,"depth") == 0)
4997 {
4998 s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4999 if (image != (Image *) NULL)
5000 s=newSViv((ssize_t) GetImageDepth(image,exception));
5001 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5002 continue;
5003 }
5004 if (LocaleCompare(attribute,"directory") == 0)
5005 {
5006 if (image && image->directory)
5007 s=newSVpv(image->directory,0);
5008 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5009 continue;
5010 }
5011 if (LocaleCompare(attribute,"dispose") == 0)
5012 {
5013 if (image == (Image *) NULL)
5014 break;
5015
5016 s=newSViv(image->dispose);
5017 (void) sv_setpv(s,
5018 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
5019 SvIOK_on(s);
5020 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5021 continue;
5022 }
5023 if (LocaleCompare(attribute,"disk") == 0)
5024 {
5025 s=newSViv(GetMagickResource(DiskResource));
5026 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5027 continue;
5028 }
5029 if (LocaleCompare(attribute,"dither") == 0)
5030 {
5031 if (info)
5032 s=newSViv((ssize_t) info->image_info->dither);
5033 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5034 continue;
5035 }
5036 if (LocaleCompare(attribute,"display") == 0) /* same as server */
5037 {
5038 if (info && info->image_info->server_name)
5039 s=newSVpv(info->image_info->server_name,0);
5040 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5041 continue;
5042 }
5043 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5044 attribute);
5045 break;
5046 }
5047 case 'E':
5048 case 'e':
5049 {
5050 if (LocaleCompare(attribute,"elapsed-time") == 0)
5051 {
5052 if (image != (Image *) NULL)
5053 s=newSVnv(GetElapsedTime(&image->timer));
5054 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5055 continue;
5056 }
5057 if (LocaleCompare(attribute,"endian") == 0)
5058 {
5059 j=info ? info->image_info->endian : image ? image->endian :
5060 UndefinedEndian;
5061 s=newSViv(j);
5062 (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
5063 SvIOK_on(s);
5064 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5065 continue;
5066 }
5067 if (LocaleCompare(attribute,"error") == 0)
5068 {
5069 if (image != (Image *) NULL)
5070 s=newSVnv(image->error.mean_error_per_pixel);
5071 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5072 continue;
5073 }
5074 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5075 attribute);
5076 break;
5077 }
5078 case 'F':
5079 case 'f':
5080 {
5081 if (LocaleCompare(attribute,"filesize") == 0)
5082 {
5083 if (image != (Image *) NULL)
5084 s=newSViv((ssize_t) GetBlobSize(image));
5085 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5086 continue;
5087 }
5088 if (LocaleCompare(attribute,"filename") == 0)
5089 {
Cristy2273d6a2017-07-14 19:19:55 -04005090 if (info && *info->image_info->filename)
cristy4a3ce0a2013-08-03 20:06:59 +00005091 s=newSVpv(info->image_info->filename,0);
5092 if (image != (Image *) NULL)
5093 s=newSVpv(image->filename,0);
5094 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5095 continue;
5096 }
5097 if (LocaleCompare(attribute,"filter") == 0)
5098 {
5099 s=image ? newSViv(image->filter) : newSViv(0);
5100 (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5101 image->filter));
5102 SvIOK_on(s);
5103 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5104 continue;
5105 }
5106 if (LocaleCompare(attribute,"font") == 0)
5107 {
5108 if (info && info->image_info->font)
5109 s=newSVpv(info->image_info->font,0);
5110 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5111 continue;
5112 }
5113 if (LocaleCompare(attribute,"foreground") == 0)
5114 continue;
5115 if (LocaleCompare(attribute,"format") == 0)
5116 {
5117 const MagickInfo
5118 *magick_info;
5119
5120 magick_info=(const MagickInfo *) NULL;
5121 if (info && (*info->image_info->magick != '\0'))
5122 magick_info=GetMagickInfo(info->image_info->magick,exception);
5123 if (image != (Image *) NULL)
5124 magick_info=GetMagickInfo(image->magick,exception);
5125 if ((magick_info != (const MagickInfo *) NULL) &&
5126 (*magick_info->description != '\0'))
5127 s=newSVpv((char *) magick_info->description,0);
5128 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5129 continue;
5130 }
5131 if (LocaleCompare(attribute,"fuzz") == 0)
5132 {
5133 if (info)
5134 s=newSVnv(info->image_info->fuzz);
5135 if (image != (Image *) NULL)
5136 s=newSVnv(image->fuzz);
5137 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5138 continue;
5139 }
5140 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5141 attribute);
5142 break;
5143 }
5144 case 'G':
5145 case 'g':
5146 {
5147 if (LocaleCompare(attribute,"gamma") == 0)
5148 {
5149 if (image != (Image *) NULL)
5150 s=newSVnv(image->gamma);
5151 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5152 continue;
5153 }
5154 if (LocaleCompare(attribute,"geometry") == 0)
5155 {
5156 if (image && image->geometry)
5157 s=newSVpv(image->geometry,0);
5158 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5159 continue;
5160 }
5161 if (LocaleCompare(attribute,"gravity") == 0)
5162 {
5163 s=image ? newSViv(image->gravity) : newSViv(0);
5164 (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5165 image->gravity));
5166 SvIOK_on(s);
5167 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5168 continue;
5169 }
5170 if (LocaleCompare(attribute,"green-primary") == 0)
5171 {
5172 if (image == (Image *) NULL)
5173 break;
Cristyb1710fe2017-02-11 13:51:48 -05005174 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005175 image->chromaticity.green_primary.x,
5176 image->chromaticity.green_primary.y);
5177 s=newSVpv(color,0);
5178 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5179 continue;
5180 }
5181 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5182 attribute);
5183 break;
5184 }
5185 case 'H':
5186 case 'h':
5187 {
5188 if (LocaleCompare(attribute,"height") == 0)
5189 {
5190 if (image != (Image *) NULL)
5191 s=newSViv((ssize_t) image->rows);
5192 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5193 continue;
5194 }
5195 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5196 attribute);
5197 break;
5198 }
5199 case 'I':
5200 case 'i':
5201 {
5202 if (LocaleCompare(attribute,"icc") == 0)
5203 {
5204 if (image != (Image *) NULL)
5205 {
5206 const StringInfo
5207 *profile;
5208
5209 profile=GetImageProfile(image,"icc");
5210 if (profile != (StringInfo *) NULL)
5211 s=newSVpv((const char *) GetStringInfoDatum(profile),
5212 GetStringInfoLength(profile));
5213 }
5214 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5215 continue;
5216 }
5217 if (LocaleCompare(attribute,"icm") == 0)
5218 {
5219 if (image != (Image *) NULL)
5220 {
5221 const StringInfo
5222 *profile;
5223
5224 profile=GetImageProfile(image,"icm");
5225 if (profile != (const StringInfo *) NULL)
5226 s=newSVpv((const char *) GetStringInfoDatum(profile),
5227 GetStringInfoLength(profile));
5228 }
5229 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5230 continue;
5231 }
5232 if (LocaleCompare(attribute,"id") == 0)
5233 {
5234 if (image != (Image *) NULL)
5235 {
5236 char
cristy151b66d2015-04-15 10:50:31 +00005237 key[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005238
5239 MagickBooleanType
5240 status;
5241
5242 static ssize_t
5243 id = 0;
5244
cristy151b66d2015-04-15 10:50:31 +00005245 (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
cristy4a3ce0a2013-08-03 20:06:59 +00005246 id);
5247 status=SetImageRegistry(ImageRegistryType,key,image,
5248 exception);
5249 (void) status;
5250 s=newSViv(id++);
5251 }
5252 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5253 continue;
5254 }
5255 if (LocaleNCompare(attribute,"index",5) == 0)
5256 {
5257 char
cristy151b66d2015-04-15 10:50:31 +00005258 name[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005259
5260 int
5261 items;
5262
5263 long
5264 x,
5265 y;
5266
5267 register const Quantum
5268 *p;
5269
5270 CacheView
5271 *image_view;
5272
5273 if (image == (Image *) NULL)
5274 break;
5275 if (image->storage_class != PseudoClass)
5276 break;
5277 x=0;
5278 y=0;
5279 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5280 (void) items;
5281 image_view=AcquireVirtualCacheView(image,exception);
5282 p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5283 if (p != (const Quantum *) NULL)
5284 {
cristy151b66d2015-04-15 10:50:31 +00005285 (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
cristy4a3ce0a2013-08-03 20:06:59 +00005286 GetPixelIndex(image,p));
5287 s=newSVpv(name,0);
5288 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5289 }
5290 image_view=DestroyCacheView(image_view);
5291 continue;
5292 }
5293 if (LocaleCompare(attribute,"iptc") == 0)
5294 {
5295 if (image != (Image *) NULL)
5296 {
5297 const StringInfo
5298 *profile;
5299
5300 profile=GetImageProfile(image,"iptc");
5301 if (profile != (const StringInfo *) NULL)
5302 s=newSVpv((const char *) GetStringInfoDatum(profile),
5303 GetStringInfoLength(profile));
5304 }
5305 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5306 continue;
5307 }
5308 if (LocaleCompare(attribute,"iterations") == 0) /* same as loop */
5309 {
5310 if (image != (Image *) NULL)
5311 s=newSViv((ssize_t) image->iterations);
5312 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5313 continue;
5314 }
5315 if (LocaleCompare(attribute,"interlace") == 0)
5316 {
5317 j=info ? info->image_info->interlace : image ? image->interlace :
5318 UndefinedInterlace;
5319 s=newSViv(j);
5320 (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5321 j));
5322 SvIOK_on(s);
5323 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5324 continue;
5325 }
5326 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5327 attribute);
5328 break;
5329 }
5330 case 'L':
5331 case 'l':
5332 {
5333 if (LocaleCompare(attribute,"label") == 0)
5334 {
5335 const char
5336 *value;
5337
5338 if (image == (Image *) NULL)
5339 break;
Cristy935a4052017-03-31 17:45:37 -04005340 value=GetImageProperty(image,"Label",exception);
cristy4a3ce0a2013-08-03 20:06:59 +00005341 if (value != (const char *) NULL)
5342 s=newSVpv(value,0);
5343 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5344 continue;
5345 }
5346 if (LocaleCompare(attribute,"loop") == 0) /* same as iterations */
5347 {
5348 if (image != (Image *) NULL)
5349 s=newSViv((ssize_t) image->iterations);
5350 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5351 continue;
5352 }
5353 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5354 attribute);
5355 break;
5356 }
5357 case 'M':
5358 case 'm':
5359 {
5360 if (LocaleCompare(attribute,"magick") == 0)
5361 {
5362 if (info && *info->image_info->magick)
5363 s=newSVpv(info->image_info->magick,0);
5364 if (image != (Image *) NULL)
5365 s=newSVpv(image->magick,0);
5366 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5367 continue;
5368 }
5369 if (LocaleCompare(attribute,"map") == 0)
5370 {
5371 s=newSViv(GetMagickResource(MapResource));
5372 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5373 continue;
5374 }
5375 if (LocaleCompare(attribute,"maximum-error") == 0)
5376 {
5377 if (image != (Image *) NULL)
5378 s=newSVnv(image->error.normalized_maximum_error);
5379 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5380 continue;
5381 }
5382 if (LocaleCompare(attribute,"memory") == 0)
5383 {
5384 s=newSViv(GetMagickResource(MemoryResource));
5385 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5386 continue;
5387 }
5388 if (LocaleCompare(attribute,"mean-error") == 0)
5389 {
5390 if (image != (Image *) NULL)
5391 s=newSVnv(image->error.normalized_mean_error);
5392 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5393 continue;
5394 }
5395 if (LocaleCompare(attribute,"mime") == 0)
5396 {
5397 if (info && *info->image_info->magick)
5398 s=newSVpv(MagickToMime(info->image_info->magick),0);
5399 if (image != (Image *) NULL)
5400 s=newSVpv(MagickToMime(image->magick),0);
5401 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5402 continue;
5403 }
5404 if (LocaleCompare(attribute,"mattecolor") == 0)
5405 {
5406 if (image == (Image *) NULL)
5407 break;
cristy151b66d2015-04-15 10:50:31 +00005408 (void) FormatLocaleString(color,MagickPathExtent,
Cristy8645e042016-02-03 16:35:29 -05005409 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5410 (double) image->alpha_color.green,
5411 (double) image->alpha_color.blue,
5412 (double) image->alpha_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00005413 s=newSVpv(color,0);
5414 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5415 continue;
5416 }
5417 if (LocaleCompare(attribute,"matte") == 0)
5418 {
5419 if (image != (Image *) NULL)
cristy17f11b02014-12-20 19:37:04 +00005420 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
cristy4a3ce0a2013-08-03 20:06:59 +00005421 1 : 0);
5422 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5423 continue;
5424 }
5425 if (LocaleCompare(attribute,"mime") == 0)
5426 {
5427 const char
5428 *magick;
5429
5430 magick=NULL;
5431 if (info && *info->image_info->magick)
5432 magick=info->image_info->magick;
5433 if (image != (Image *) NULL)
5434 magick=image->magick;
5435 if (magick)
5436 {
5437 char
5438 *mime;
5439
5440 mime=MagickToMime(magick);
5441 s=newSVpv(mime,0);
5442 mime=(char *) RelinquishMagickMemory(mime);
5443 }
5444 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5445 continue;
5446 }
5447 if (LocaleCompare(attribute,"monochrome") == 0)
5448 {
5449 if (image == (Image *) NULL)
5450 continue;
5451 j=info ? info->image_info->monochrome :
cristy932cb072015-04-13 20:06:25 +00005452 SetImageMonochrome(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00005453 s=newSViv(j);
5454 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5455 continue;
5456 }
5457 if (LocaleCompare(attribute,"montage") == 0)
5458 {
5459 if (image && image->montage)
5460 s=newSVpv(image->montage,0);
5461 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5462 continue;
5463 }
5464 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5465 attribute);
5466 break;
5467 }
5468 case 'O':
5469 case 'o':
5470 {
5471 if (LocaleCompare(attribute,"orientation") == 0)
5472 {
5473 j=info ? info->image_info->orientation : image ?
5474 image->orientation : UndefinedOrientation;
5475 s=newSViv(j);
5476 (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5477 j));
5478 SvIOK_on(s);
5479 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5480 continue;
5481 }
5482 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5483 attribute);
5484 break;
5485 }
5486 case 'P':
5487 case 'p':
5488 {
5489 if (LocaleCompare(attribute,"page") == 0)
5490 {
5491 if (info && info->image_info->page)
5492 s=newSVpv(info->image_info->page,0);
5493 if (image != (Image *) NULL)
5494 {
5495 char
cristy151b66d2015-04-15 10:50:31 +00005496 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005497
cristy151b66d2015-04-15 10:50:31 +00005498 (void) FormatLocaleString(geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00005499 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5500 (double) image->page.height,(double) image->page.x,(double)
5501 image->page.y);
5502 s=newSVpv(geometry,0);
5503 }
5504 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5505 continue;
5506 }
5507 if (LocaleCompare(attribute,"page.x") == 0)
5508 {
5509 if (image != (Image *) NULL)
5510 s=newSViv((ssize_t) image->page.x);
5511 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5512 continue;
5513 }
5514 if (LocaleCompare(attribute,"page.y") == 0)
5515 {
5516 if (image != (Image *) NULL)
5517 s=newSViv((ssize_t) image->page.y);
5518 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5519 continue;
5520 }
5521 if (LocaleNCompare(attribute,"pixel",5) == 0)
5522 {
5523 char
cristy151b66d2015-04-15 10:50:31 +00005524 tuple[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005525
5526 int
5527 items;
5528
5529 long
5530 x,
5531 y;
5532
5533 register const Quantum
5534 *p;
5535
5536 if (image == (Image *) NULL)
5537 break;
5538 x=0;
5539 y=0;
5540 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5541 (void) items;
5542 p=GetVirtualPixels(image,x,y,1,1,exception);
5543 if (image->colorspace != CMYKColorspace)
cristy151b66d2015-04-15 10:50:31 +00005544 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
cristy4a3ce0a2013-08-03 20:06:59 +00005545 QuantumFormat "," QuantumFormat "," QuantumFormat,
5546 GetPixelRed(image,p),GetPixelGreen(image,p),
5547 GetPixelBlue(image,p),GetPixelAlpha(image,p));
5548 else
cristy151b66d2015-04-15 10:50:31 +00005549 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
cristy4a3ce0a2013-08-03 20:06:59 +00005550 QuantumFormat "," QuantumFormat "," QuantumFormat ","
5551 QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5552 GetPixelBlue(image,p),GetPixelBlack(image,p),
5553 GetPixelAlpha(image,p));
5554 s=newSVpv(tuple,0);
5555 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5556 continue;
5557 }
5558 if (LocaleCompare(attribute,"pointsize") == 0)
5559 {
5560 if (info)
5561 s=newSViv((ssize_t) info->image_info->pointsize);
5562 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5563 continue;
5564 }
Cristy798981a2020-02-17 12:07:15 -05005565 if (LocaleCompare(attribute,"precision") == 0)
5566 {
5567 s=newSViv((ssize_t) GetMagickPrecision());
5568 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5569 continue;
5570 }
cristy4a3ce0a2013-08-03 20:06:59 +00005571 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5572 attribute);
5573 break;
5574 }
5575 case 'Q':
5576 case 'q':
5577 {
5578 if (LocaleCompare(attribute,"quality") == 0)
5579 {
5580 if (info)
5581 s=newSViv((ssize_t) info->image_info->quality);
5582 if (image != (Image *) NULL)
5583 s=newSViv((ssize_t) image->quality);
5584 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5585 continue;
5586 }
5587 if (LocaleCompare(attribute,"quantum") == 0)
5588 {
5589 if (info)
5590 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5591 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5592 continue;
5593 }
5594 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5595 attribute);
5596 break;
5597 }
5598 case 'R':
5599 case 'r':
5600 {
5601 if (LocaleCompare(attribute,"rendering-intent") == 0)
5602 {
5603 s=newSViv(image->rendering_intent);
5604 (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5605 image->rendering_intent));
5606 SvIOK_on(s);
5607 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5608 continue;
5609 }
5610 if (LocaleCompare(attribute,"red-primary") == 0)
5611 {
5612 if (image == (Image *) NULL)
5613 break;
Cristyb1710fe2017-02-11 13:51:48 -05005614 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005615 image->chromaticity.red_primary.x,
5616 image->chromaticity.red_primary.y);
5617 s=newSVpv(color,0);
5618 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5619 continue;
5620 }
5621 if (LocaleCompare(attribute,"rows") == 0)
5622 {
5623 if (image != (Image *) NULL)
5624 s=newSViv((ssize_t) image->rows);
5625 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5626 continue;
5627 }
5628 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5629 attribute);
5630 break;
5631 }
5632 case 'S':
5633 case 's':
5634 {
5635 if (LocaleCompare(attribute,"sampling-factor") == 0)
5636 {
5637 if (info && info->image_info->sampling_factor)
5638 s=newSVpv(info->image_info->sampling_factor,0);
5639 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5640 continue;
5641 }
5642 if (LocaleCompare(attribute,"server") == 0) /* same as display */
5643 {
5644 if (info && info->image_info->server_name)
5645 s=newSVpv(info->image_info->server_name,0);
5646 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5647 continue;
5648 }
5649 if (LocaleCompare(attribute,"size") == 0)
5650 {
5651 if (info && info->image_info->size)
5652 s=newSVpv(info->image_info->size,0);
5653 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5654 continue;
5655 }
5656 if (LocaleCompare(attribute,"scene") == 0)
5657 {
5658 if (image != (Image *) NULL)
5659 s=newSViv((ssize_t) image->scene);
5660 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5661 continue;
5662 }
5663 if (LocaleCompare(attribute,"scenes") == 0)
5664 {
5665 if (image != (Image *) NULL)
5666 s=newSViv((ssize_t) info->image_info->number_scenes);
5667 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5668 continue;
5669 }
5670 if (LocaleCompare(attribute,"signature") == 0)
5671 {
5672 const char
5673 *value;
5674
5675 if (image == (Image *) NULL)
5676 break;
5677 (void) SignatureImage(image,exception);
5678 value=GetImageProperty(image,"Signature",exception);
5679 if (value != (const char *) NULL)
5680 s=newSVpv(value,0);
5681 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5682 continue;
5683 }
5684 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5685 attribute);
5686 break;
5687 }
5688 case 'T':
5689 case 't':
5690 {
5691 if (LocaleCompare(attribute,"taint") == 0)
5692 {
5693 if (image != (Image *) NULL)
5694 s=newSViv((ssize_t) IsTaintImage(image));
5695 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5696 continue;
5697 }
5698 if (LocaleCompare(attribute,"texture") == 0)
5699 {
5700 if (info && info->image_info->texture)
5701 s=newSVpv(info->image_info->texture,0);
5702 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5703 continue;
5704 }
5705 if (LocaleCompare(attribute,"total-ink-density") == 0)
5706 {
5707 s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5708 if (image != (Image *) NULL)
5709 s=newSVnv(GetImageTotalInkDensity(image,exception));
5710 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5711 continue;
5712 }
5713 if (LocaleCompare(attribute,"transparent-color") == 0)
5714 {
5715 if (image == (Image *) NULL)
5716 break;
cristy151b66d2015-04-15 10:50:31 +00005717 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00005718 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5719 (double) image->transparent_color.green,
5720 (double) image->transparent_color.blue,
5721 (double) image->transparent_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00005722 s=newSVpv(color,0);
5723 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5724 continue;
5725 }
5726 if (LocaleCompare(attribute,"type") == 0)
5727 {
5728 if (image == (Image *) NULL)
5729 break;
cristya26f54c2015-07-29 12:26:12 +00005730 j=(ssize_t) GetImageType(image);
cristy4a3ce0a2013-08-03 20:06:59 +00005731 s=newSViv(j);
5732 (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5733 SvIOK_on(s);
5734 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5735 continue;
5736 }
5737 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5738 attribute);
5739 break;
5740 }
5741 case 'U':
5742 case 'u':
5743 {
5744 if (LocaleCompare(attribute,"units") == 0)
5745 {
5746 j=info ? info->image_info->units : image ? image->units :
5747 UndefinedResolution;
5748 if (info && (info->image_info->units == UndefinedResolution))
5749 if (image)
5750 j=image->units;
5751 if (j == UndefinedResolution)
5752 s=newSVpv("undefined units",0);
5753 else
5754 if (j == PixelsPerInchResolution)
5755 s=newSVpv("pixels / inch",0);
5756 else
5757 s=newSVpv("pixels / centimeter",0);
5758 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5759 continue;
5760 }
5761 if (LocaleCompare(attribute,"user-time") == 0)
5762 {
5763 if (image != (Image *) NULL)
5764 s=newSVnv(GetUserTime(&image->timer));
5765 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5766 continue;
5767 }
5768 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5769 attribute);
5770 break;
5771 }
5772 case 'V':
5773 case 'v':
5774 {
5775 if (LocaleCompare(attribute,"verbose") == 0)
5776 {
5777 if (info)
5778 s=newSViv((ssize_t) info->image_info->verbose);
5779 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5780 continue;
5781 }
5782 if (LocaleCompare(attribute,"version") == 0)
5783 {
5784 s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5785 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5786 continue;
5787 }
cristy4a3ce0a2013-08-03 20:06:59 +00005788 if (LocaleCompare(attribute,"virtual-pixel") == 0)
5789 {
5790 if (image == (Image *) NULL)
5791 break;
5792 j=(ssize_t) GetImageVirtualPixelMethod(image);
5793 s=newSViv(j);
5794 (void) sv_setpv(s,CommandOptionToMnemonic(
5795 MagickVirtualPixelOptions,j));
5796 SvIOK_on(s);
5797 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5798 continue;
5799 }
5800 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5801 attribute);
5802 break;
5803 }
5804 case 'W':
5805 case 'w':
5806 {
5807 if (LocaleCompare(attribute,"white-point") == 0)
5808 {
5809 if (image == (Image *) NULL)
5810 break;
Cristyb1710fe2017-02-11 13:51:48 -05005811 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005812 image->chromaticity.white_point.x,
5813 image->chromaticity.white_point.y);
5814 s=newSVpv(color,0);
5815 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5816 continue;
5817 }
5818 if (LocaleCompare(attribute,"width") == 0)
5819 {
5820 if (image != (Image *) NULL)
5821 s=newSViv((ssize_t) image->columns);
5822 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5823 continue;
5824 }
5825 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5826 attribute);
5827 break;
5828 }
5829 case 'X':
5830 case 'x':
5831 {
Cristyc1f9f9f2016-01-05 08:19:28 -05005832 if (LocaleCompare(attribute,"xmp") == 0)
5833 {
5834 if (image != (Image *) NULL)
5835 {
5836 const StringInfo
5837 *profile;
5838
5839 profile=GetImageProfile(image,"xmp");
5840 if (profile != (StringInfo *) NULL)
5841 s=newSVpv((const char *) GetStringInfoDatum(profile),
5842 GetStringInfoLength(profile));
5843 }
5844 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5845 continue;
5846 }
cristy4a3ce0a2013-08-03 20:06:59 +00005847 if (LocaleCompare(attribute,"x-resolution") == 0)
5848 {
5849 if (image != (Image *) NULL)
5850 s=newSVnv(image->resolution.x);
5851 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5852 continue;
5853 }
5854 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5855 attribute);
5856 break;
5857 }
5858 case 'Y':
5859 case 'y':
5860 {
5861 if (LocaleCompare(attribute,"y-resolution") == 0)
5862 {
5863 if (image != (Image *) NULL)
5864 s=newSVnv(image->resolution.y);
5865 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5866 continue;
5867 }
5868 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5869 attribute);
5870 break;
5871 }
5872 default:
5873 break;
5874 }
5875 if (image == (Image *) NULL)
5876 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5877 attribute)
5878 else
5879 {
5880 value=GetImageProperty(image,attribute,exception);
5881 if (value != (const char *) NULL)
5882 {
5883 s=newSVpv(value,0);
5884 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5885 }
5886 else
5887 if (*attribute != '%')
5888 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5889 attribute)
5890 else
5891 {
5892 char
5893 *meta;
5894
5895 meta=InterpretImageProperties(info ? info->image_info :
5896 (ImageInfo *) NULL,image,attribute,exception);
5897 s=newSVpv(meta,0);
5898 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5899 meta=(char *) RelinquishMagickMemory(meta);
5900 }
5901 }
5902 }
5903 exception=DestroyExceptionInfo(exception);
5904 SvREFCNT_dec(perl_exception); /* can't return warning messages */
5905 }
5906
5907#
5908###############################################################################
5909# #
5910# #
5911# #
5912# G e t A u t h e n t i c P i x e l s #
5913# #
5914# #
5915# #
5916###############################################################################
5917#
5918#
5919void *
5920GetAuthenticPixels(ref,...)
5921 Image::Magick ref = NO_INIT
5922 ALIAS:
5923 getauthenticpixels = 1
5924 GetImagePixels = 2
5925 getimagepixels = 3
5926 CODE:
5927 {
5928 char
5929 *attribute;
5930
5931 ExceptionInfo
5932 *exception;
5933
5934 Image
5935 *image;
5936
5937 RectangleInfo
5938 region;
5939
5940 ssize_t
5941 i;
5942
5943 struct PackageInfo
5944 *info;
5945
5946 SV
5947 *perl_exception,
5948 *reference;
5949
5950 void
5951 *blob = NULL;
5952
5953 PERL_UNUSED_VAR(ref);
5954 PERL_UNUSED_VAR(ix);
5955 exception=AcquireExceptionInfo();
5956 perl_exception=newSVpv("",0);
5957 if (sv_isobject(ST(0)) == 0)
5958 {
5959 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5960 PackageName);
5961 goto PerlException;
5962 }
5963 reference=SvRV(ST(0));
5964
5965 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5966 if (image == (Image *) NULL)
5967 {
5968 ThrowPerlException(exception,OptionError,"NoImagesDefined",
5969 PackageName);
5970 goto PerlException;
5971 }
5972
5973 region.x=0;
5974 region.y=0;
5975 region.width=image->columns;
5976 region.height=1;
5977 if (items == 1)
5978 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5979 for (i=2; i < items; i+=2)
5980 {
5981 attribute=(char *) SvPV(ST(i-1),na);
5982 switch (*attribute)
5983 {
5984 case 'g':
5985 case 'G':
5986 {
5987 if (LocaleCompare(attribute,"geometry") == 0)
5988 {
5989 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5990 break;
5991 }
5992 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5993 attribute);
5994 break;
5995 }
5996 case 'H':
5997 case 'h':
5998 {
5999 if (LocaleCompare(attribute,"height") == 0)
6000 {
6001 region.height=SvIV(ST(i));
6002 continue;
6003 }
6004 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6005 attribute);
6006 break;
6007 }
6008 case 'X':
6009 case 'x':
6010 {
6011 if (LocaleCompare(attribute,"x") == 0)
6012 {
6013 region.x=SvIV(ST(i));
6014 continue;
6015 }
6016 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6017 attribute);
6018 break;
6019 }
6020 case 'Y':
6021 case 'y':
6022 {
6023 if (LocaleCompare(attribute,"y") == 0)
6024 {
6025 region.y=SvIV(ST(i));
6026 continue;
6027 }
6028 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6029 attribute);
6030 break;
6031 }
6032 case 'W':
6033 case 'w':
6034 {
6035 if (LocaleCompare(attribute,"width") == 0)
6036 {
6037 region.width=SvIV(ST(i));
6038 continue;
6039 }
6040 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6041 attribute);
6042 break;
6043 }
6044 }
6045 }
6046 blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
6047 region.height,exception);
6048 if (blob != (void *) NULL)
6049 goto PerlEnd;
6050
6051 PerlException:
6052 InheritPerlException(exception,perl_exception);
6053 exception=DestroyExceptionInfo(exception);
6054 SvREFCNT_dec(perl_exception); /* throw away all errors */
6055
6056 PerlEnd:
6057 RETVAL = blob;
6058 }
6059 OUTPUT:
6060 RETVAL
6061
6062#
6063###############################################################################
6064# #
6065# #
6066# #
6067# G e t V i r t u a l P i x e l s #
6068# #
6069# #
6070# #
6071###############################################################################
6072#
6073#
6074void *
6075GetVirtualPixels(ref,...)
6076 Image::Magick ref = NO_INIT
6077 ALIAS:
6078 getvirtualpixels = 1
6079 AcquireImagePixels = 2
6080 acquireimagepixels = 3
6081 CODE:
6082 {
6083 char
6084 *attribute;
6085
6086 const void
6087 *blob = NULL;
6088
6089 ExceptionInfo
6090 *exception;
6091
6092 Image
6093 *image;
6094
6095 RectangleInfo
6096 region;
6097
6098 ssize_t
6099 i;
6100
6101 struct PackageInfo
6102 *info;
6103
6104 SV
6105 *perl_exception,
6106 *reference;
6107
6108 PERL_UNUSED_VAR(ref);
6109 PERL_UNUSED_VAR(ix);
6110 exception=AcquireExceptionInfo();
6111 perl_exception=newSVpv("",0);
6112 if (sv_isobject(ST(0)) == 0)
6113 {
6114 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6115 PackageName);
6116 goto PerlException;
6117 }
6118 reference=SvRV(ST(0));
6119
6120 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6121 if (image == (Image *) NULL)
6122 {
6123 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6124 PackageName);
6125 goto PerlException;
6126 }
6127
6128 region.x=0;
6129 region.y=0;
6130 region.width=image->columns;
6131 region.height=1;
6132 if (items == 1)
6133 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6134 for (i=2; i < items; i+=2)
6135 {
6136 attribute=(char *) SvPV(ST(i-1),na);
6137 switch (*attribute)
6138 {
6139 case 'g':
6140 case 'G':
6141 {
6142 if (LocaleCompare(attribute,"geometry") == 0)
6143 {
6144 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6145 break;
6146 }
6147 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6148 attribute);
6149 break;
6150 }
6151 case 'H':
6152 case 'h':
6153 {
6154 if (LocaleCompare(attribute,"height") == 0)
6155 {
6156 region.height=SvIV(ST(i));
6157 continue;
6158 }
6159 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6160 attribute);
6161 break;
6162 }
6163 case 'X':
6164 case 'x':
6165 {
6166 if (LocaleCompare(attribute,"x") == 0)
6167 {
6168 region.x=SvIV(ST(i));
6169 continue;
6170 }
6171 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6172 attribute);
6173 break;
6174 }
6175 case 'Y':
6176 case 'y':
6177 {
6178 if (LocaleCompare(attribute,"y") == 0)
6179 {
6180 region.y=SvIV(ST(i));
6181 continue;
6182 }
6183 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6184 attribute);
6185 break;
6186 }
6187 case 'W':
6188 case 'w':
6189 {
6190 if (LocaleCompare(attribute,"width") == 0)
6191 {
6192 region.width=SvIV(ST(i));
6193 continue;
6194 }
6195 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6196 attribute);
6197 break;
6198 }
6199 }
6200 }
6201 blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6202 region.height,exception);
6203 if (blob != (void *) NULL)
6204 goto PerlEnd;
6205
6206 PerlException:
6207 InheritPerlException(exception,perl_exception);
6208 exception=DestroyExceptionInfo(exception);
6209 SvREFCNT_dec(perl_exception); /* throw away all errors */
6210
6211 PerlEnd:
6212 RETVAL = (void *) blob;
6213 }
6214 OUTPUT:
6215 RETVAL
6216
6217#
6218###############################################################################
6219# #
6220# #
6221# #
6222# G e t A u t h e n t i c M e t a c o n t e n t #
6223# #
6224# #
6225# #
6226###############################################################################
6227#
6228#
6229void *
6230GetAuthenticMetacontent(ref,...)
6231 Image::Magick ref = NO_INIT
6232 ALIAS:
6233 getauthenticmetacontent = 1
6234 GetMetacontent = 2
6235 getmetacontent = 3
6236 CODE:
6237 {
6238 ExceptionInfo
6239 *exception;
6240
6241 Image
6242 *image;
6243
6244 struct PackageInfo
6245 *info;
6246
6247 SV
6248 *perl_exception,
6249 *reference;
6250
6251 void
6252 *blob = NULL;
6253
6254 PERL_UNUSED_VAR(ref);
6255 PERL_UNUSED_VAR(ix);
6256 exception=AcquireExceptionInfo();
6257 perl_exception=newSVpv("",0);
6258 if (sv_isobject(ST(0)) == 0)
6259 {
6260 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6261 PackageName);
6262 goto PerlException;
6263 }
6264 reference=SvRV(ST(0));
6265
6266 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6267 if (image == (Image *) NULL)
6268 {
6269 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6270 PackageName);
6271 goto PerlException;
6272 }
6273
6274 blob=(void *) GetAuthenticMetacontent(image);
6275 if (blob != (void *) NULL)
6276 goto PerlEnd;
6277
6278 PerlException:
6279 InheritPerlException(exception,perl_exception);
6280 exception=DestroyExceptionInfo(exception);
6281 SvREFCNT_dec(perl_exception); /* throw away all errors */
6282
6283 PerlEnd:
6284 RETVAL = blob;
6285 }
6286 OUTPUT:
6287 RETVAL
6288
6289#
6290###############################################################################
6291# #
6292# #
6293# #
6294# G e t V i r t u a l M e t a c o n t e n t #
6295# #
6296# #
6297# #
6298###############################################################################
6299#
6300#
6301void *
6302GetVirtualMetacontent(ref,...)
6303 Image::Magick ref = NO_INIT
6304 ALIAS:
6305 getvirtualmetacontent = 1
6306 CODE:
6307 {
6308 ExceptionInfo
6309 *exception;
6310
6311 Image
6312 *image;
6313
6314 struct PackageInfo
6315 *info;
6316
6317 SV
6318 *perl_exception,
6319 *reference;
6320
6321 void
6322 *blob = NULL;
6323
6324 PERL_UNUSED_VAR(ref);
6325 PERL_UNUSED_VAR(ix);
6326 exception=AcquireExceptionInfo();
6327 perl_exception=newSVpv("",0);
6328 if (sv_isobject(ST(0)) == 0)
6329 {
6330 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6331 PackageName);
6332 goto PerlException;
6333 }
6334 reference=SvRV(ST(0));
6335
6336 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6337 if (image == (Image *) NULL)
6338 {
6339 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6340 PackageName);
6341 goto PerlException;
6342 }
6343
6344 blob=(void *) GetVirtualMetacontent(image);
6345 if (blob != (void *) NULL)
6346 goto PerlEnd;
6347
6348 PerlException:
6349 InheritPerlException(exception,perl_exception);
6350 exception=DestroyExceptionInfo(exception);
6351 SvREFCNT_dec(perl_exception); /* throw away all errors */
6352
6353 PerlEnd:
6354 RETVAL = blob;
6355 }
6356 OUTPUT:
6357 RETVAL
6358
6359#
6360###############################################################################
6361# #
6362# #
6363# #
6364# H i s t o g r a m #
6365# #
6366# #
6367# #
6368###############################################################################
6369#
6370#
6371void
6372Histogram(ref,...)
6373 Image::Magick ref=NO_INIT
6374 ALIAS:
6375 HistogramImage = 1
6376 histogram = 2
6377 histogramimage = 3
6378 PPCODE:
6379 {
6380 AV
6381 *av;
6382
6383 char
cristy151b66d2015-04-15 10:50:31 +00006384 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00006385
6386 PixelInfo
6387 *histogram;
6388
6389 ExceptionInfo
6390 *exception;
6391
6392 Image
6393 *image;
6394
6395 register ssize_t
6396 i;
6397
6398 ssize_t
6399 count;
6400
6401 struct PackageInfo
6402 *info;
6403
6404 SV
6405 *perl_exception,
6406 *reference;
6407
6408 size_t
6409 number_colors;
6410
6411 PERL_UNUSED_VAR(ref);
6412 PERL_UNUSED_VAR(ix);
6413 exception=AcquireExceptionInfo();
6414 perl_exception=newSVpv("",0);
6415 av=NULL;
6416 if (sv_isobject(ST(0)) == 0)
6417 {
6418 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6419 PackageName);
6420 goto PerlException;
6421 }
6422 reference=SvRV(ST(0));
6423 av=newAV();
6424 SvREFCNT_dec(av);
6425 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6426 if (image == (Image *) NULL)
6427 {
6428 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6429 PackageName);
6430 goto PerlException;
6431 }
cristy4a3ce0a2013-08-03 20:06:59 +00006432 count=0;
6433 for ( ; image; image=image->next)
6434 {
6435 histogram=GetImageHistogram(image,&number_colors,exception);
6436 if (histogram == (PixelInfo *) NULL)
6437 continue;
6438 count+=(ssize_t) number_colors;
6439 EXTEND(sp,6*count);
6440 for (i=0; i < (ssize_t) number_colors; i++)
6441 {
cristy151b66d2015-04-15 10:50:31 +00006442 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006443 histogram[i].red);
6444 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006445 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006446 histogram[i].green);
6447 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006448 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006449 histogram[i].blue);
6450 PUSHs(sv_2mortal(newSVpv(message,0)));
6451 if (image->colorspace == CMYKColorspace)
6452 {
cristy151b66d2015-04-15 10:50:31 +00006453 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006454 histogram[i].black);
6455 PUSHs(sv_2mortal(newSVpv(message,0)));
6456 }
cristy151b66d2015-04-15 10:50:31 +00006457 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006458 histogram[i].alpha);
6459 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006460 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
cristy4a3ce0a2013-08-03 20:06:59 +00006461 histogram[i].count);
6462 PUSHs(sv_2mortal(newSVpv(message,0)));
6463 }
6464 histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6465 }
6466
6467 PerlException:
6468 InheritPerlException(exception,perl_exception);
6469 exception=DestroyExceptionInfo(exception);
6470 SvREFCNT_dec(perl_exception);
6471 }
6472
6473#
6474###############################################################################
6475# #
6476# #
6477# #
6478# G e t P i x e l #
6479# #
6480# #
6481# #
6482###############################################################################
6483#
6484#
6485void
6486GetPixel(ref,...)
6487 Image::Magick ref=NO_INIT
6488 ALIAS:
6489 getpixel = 1
6490 getPixel = 2
6491 PPCODE:
6492 {
6493 AV
6494 *av;
6495
6496 char
6497 *attribute;
6498
6499 ExceptionInfo
6500 *exception;
6501
6502 Image
6503 *image;
6504
6505 MagickBooleanType
6506 normalize;
6507
6508 RectangleInfo
6509 region;
6510
6511 register const Quantum
6512 *p;
6513
6514 register ssize_t
6515 i;
6516
6517 ssize_t
6518 option;
6519
6520 struct PackageInfo
6521 *info;
6522
6523 SV
6524 *perl_exception,
6525 *reference; /* reference is the SV* of ref=SvIV(reference) */
6526
6527 PERL_UNUSED_VAR(ref);
6528 PERL_UNUSED_VAR(ix);
6529 exception=AcquireExceptionInfo();
6530 perl_exception=newSVpv("",0);
6531 reference=SvRV(ST(0));
6532 av=(AV *) reference;
6533 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6534 exception);
6535 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6536 if (image == (Image *) NULL)
6537 {
6538 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6539 PackageName);
6540 goto PerlException;
6541 }
6542 normalize=MagickTrue;
6543 region.x=0;
6544 region.y=0;
6545 region.width=image->columns;
6546 region.height=1;
6547 if (items == 1)
6548 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6549 for (i=2; i < items; i+=2)
6550 {
6551 attribute=(char *) SvPV(ST(i-1),na);
6552 switch (*attribute)
6553 {
6554 case 'C':
6555 case 'c':
6556 {
6557 if (LocaleCompare(attribute,"channel") == 0)
6558 {
6559 ssize_t
6560 option;
6561
6562 option=ParseChannelOption(SvPV(ST(i),na));
6563 if (option < 0)
6564 {
6565 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6566 SvPV(ST(i),na));
6567 return;
6568 }
cristybcd59342015-06-07 14:07:19 +00006569 (void) SetPixelChannelMask(image,(ChannelType) option);
cristy4a3ce0a2013-08-03 20:06:59 +00006570 break;
6571 }
6572 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6573 attribute);
6574 break;
6575 }
6576 case 'g':
6577 case 'G':
6578 {
6579 if (LocaleCompare(attribute,"geometry") == 0)
6580 {
6581 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6582 break;
6583 }
6584 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6585 attribute);
6586 break;
6587 }
6588 case 'N':
6589 case 'n':
6590 {
6591 if (LocaleCompare(attribute,"normalize") == 0)
6592 {
6593 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6594 SvPV(ST(i),na));
6595 if (option < 0)
6596 {
6597 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6598 SvPV(ST(i),na));
6599 break;
6600 }
6601 normalize=option != 0 ? MagickTrue : MagickFalse;
6602 break;
6603 }
6604 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6605 attribute);
6606 break;
6607 }
6608 case 'x':
6609 case 'X':
6610 {
6611 if (LocaleCompare(attribute,"x") == 0)
6612 {
6613 region.x=SvIV(ST(i));
6614 break;
6615 }
6616 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6617 attribute);
6618 break;
6619 }
6620 case 'y':
6621 case 'Y':
6622 {
6623 if (LocaleCompare(attribute,"y") == 0)
6624 {
6625 region.y=SvIV(ST(i));
6626 break;
6627 }
6628 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6629 attribute);
6630 break;
6631 }
6632 default:
6633 {
6634 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6635 attribute);
6636 break;
6637 }
6638 }
6639 }
6640 p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6641 if (p == (const Quantum *) NULL)
6642 PUSHs(&sv_undef);
6643 else
6644 {
6645 double
6646 scale;
6647
6648 scale=1.0;
6649 if (normalize != MagickFalse)
6650 scale=1.0/QuantumRange;
6651 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6652 PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6653 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6654 PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6655 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6656 PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6657 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6658 (image->colorspace == CMYKColorspace))
6659 PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6660 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6661 PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6662 }
6663
6664 PerlException:
6665 InheritPerlException(exception,perl_exception);
6666 exception=DestroyExceptionInfo(exception);
6667 SvREFCNT_dec(perl_exception);
6668 }
6669
6670#
6671###############################################################################
6672# #
6673# #
6674# #
6675# G e t P i x e l s #
6676# #
6677# #
6678# #
6679###############################################################################
6680#
6681#
6682void
6683GetPixels(ref,...)
6684 Image::Magick ref=NO_INIT
6685 ALIAS:
6686 getpixels = 1
6687 getPixels = 2
6688 PPCODE:
6689 {
6690 AV
6691 *av;
6692
6693 char
6694 *attribute;
6695
6696 const char
6697 *map;
6698
6699 ExceptionInfo
6700 *exception;
6701
6702 Image
6703 *image;
6704
6705 MagickBooleanType
6706 normalize,
6707 status;
6708
6709 RectangleInfo
6710 region;
6711
6712 register ssize_t
6713 i;
6714
6715 ssize_t
6716 option;
6717
6718 struct PackageInfo
6719 *info;
6720
6721 SV
6722 *perl_exception,
6723 *reference; /* reference is the SV* of ref=SvIV(reference) */
6724
6725 PERL_UNUSED_VAR(ref);
6726 PERL_UNUSED_VAR(ix);
6727 exception=AcquireExceptionInfo();
6728 perl_exception=newSVpv("",0);
6729 reference=SvRV(ST(0));
6730 av=(AV *) reference;
6731 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6732 exception);
6733 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6734 if (image == (Image *) NULL)
6735 {
6736 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6737 PackageName);
6738 goto PerlException;
6739 }
6740 map="RGB";
cristy17f11b02014-12-20 19:37:04 +00006741 if (image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00006742 map="RGBA";
6743 if (image->colorspace == CMYKColorspace)
6744 {
6745 map="CMYK";
cristy17f11b02014-12-20 19:37:04 +00006746 if (image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00006747 map="CMYKA";
6748 }
6749 normalize=MagickFalse;
6750 region.x=0;
6751 region.y=0;
6752 region.width=image->columns;
6753 region.height=1;
6754 if (items == 1)
6755 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6756 for (i=2; i < items; i+=2)
6757 {
6758 attribute=(char *) SvPV(ST(i-1),na);
6759 switch (*attribute)
6760 {
6761 case 'g':
6762 case 'G':
6763 {
6764 if (LocaleCompare(attribute,"geometry") == 0)
6765 {
6766 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6767 break;
6768 }
6769 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6770 attribute);
6771 break;
6772 }
6773 case 'H':
6774 case 'h':
6775 {
6776 if (LocaleCompare(attribute,"height") == 0)
6777 {
6778 region.height=SvIV(ST(i));
6779 break;
6780 }
6781 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6782 attribute);
6783 break;
6784 }
6785 case 'M':
6786 case 'm':
6787 {
6788 if (LocaleCompare(attribute,"map") == 0)
6789 {
6790 map=SvPV(ST(i),na);
6791 break;
6792 }
6793 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6794 attribute);
6795 break;
6796 }
6797 case 'N':
6798 case 'n':
6799 {
6800 if (LocaleCompare(attribute,"normalize") == 0)
6801 {
6802 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6803 SvPV(ST(i),na));
6804 if (option < 0)
6805 {
6806 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6807 SvPV(ST(i),na));
6808 break;
6809 }
6810 normalize=option != 0 ? MagickTrue : MagickFalse;
6811 break;
6812 }
6813 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6814 attribute);
6815 break;
6816 }
6817 case 'W':
6818 case 'w':
6819 {
6820 if (LocaleCompare(attribute,"width") == 0)
6821 {
6822 region.width=SvIV(ST(i));
6823 break;
6824 }
6825 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6826 attribute);
6827 break;
6828 }
6829 case 'x':
6830 case 'X':
6831 {
6832 if (LocaleCompare(attribute,"x") == 0)
6833 {
6834 region.x=SvIV(ST(i));
6835 break;
6836 }
6837 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6838 attribute);
6839 break;
6840 }
6841 case 'y':
6842 case 'Y':
6843 {
6844 if (LocaleCompare(attribute,"y") == 0)
6845 {
6846 region.y=SvIV(ST(i));
6847 break;
6848 }
6849 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6850 attribute);
6851 break;
6852 }
6853 default:
6854 {
6855 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6856 attribute);
6857 break;
6858 }
6859 }
6860 }
6861 if (normalize != MagickFalse)
6862 {
6863 float
6864 *pixels;
6865
6866 pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6867 region.height*sizeof(*pixels));
6868 if (pixels == (float *) NULL)
6869 {
6870 ThrowPerlException(exception,ResourceLimitError,
6871 "MemoryAllocationFailed",PackageName);
6872 goto PerlException;
6873 }
6874 status=ExportImagePixels(image,region.x,region.y,region.width,
6875 region.height,map,FloatPixel,pixels,exception);
6876 if (status == MagickFalse)
6877 PUSHs(&sv_undef);
6878 else
6879 {
6880 EXTEND(sp,strlen(map)*region.width*region.height);
6881 for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6882 PUSHs(sv_2mortal(newSVnv(pixels[i])));
6883 }
6884 pixels=(float *) RelinquishMagickMemory(pixels);
6885 }
6886 else
6887 {
6888 Quantum
6889 *pixels;
6890
6891 pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6892 region.height*sizeof(*pixels));
6893 if (pixels == (Quantum *) NULL)
6894 {
6895 ThrowPerlException(exception,ResourceLimitError,
6896 "MemoryAllocationFailed",PackageName);
6897 goto PerlException;
6898 }
6899 status=ExportImagePixels(image,region.x,region.y,region.width,
6900 region.height,map,QuantumPixel,pixels,exception);
6901 if (status == MagickFalse)
6902 PUSHs(&sv_undef);
6903 else
6904 {
6905 EXTEND(sp,strlen(map)*region.width*region.height);
6906 for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6907 PUSHs(sv_2mortal(newSViv(pixels[i])));
6908 }
6909 pixels=(Quantum *) RelinquishMagickMemory(pixels);
6910 }
6911
6912 PerlException:
6913 InheritPerlException(exception,perl_exception);
6914 exception=DestroyExceptionInfo(exception);
6915 SvREFCNT_dec(perl_exception);
6916 }
6917
6918#
6919###############################################################################
6920# #
6921# #
6922# #
6923# I m a g e T o B l o b #
6924# #
6925# #
6926# #
6927###############################################################################
6928#
6929#
6930void
6931ImageToBlob(ref,...)
6932 Image::Magick ref=NO_INIT
6933 ALIAS:
6934 ImageToBlob = 1
6935 imagetoblob = 2
6936 toblob = 3
6937 blob = 4
6938 PPCODE:
6939 {
6940 char
cristy151b66d2015-04-15 10:50:31 +00006941 filename[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00006942
6943 ExceptionInfo
6944 *exception;
6945
6946 Image
6947 *image,
6948 *next;
6949
6950 register ssize_t
6951 i;
6952
6953 struct PackageInfo
6954 *info,
6955 *package_info;
6956
6957 size_t
6958 length;
6959
6960 ssize_t
6961 scene;
6962
6963 SV
6964 *perl_exception,
6965 *reference;
6966
6967 void
6968 *blob;
6969
6970 PERL_UNUSED_VAR(ref);
6971 PERL_UNUSED_VAR(ix);
6972 exception=AcquireExceptionInfo();
6973 perl_exception=newSVpv("",0);
6974 package_info=(struct PackageInfo *) NULL;
6975 if (sv_isobject(ST(0)) == 0)
6976 {
6977 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6978 PackageName);
6979 goto PerlException;
6980 }
6981 reference=SvRV(ST(0));
6982 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6983 if (image == (Image *) NULL)
6984 {
6985 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6986 PackageName);
6987 goto PerlException;
6988 }
6989 package_info=ClonePackageInfo(info,exception);
6990 for (i=2; i < items; i+=2)
6991 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6992 (void) CopyMagickString(filename,package_info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00006993 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00006994 scene=0;
6995 for (next=image; next; next=next->next)
6996 {
cristy151b66d2015-04-15 10:50:31 +00006997 (void) CopyMagickString(next->filename,filename,MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00006998 next->scene=scene++;
6999 }
7000 SetImageInfo(package_info->image_info,(unsigned int)
7001 GetImageListLength(image),exception);
7002 EXTEND(sp,(ssize_t) GetImageListLength(image));
7003 for ( ; image; image=image->next)
7004 {
7005 length=0;
7006 blob=ImagesToBlob(package_info->image_info,image,&length,exception);
7007 if (blob != (char *) NULL)
7008 {
7009 PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
7010 blob=(unsigned char *) RelinquishMagickMemory(blob);
7011 }
7012 if (package_info->image_info->adjoin)
7013 break;
7014 }
7015
7016 PerlException:
7017 if (package_info != (struct PackageInfo *) NULL)
7018 DestroyPackageInfo(package_info);
7019 InheritPerlException(exception,perl_exception);
7020 exception=DestroyExceptionInfo(exception);
7021 SvREFCNT_dec(perl_exception); /* throw away all errors */
7022 }
7023
7024#
7025###############################################################################
7026# #
7027# #
7028# #
7029# L a y e r s #
7030# #
7031# #
7032# #
7033###############################################################################
7034#
7035#
7036void
7037Layers(ref,...)
7038 Image::Magick ref=NO_INIT
7039 ALIAS:
7040 Layers = 1
7041 layers = 2
7042 OptimizeImageLayers = 3
7043 optimizelayers = 4
7044 optimizeimagelayers = 5
7045 PPCODE:
7046 {
7047 AV
7048 *av;
7049
7050 char
7051 *attribute;
7052
7053 CompositeOperator
7054 compose;
7055
7056 ExceptionInfo
7057 *exception;
7058
7059 HV
7060 *hv;
7061
7062 Image
7063 *image,
7064 *layers;
7065
7066 LayerMethod
7067 method;
7068
7069 register ssize_t
7070 i;
7071
7072 ssize_t
7073 option,
7074 sp;
7075
7076 struct PackageInfo
7077 *info;
7078
7079 SV
7080 *av_reference,
7081 *perl_exception,
7082 *reference,
7083 *rv,
7084 *sv;
7085
7086 PERL_UNUSED_VAR(ref);
7087 PERL_UNUSED_VAR(ix);
7088 exception=AcquireExceptionInfo();
7089 perl_exception=newSVpv("",0);
7090 sv=NULL;
7091 if (sv_isobject(ST(0)) == 0)
7092 {
7093 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7094 PackageName);
7095 goto PerlException;
7096 }
7097 reference=SvRV(ST(0));
7098 hv=SvSTASH(reference);
7099 av=newAV();
7100 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7101 SvREFCNT_dec(av);
7102 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7103 if (image == (Image *) NULL)
7104 {
7105 ThrowPerlException(exception,OptionError,"NoImagesDefined",
7106 PackageName);
7107 goto PerlException;
7108 }
7109 compose=image->compose;
7110 method=OptimizeLayer;
7111 for (i=2; i < items; i+=2)
7112 {
7113 attribute=(char *) SvPV(ST(i-1),na);
7114 switch (*attribute)
7115 {
7116 case 'C':
7117 case 'c':
7118 {
7119 if (LocaleCompare(attribute,"compose") == 0)
7120 {
7121 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7122 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7123 if (sp < 0)
7124 {
7125 ThrowPerlException(exception,OptionError,"UnrecognizedType",
7126 SvPV(ST(i),na));
7127 break;
7128 }
7129 compose=(CompositeOperator) sp;
7130 break;
7131 }
7132 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7133 attribute);
7134 break;
7135 }
7136 case 'M':
7137 case 'm':
7138 {
7139 if (LocaleCompare(attribute,"method") == 0)
7140 {
7141 option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7142 SvPV(ST(i),na));
7143 if (option < 0)
7144 {
7145 ThrowPerlException(exception,OptionError,"UnrecognizedType",
7146 SvPV(ST(i),na));
7147 break;
7148 }
7149 method=(LayerMethod) option;
7150 break;
7151 }
7152 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7153 attribute);
7154 break;
7155 }
7156 default:
7157 {
7158 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7159 attribute);
7160 break;
7161 }
7162 }
7163 }
7164 layers=(Image *) NULL;
7165 switch (method)
7166 {
7167 case CompareAnyLayer:
7168 case CompareClearLayer:
7169 case CompareOverlayLayer:
7170 default:
7171 {
7172 layers=CompareImagesLayers(image,method,exception);
7173 break;
7174 }
7175 case MergeLayer:
7176 case FlattenLayer:
7177 case MosaicLayer:
7178 {
7179 layers=MergeImageLayers(image,method,exception);
7180 break;
7181 }
7182 case DisposeLayer:
7183 {
7184 layers=DisposeImages(image,exception);
7185 break;
7186 }
7187 case OptimizeImageLayer:
7188 {
7189 layers=OptimizeImageLayers(image,exception);
7190 break;
7191 }
7192 case OptimizePlusLayer:
7193 {
7194 layers=OptimizePlusImageLayers(image,exception);
7195 break;
7196 }
7197 case OptimizeTransLayer:
7198 {
7199 OptimizeImageTransparency(image,exception);
7200 break;
7201 }
7202 case RemoveDupsLayer:
7203 {
7204 RemoveDuplicateLayers(&image,exception);
7205 break;
7206 }
7207 case RemoveZeroLayer:
7208 {
7209 RemoveZeroDelayLayers(&image,exception);
7210 break;
7211 }
7212 case OptimizeLayer:
7213 {
7214 QuantizeInfo
7215 *quantize_info;
7216
7217 /*
7218 General Purpose, GIF Animation Optimizer.
7219 */
7220 layers=CoalesceImages(image,exception);
7221 if (layers == (Image *) NULL)
7222 break;
7223 image=layers;
7224 layers=OptimizeImageLayers(image,exception);
7225 if (layers == (Image *) NULL)
7226 break;
7227 image=DestroyImageList(image);
7228 image=layers;
7229 layers=(Image *) NULL;
7230 OptimizeImageTransparency(image,exception);
7231 quantize_info=AcquireQuantizeInfo(info->image_info);
7232 (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7233 quantize_info=DestroyQuantizeInfo(quantize_info);
7234 break;
7235 }
7236 case CompositeLayer:
7237 {
7238 Image
7239 *source;
7240
7241 RectangleInfo
7242 geometry;
7243
7244 /*
7245 Split image sequence at the first 'NULL:' image.
7246 */
7247 source=image;
7248 while (source != (Image *) NULL)
7249 {
7250 source=GetNextImageInList(source);
7251 if ((source != (Image *) NULL) &&
7252 (LocaleCompare(source->magick,"NULL") == 0))
7253 break;
7254 }
7255 if (source != (Image *) NULL)
7256 {
7257 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7258 (GetNextImageInList(source) == (Image *) NULL))
7259 source=(Image *) NULL;
7260 else
7261 {
7262 /*
7263 Separate the two lists, junk the null: image.
7264 */
7265 source=SplitImageList(source->previous);
7266 DeleteImageFromList(&source);
7267 }
7268 }
7269 if (source == (Image *) NULL)
7270 {
7271 (void) ThrowMagickException(exception,GetMagickModule(),
7272 OptionError,"MissingNullSeparator","layers Composite");
7273 break;
7274 }
7275 /*
7276 Adjust offset with gravity and virtual canvas.
7277 */
7278 SetGeometry(image,&geometry);
7279 (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7280 geometry.width=source->page.width != 0 ? source->page.width :
7281 source->columns;
7282 geometry.height=source->page.height != 0 ? source->page.height :
7283 source->rows;
7284 GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7285 image->columns,image->page.height != 0 ? image->page.height :
7286 image->rows,image->gravity,&geometry);
7287 CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7288 source=DestroyImageList(source);
7289 break;
7290 }
7291 }
7292 if (layers != (Image *) NULL)
7293 image=layers;
cristy83a28a02013-08-03 20:25:48 +00007294 else
7295 image=CloneImage(image,0,0,MagickTrue,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007296 if (image == (Image *) NULL)
7297 goto PerlException;
7298 for ( ; image; image=image->next)
7299 {
7300 AddImageToRegistry(sv,image);
7301 rv=newRV(sv);
7302 av_push(av,sv_bless(rv,hv));
7303 SvREFCNT_dec(sv);
7304 }
7305 exception=DestroyExceptionInfo(exception);
7306 ST(0)=av_reference;
7307 SvREFCNT_dec(perl_exception);
7308 XSRETURN(1);
7309
7310 PerlException:
7311 InheritPerlException(exception,perl_exception);
7312 exception=DestroyExceptionInfo(exception);
7313 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7314 SvPOK_on(perl_exception);
7315 ST(0)=sv_2mortal(perl_exception);
7316 XSRETURN(1);
7317 }
7318
7319#
7320###############################################################################
7321# #
7322# #
7323# #
7324# M a g i c k T o M i m e #
7325# #
7326# #
7327# #
7328###############################################################################
7329#
7330#
7331SV *
7332MagickToMime(ref,name)
7333 Image::Magick ref=NO_INIT
7334 char *name
7335 ALIAS:
7336 magicktomime = 1
7337 CODE:
7338 {
7339 char
7340 *mime;
7341
7342 PERL_UNUSED_VAR(ref);
7343 PERL_UNUSED_VAR(ix);
7344 mime=MagickToMime(name);
7345 RETVAL=newSVpv(mime,0);
7346 mime=(char *) RelinquishMagickMemory(mime);
7347 }
7348 OUTPUT:
7349 RETVAL
7350
7351#
7352###############################################################################
7353# #
7354# #
7355# #
7356# M o g r i f y #
7357# #
7358# #
7359# #
7360###############################################################################
7361#
7362#
7363void
7364Mogrify(ref,...)
7365 Image::Magick ref=NO_INIT
7366 ALIAS:
7367 Comment = 1
7368 CommentImage = 2
7369 Label = 3
7370 LabelImage = 4
7371 AddNoise = 5
7372 AddNoiseImage = 6
7373 Colorize = 7
7374 ColorizeImage = 8
7375 Border = 9
7376 BorderImage = 10
7377 Blur = 11
7378 BlurImage = 12
7379 Chop = 13
7380 ChopImage = 14
7381 Crop = 15
7382 CropImage = 16
7383 Despeckle = 17
7384 DespeckleImage = 18
7385 Edge = 19
7386 EdgeImage = 20
7387 Emboss = 21
7388 EmbossImage = 22
7389 Enhance = 23
7390 EnhanceImage = 24
7391 Flip = 25
7392 FlipImage = 26
7393 Flop = 27
7394 FlopImage = 28
7395 Frame = 29
7396 FrameImage = 30
7397 Implode = 31
7398 ImplodeImage = 32
7399 Magnify = 33
7400 MagnifyImage = 34
7401 MedianFilter = 35
7402 MedianConvolveImage = 36
7403 Minify = 37
7404 MinifyImage = 38
7405 OilPaint = 39
7406 OilPaintImage = 40
7407 ReduceNoise = 41
7408 ReduceNoiseImage = 42
7409 Roll = 43
7410 RollImage = 44
7411 Rotate = 45
7412 RotateImage = 46
7413 Sample = 47
7414 SampleImage = 48
7415 Scale = 49
7416 ScaleImage = 50
7417 Shade = 51
7418 ShadeImage = 52
7419 Sharpen = 53
7420 SharpenImage = 54
7421 Shear = 55
7422 ShearImage = 56
7423 Spread = 57
7424 SpreadImage = 58
7425 Swirl = 59
7426 SwirlImage = 60
7427 Resize = 61
7428 ResizeImage = 62
7429 Zoom = 63
7430 ZoomImage = 64
7431 Annotate = 65
7432 AnnotateImage = 66
7433 ColorFloodfill = 67
7434 ColorFloodfillImage= 68
7435 Composite = 69
7436 CompositeImage = 70
7437 Contrast = 71
7438 ContrastImage = 72
7439 CycleColormap = 73
7440 CycleColormapImage = 74
7441 Draw = 75
7442 DrawImage = 76
7443 Equalize = 77
7444 EqualizeImage = 78
7445 Gamma = 79
7446 GammaImage = 80
7447 Map = 81
7448 MapImage = 82
7449 MatteFloodfill = 83
7450 MatteFloodfillImage= 84
7451 Modulate = 85
7452 ModulateImage = 86
7453 Negate = 87
7454 NegateImage = 88
7455 Normalize = 89
7456 NormalizeImage = 90
7457 NumberColors = 91
7458 NumberColorsImage = 92
7459 Opaque = 93
7460 OpaqueImage = 94
7461 Quantize = 95
7462 QuantizeImage = 96
7463 Raise = 97
7464 RaiseImage = 98
7465 Segment = 99
7466 SegmentImage = 100
7467 Signature = 101
7468 SignatureImage = 102
7469 Solarize = 103
7470 SolarizeImage = 104
7471 Sync = 105
7472 SyncImage = 106
7473 Texture = 107
7474 TextureImage = 108
7475 Evaluate = 109
7476 EvaluateImage = 110
7477 Transparent = 111
7478 TransparentImage = 112
7479 Threshold = 113
7480 ThresholdImage = 114
7481 Charcoal = 115
7482 CharcoalImage = 116
7483 Trim = 117
7484 TrimImage = 118
7485 Wave = 119
7486 WaveImage = 120
7487 Separate = 121
7488 SeparateImage = 122
7489 Stereo = 125
7490 StereoImage = 126
7491 Stegano = 127
7492 SteganoImage = 128
7493 Deconstruct = 129
7494 DeconstructImage = 130
7495 GaussianBlur = 131
7496 GaussianBlurImage = 132
7497 Convolve = 133
7498 ConvolveImage = 134
7499 Profile = 135
7500 ProfileImage = 136
7501 UnsharpMask = 137
7502 UnsharpMaskImage = 138
7503 MotionBlur = 139
7504 MotionBlurImage = 140
7505 OrderedDither = 141
7506 OrderedDitherImage = 142
7507 Shave = 143
7508 ShaveImage = 144
7509 Level = 145
7510 LevelImage = 146
7511 Clip = 147
7512 ClipImage = 148
7513 AffineTransform = 149
7514 AffineTransformImage = 150
7515 Difference = 151
7516 DifferenceImage = 152
7517 AdaptiveThreshold = 153
7518 AdaptiveThresholdImage = 154
7519 Resample = 155
7520 ResampleImage = 156
7521 Describe = 157
7522 DescribeImage = 158
7523 BlackThreshold = 159
7524 BlackThresholdImage= 160
7525 WhiteThreshold = 161
7526 WhiteThresholdImage= 162
cristy60c73c02014-03-25 12:09:58 +00007527 RotationalBlur = 163
7528 RotationalBlurImage= 164
cristy4a3ce0a2013-08-03 20:06:59 +00007529 Thumbnail = 165
7530 ThumbnailImage = 166
7531 Strip = 167
7532 StripImage = 168
7533 Tint = 169
7534 TintImage = 170
7535 Channel = 171
7536 ChannelImage = 172
7537 Splice = 173
7538 SpliceImage = 174
7539 Posterize = 175
7540 PosterizeImage = 176
7541 Shadow = 177
7542 ShadowImage = 178
7543 Identify = 179
7544 IdentifyImage = 180
7545 SepiaTone = 181
7546 SepiaToneImage = 182
7547 SigmoidalContrast = 183
7548 SigmoidalContrastImage = 184
7549 Extent = 185
7550 ExtentImage = 186
7551 Vignette = 187
7552 VignetteImage = 188
7553 ContrastStretch = 189
7554 ContrastStretchImage = 190
7555 Sans0 = 191
7556 Sans0Image = 192
7557 Sans1 = 193
7558 Sans1Image = 194
7559 AdaptiveSharpen = 195
7560 AdaptiveSharpenImage = 196
7561 Transpose = 197
7562 TransposeImage = 198
7563 Transverse = 199
7564 TransverseImage = 200
7565 AutoOrient = 201
7566 AutoOrientImage = 202
7567 AdaptiveBlur = 203
7568 AdaptiveBlurImage = 204
7569 Sketch = 205
7570 SketchImage = 206
7571 UniqueColors = 207
7572 UniqueColorsImage = 208
7573 AdaptiveResize = 209
7574 AdaptiveResizeImage= 210
7575 ClipMask = 211
7576 ClipMaskImage = 212
7577 LinearStretch = 213
7578 LinearStretchImage = 214
7579 ColorMatrix = 215
7580 ColorMatrixImage = 216
7581 Mask = 217
7582 MaskImage = 218
7583 Polaroid = 219
7584 PolaroidImage = 220
7585 FloodfillPaint = 221
7586 FloodfillPaintImage= 222
7587 Distort = 223
7588 DistortImage = 224
7589 Clut = 225
7590 ClutImage = 226
7591 LiquidRescale = 227
7592 LiquidRescaleImage = 228
7593 Encipher = 229
7594 EncipherImage = 230
7595 Decipher = 231
7596 DecipherImage = 232
7597 Deskew = 233
7598 DeskewImage = 234
7599 Remap = 235
7600 RemapImage = 236
7601 SparseColor = 237
7602 SparseColorImage = 238
7603 Function = 239
7604 FunctionImage = 240
7605 SelectiveBlur = 241
7606 SelectiveBlurImage = 242
7607 HaldClut = 243
7608 HaldClutImage = 244
7609 BlueShift = 245
7610 BlueShiftImage = 246
7611 ForwardFourierTransform = 247
7612 ForwardFourierTransformImage = 248
7613 InverseFourierTransform = 249
7614 InverseFourierTransformImage = 250
7615 ColorDecisionList = 251
7616 ColorDecisionListImage = 252
7617 AutoGamma = 253
7618 AutoGammaImage = 254
7619 AutoLevel = 255
7620 AutoLevelImage = 256
7621 LevelColors = 257
7622 LevelImageColors = 258
7623 Clamp = 259
7624 ClampImage = 260
7625 BrightnessContrast = 261
7626 BrightnessContrastImage = 262
7627 Morphology = 263
7628 MorphologyImage = 264
Cristy3ca633e2016-02-13 12:49:01 -05007629 Mode = 265
7630 ModeImage = 266
7631 Statistic = 267
7632 StatisticImage = 268
7633 Perceptible = 269
7634 PerceptibleImage = 270
7635 Poly = 271
7636 PolyImage = 272
7637 Grayscale = 273
7638 GrayscaleImage = 274
7639 CannyEdge = 275
7640 CannyEdgeImage = 276
7641 HoughLine = 277
7642 HoughLineImage = 278
7643 MeanShift = 279
7644 MeanShiftImage = 280
7645 Kuwahara = 281
7646 KuwaharaImage = 282
Cristy0f5df812017-07-04 18:30:05 -04007647 ConnectedComponents = 283
7648 ConnectedComponentsImage = 284
Cristy3ca633e2016-02-13 12:49:01 -05007649 CopyPixels = 285
7650 CopyImagePixels = 286
Cristy5488c982016-02-13 14:07:50 -05007651 Color = 287
7652 ColorImage = 288
Cristy2d830ed2016-02-21 10:54:16 -05007653 WaveletDenoise = 289
7654 WaveletDenoiseImage= 290
Cristy99a57162016-12-05 11:47:57 -05007655 Colorspace = 291
7656 ColorspaceImage = 292
Cristy53353872017-07-02 12:24:24 -04007657 AutoThreshold = 293
7658 AutoThresholdImage = 294
Cristy532b3382018-08-05 17:56:56 -04007659 RangeThreshold = 295
7660 RangeThresholdImage= 296
Cristy9f252542018-11-21 19:13:46 -05007661 CLAHE = 297
7662 CLAHEImage = 298
Cristyb4ab5192019-12-19 06:53:46 -05007663 Kmeans = 299
7664 KMeansImage = 300
cristy4a3ce0a2013-08-03 20:06:59 +00007665 MogrifyRegion = 666
7666 PPCODE:
7667 {
7668 AffineMatrix
7669 affine,
7670 current;
7671
7672 char
7673 attribute_flag[MaxArguments],
cristy151b66d2015-04-15 10:50:31 +00007674 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00007675
7676 ChannelType
7677 channel,
7678 channel_mask;
7679
7680 CompositeOperator
7681 compose;
7682
7683 const char
7684 *attribute,
7685 *value;
7686
7687 double
7688 angle;
7689
7690 ExceptionInfo
7691 *exception;
7692
7693 GeometryInfo
7694 geometry_info;
7695
7696 Image
7697 *image,
Cristy7e567962018-02-03 12:42:20 -05007698 *next;
cristy4a3ce0a2013-08-03 20:06:59 +00007699
cristy4a3ce0a2013-08-03 20:06:59 +00007700 MagickStatusType
7701 flags;
7702
7703 PixelInfo
7704 fill_color;
7705
7706 RectangleInfo
7707 geometry,
7708 region_info;
7709
7710 register ssize_t
7711 i;
7712
7713 ssize_t
7714 base,
7715 j,
7716 number_images;
7717
7718 struct Methods
7719 *rp;
7720
7721 struct PackageInfo
7722 *info;
7723
7724 SV
7725 *perl_exception,
7726 **pv,
7727 *reference,
7728 **reference_vector;
7729
7730 struct ArgumentList
7731 argument_list[MaxArguments];
7732
7733 PERL_UNUSED_VAR(ref);
7734 PERL_UNUSED_VAR(ix);
7735 exception=AcquireExceptionInfo();
7736 perl_exception=newSVpv("",0);
7737 reference_vector=NULL;
cristy4a3ce0a2013-08-03 20:06:59 +00007738 number_images=0;
7739 base=2;
7740 if (sv_isobject(ST(0)) == 0)
7741 {
7742 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7743 PackageName);
7744 goto PerlException;
7745 }
7746 reference=SvRV(ST(0));
7747 region_info.width=0;
7748 region_info.height=0;
7749 region_info.x=0;
7750 region_info.y=0;
cristy4a3ce0a2013-08-03 20:06:59 +00007751 image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7752 if (ix && (ix != 666))
7753 {
7754 /*
7755 Called as Method(...)
7756 */
7757 ix=(ix+1)/2;
7758 rp=(&Methods[ix-1]);
7759 attribute=rp->name;
7760 }
7761 else
7762 {
7763 /*
7764 Called as Mogrify("Method",...)
7765 */
7766 attribute=(char *) SvPV(ST(1),na);
7767 if (ix)
7768 {
7769 flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7770 attribute=(char *) SvPV(ST(2),na);
7771 base++;
7772 }
7773 for (rp=Methods; ; rp++)
7774 {
7775 if (rp >= EndOf(Methods))
7776 {
7777 ThrowPerlException(exception,OptionError,
7778 "UnrecognizedPerlMagickMethod",attribute);
7779 goto PerlException;
7780 }
7781 if (strEQcase(attribute,rp->name))
7782 break;
7783 }
7784 ix=rp-Methods+1;
7785 base++;
7786 }
7787 if (image == (Image *) NULL)
7788 {
7789 ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7790 goto PerlException;
7791 }
7792 Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7793 Zero(&attribute_flag,NumberOf(attribute_flag),char);
7794 for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7795 {
7796 Arguments
7797 *pp,
7798 *qq;
7799
7800 ssize_t
7801 ssize_test;
7802
7803 struct ArgumentList
7804 *al;
7805
7806 SV
7807 *sv;
7808
7809 sv=NULL;
7810 ssize_test=0;
7811 pp=(Arguments *) NULL;
7812 qq=rp->arguments;
7813 if (i == items)
7814 {
7815 pp=rp->arguments,
7816 sv=ST(i-1);
7817 }
7818 else
7819 for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7820 {
7821 if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7822 break;
7823 if (strEQcase(attribute,qq->method) > ssize_test)
7824 {
7825 pp=qq;
7826 ssize_test=strEQcase(attribute,qq->method);
7827 }
7828 }
7829 if (pp == (Arguments *) NULL)
7830 {
7831 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7832 attribute);
7833 goto continue_outer_loop;
7834 }
7835 al=(&argument_list[pp-rp->arguments]);
7836 switch (pp->type)
7837 {
7838 case ArrayReference:
7839 {
7840 if (SvTYPE(sv) != SVt_RV)
7841 {
cristy151b66d2015-04-15 10:50:31 +00007842 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007843 "invalid %.60s value",pp->method);
7844 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7845 goto continue_outer_loop;
7846 }
7847 al->array_reference=SvRV(sv);
7848 break;
7849 }
7850 case RealReference:
7851 {
7852 al->real_reference=SvNV(sv);
7853 break;
7854 }
7855 case FileReference:
7856 {
7857 al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7858 break;
7859 }
7860 case ImageReference:
7861 {
7862 if (!sv_isobject(sv) ||
7863 !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7864 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7865 {
7866 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7867 PackageName);
7868 goto PerlException;
7869 }
7870 break;
7871 }
7872 case IntegerReference:
7873 {
7874 al->integer_reference=SvIV(sv);
7875 break;
7876 }
7877 case StringReference:
7878 {
7879 al->string_reference=(char *) SvPV(sv,al->length);
7880 if (sv_isobject(sv))
7881 al->image_reference=SetupList(aTHX_ SvRV(sv),
7882 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7883 break;
7884 }
7885 default:
7886 {
7887 /*
7888 Is a string; look up name.
7889 */
7890 if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7891 {
7892 al->string_reference=(char *) SvPV(sv,al->length);
7893 al->integer_reference=(-1);
7894 break;
7895 }
7896 al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7897 MagickFalse,SvPV(sv,na));
7898 if (pp->type == MagickChannelOptions)
7899 al->integer_reference=ParseChannelOption(SvPV(sv,na));
7900 if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7901 {
cristy151b66d2015-04-15 10:50:31 +00007902 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007903 "invalid %.60s value",pp->method);
7904 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7905 goto continue_outer_loop;
7906 }
7907 break;
7908 }
7909 }
7910 attribute_flag[pp-rp->arguments]++;
7911 continue_outer_loop: ;
7912 }
7913 (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7914 pv=reference_vector;
7915 SetGeometryInfo(&geometry_info);
7916 channel=DefaultChannels;
7917 for (next=image; next; next=next->next)
7918 {
7919 image=next;
7920 SetGeometry(image,&geometry);
7921 if ((region_info.width*region_info.height) != 0)
Cristy7e567962018-02-03 12:42:20 -05007922 (void) SetImageRegionMask(image,WritePixelMask,&region_info,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007923 switch (ix)
7924 {
7925 default:
7926 {
cristy151b66d2015-04-15 10:50:31 +00007927 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
cristy4a3ce0a2013-08-03 20:06:59 +00007928 ThrowPerlException(exception,OptionError,
7929 "UnrecognizedPerlMagickMethod",message);
7930 goto PerlException;
7931 }
7932 case 1: /* Comment */
7933 {
7934 if (attribute_flag[0] == 0)
7935 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007936 (void) SetImageProperty(image,"comment",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007937 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007938 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007939 break;
7940 }
7941 case 2: /* Label */
7942 {
7943 if (attribute_flag[0] == 0)
7944 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007945 (void) SetImageProperty(image,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007946 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007947 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007948 break;
7949 }
7950 case 3: /* AddNoise */
7951 {
7952 double
7953 attenuate;
7954
7955 if (attribute_flag[0] == 0)
7956 argument_list[0].integer_reference=UniformNoise;
7957 attenuate=1.0;
7958 if (attribute_flag[1] != 0)
7959 attenuate=argument_list[1].real_reference;
7960 if (attribute_flag[2] != 0)
7961 channel=(ChannelType) argument_list[2].integer_reference;
7962 channel_mask=SetImageChannelMask(image,channel);
7963 image=AddNoiseImage(image,(NoiseType)
7964 argument_list[0].integer_reference,attenuate,exception);
7965 if (image != (Image *) NULL)
7966 (void) SetImageChannelMask(image,channel_mask);
7967 break;
7968 }
7969 case 4: /* Colorize */
7970 {
7971 PixelInfo
7972 target;
7973
7974 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7975 0,0,&target,exception);
7976 if (attribute_flag[0] != 0)
7977 (void) QueryColorCompliance(argument_list[0].string_reference,
7978 AllCompliance,&target,exception);
7979 if (attribute_flag[1] == 0)
7980 argument_list[1].string_reference="100%";
7981 image=ColorizeImage(image,argument_list[1].string_reference,&target,
7982 exception);
7983 break;
7984 }
7985 case 5: /* Border */
7986 {
7987 CompositeOperator
7988 compose;
7989
7990 geometry.width=0;
7991 geometry.height=0;
7992 if (attribute_flag[0] != 0)
7993 flags=ParsePageGeometry(image,argument_list[0].string_reference,
7994 &geometry,exception);
7995 if (attribute_flag[1] != 0)
7996 geometry.width=argument_list[1].integer_reference;
7997 if (attribute_flag[2] != 0)
7998 geometry.height=argument_list[2].integer_reference;
7999 if (attribute_flag[3] != 0)
8000 QueryColorCompliance(argument_list[3].string_reference,
8001 AllCompliance,&image->border_color,exception);
8002 if (attribute_flag[4] != 0)
8003 QueryColorCompliance(argument_list[4].string_reference,
8004 AllCompliance,&image->border_color,exception);
8005 if (attribute_flag[5] != 0)
8006 QueryColorCompliance(argument_list[5].string_reference,
8007 AllCompliance,&image->border_color,exception);
8008 compose=image->compose;
8009 if (attribute_flag[6] != 0)
8010 compose=(CompositeOperator) argument_list[6].integer_reference;
8011 image=BorderImage(image,&geometry,compose,exception);
8012 break;
8013 }
8014 case 6: /* Blur */
8015 {
8016 if (attribute_flag[0] != 0)
8017 {
8018 flags=ParseGeometry(argument_list[0].string_reference,
8019 &geometry_info);
8020 if ((flags & SigmaValue) == 0)
8021 geometry_info.sigma=1.0;
8022 }
8023 if (attribute_flag[1] != 0)
8024 geometry_info.rho=argument_list[1].real_reference;
8025 if (attribute_flag[2] != 0)
8026 geometry_info.sigma=argument_list[2].real_reference;
8027 if (attribute_flag[3] != 0)
8028 channel=(ChannelType) argument_list[3].integer_reference;
8029 channel_mask=SetImageChannelMask(image,channel);
8030 image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
8031 exception);
8032 if (image != (Image *) NULL)
8033 (void) SetImageChannelMask(image,channel_mask);
8034 break;
8035 }
8036 case 7: /* Chop */
8037 {
cristy260bd762014-08-15 12:46:34 +00008038 if (attribute_flag[5] != 0)
8039 image->gravity=(GravityType) argument_list[5].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00008040 if (attribute_flag[0] != 0)
8041 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8042 &geometry,exception);
8043 if (attribute_flag[1] != 0)
8044 geometry.width=argument_list[1].integer_reference;
8045 if (attribute_flag[2] != 0)
8046 geometry.height=argument_list[2].integer_reference;
8047 if (attribute_flag[3] != 0)
8048 geometry.x=argument_list[3].integer_reference;
8049 if (attribute_flag[4] != 0)
8050 geometry.y=argument_list[4].integer_reference;
8051 image=ChopImage(image,&geometry,exception);
8052 break;
8053 }
8054 case 8: /* Crop */
8055 {
8056 if (attribute_flag[6] != 0)
8057 image->gravity=(GravityType) argument_list[6].integer_reference;
8058 if (attribute_flag[0] != 0)
8059 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8060 &geometry,exception);
8061 if (attribute_flag[1] != 0)
8062 geometry.width=argument_list[1].integer_reference;
8063 if (attribute_flag[2] != 0)
8064 geometry.height=argument_list[2].integer_reference;
8065 if (attribute_flag[3] != 0)
8066 geometry.x=argument_list[3].integer_reference;
8067 if (attribute_flag[4] != 0)
8068 geometry.y=argument_list[4].integer_reference;
8069 if (attribute_flag[5] != 0)
8070 image->fuzz=StringToDoubleInterval(
8071 argument_list[5].string_reference,(double) QuantumRange+1.0);
8072 image=CropImage(image,&geometry,exception);
8073 break;
8074 }
8075 case 9: /* Despeckle */
8076 {
8077 image=DespeckleImage(image,exception);
8078 break;
8079 }
8080 case 10: /* Edge */
8081 {
8082 if (attribute_flag[0] != 0)
8083 geometry_info.rho=argument_list[0].real_reference;
8084 image=EdgeImage(image,geometry_info.rho,exception);
8085 break;
8086 }
8087 case 11: /* Emboss */
8088 {
8089 if (attribute_flag[0] != 0)
8090 {
8091 flags=ParseGeometry(argument_list[0].string_reference,
8092 &geometry_info);
8093 if ((flags & SigmaValue) == 0)
8094 geometry_info.sigma=1.0;
8095 }
8096 if (attribute_flag[1] != 0)
8097 geometry_info.rho=argument_list[1].real_reference;
8098 if (attribute_flag[2] != 0)
8099 geometry_info.sigma=argument_list[2].real_reference;
8100 image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8101 exception);
8102 break;
8103 }
8104 case 12: /* Enhance */
8105 {
8106 image=EnhanceImage(image,exception);
8107 break;
8108 }
8109 case 13: /* Flip */
8110 {
8111 image=FlipImage(image,exception);
8112 break;
8113 }
8114 case 14: /* Flop */
8115 {
8116 image=FlopImage(image,exception);
8117 break;
8118 }
8119 case 15: /* Frame */
8120 {
8121 CompositeOperator
8122 compose;
8123
8124 FrameInfo
8125 frame_info;
8126
8127 if (attribute_flag[0] != 0)
8128 {
8129 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8130 &geometry,exception);
8131 frame_info.width=geometry.width;
8132 frame_info.height=geometry.height;
8133 frame_info.outer_bevel=geometry.x;
8134 frame_info.inner_bevel=geometry.y;
8135 }
8136 if (attribute_flag[1] != 0)
8137 frame_info.width=argument_list[1].integer_reference;
8138 if (attribute_flag[2] != 0)
8139 frame_info.height=argument_list[2].integer_reference;
8140 if (attribute_flag[3] != 0)
8141 frame_info.inner_bevel=argument_list[3].integer_reference;
8142 if (attribute_flag[4] != 0)
8143 frame_info.outer_bevel=argument_list[4].integer_reference;
8144 if (attribute_flag[5] != 0)
8145 QueryColorCompliance(argument_list[5].string_reference,
8146 AllCompliance,&fill_color,exception);
8147 if (attribute_flag[6] != 0)
8148 QueryColorCompliance(argument_list[6].string_reference,
8149 AllCompliance,&fill_color,exception);
8150 frame_info.x=(ssize_t) frame_info.width;
8151 frame_info.y=(ssize_t) frame_info.height;
8152 frame_info.width=image->columns+2*frame_info.x;
8153 frame_info.height=image->rows+2*frame_info.y;
8154 if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
Cristy8645e042016-02-03 16:35:29 -05008155 image->alpha_color=fill_color;
cristy4a3ce0a2013-08-03 20:06:59 +00008156 compose=image->compose;
8157 if (attribute_flag[7] != 0)
8158 compose=(CompositeOperator) argument_list[7].integer_reference;
8159 image=FrameImage(image,&frame_info,compose,exception);
8160 break;
8161 }
8162 case 16: /* Implode */
8163 {
8164 PixelInterpolateMethod
8165 method;
8166
8167 if (attribute_flag[0] == 0)
8168 argument_list[0].real_reference=0.5;
8169 method=UndefinedInterpolatePixel;
8170 if (attribute_flag[1] != 0)
8171 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8172 image=ImplodeImage(image,argument_list[0].real_reference,
8173 method,exception);
8174 break;
8175 }
8176 case 17: /* Magnify */
8177 {
8178 image=MagnifyImage(image,exception);
8179 break;
8180 }
8181 case 18: /* MedianFilter */
8182 {
8183 if (attribute_flag[0] != 0)
8184 {
8185 flags=ParseGeometry(argument_list[0].string_reference,
8186 &geometry_info);
8187 if ((flags & SigmaValue) == 0)
8188 geometry_info.sigma=geometry_info.rho;
8189 }
8190 if (attribute_flag[1] != 0)
8191 geometry_info.rho=argument_list[1].real_reference;
8192 if (attribute_flag[2] != 0)
8193 geometry_info.sigma=argument_list[2].real_reference;
8194 if (attribute_flag[3] != 0)
8195 channel=(ChannelType) argument_list[3].integer_reference;
8196 channel_mask=SetImageChannelMask(image,channel);
8197 image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8198 (size_t) geometry_info.sigma,exception);
8199 if (image != (Image *) NULL)
8200 (void) SetImageChannelMask(image,channel_mask);
8201 break;
8202 }
8203 case 19: /* Minify */
8204 {
8205 image=MinifyImage(image,exception);
8206 break;
8207 }
8208 case 20: /* OilPaint */
8209 {
8210 if (attribute_flag[0] == 0)
8211 argument_list[0].real_reference=0.0;
8212 if (attribute_flag[1] == 0)
8213 argument_list[1].real_reference=1.0;
8214 image=OilPaintImage(image,argument_list[0].real_reference,
8215 argument_list[1].real_reference,exception);
8216 break;
8217 }
8218 case 21: /* ReduceNoise */
8219 {
8220 if (attribute_flag[0] != 0)
8221 {
8222 flags=ParseGeometry(argument_list[0].string_reference,
8223 &geometry_info);
8224 if ((flags & SigmaValue) == 0)
8225 geometry_info.sigma=1.0;
8226 }
8227 if (attribute_flag[1] != 0)
8228 geometry_info.rho=argument_list[1].real_reference;
8229 if (attribute_flag[2] != 0)
8230 geometry_info.sigma=argument_list[2].real_reference;
8231 if (attribute_flag[3] != 0)
8232 channel=(ChannelType) argument_list[3].integer_reference;
8233 channel_mask=SetImageChannelMask(image,channel);
8234 image=StatisticImage(image,NonpeakStatistic,(size_t)
8235 geometry_info.rho,(size_t) geometry_info.sigma,exception);
8236 if (image != (Image *) NULL)
8237 (void) SetImageChannelMask(image,channel_mask);
8238 break;
8239 }
8240 case 22: /* Roll */
8241 {
8242 if (attribute_flag[0] != 0)
Cristyf94b0842017-07-14 07:05:02 -04008243 {
8244 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8245 &geometry,exception);
8246 if ((flags & PercentValue) != 0)
8247 {
8248 geometry.x*=(double) image->columns/100.0;
8249 geometry.y*=(double) image->rows/100.0;
8250 }
8251 }
cristy4a3ce0a2013-08-03 20:06:59 +00008252 if (attribute_flag[1] != 0)
8253 geometry.x=argument_list[1].integer_reference;
8254 if (attribute_flag[2] != 0)
8255 geometry.y=argument_list[2].integer_reference;
8256 image=RollImage(image,geometry.x,geometry.y,exception);
8257 break;
8258 }
8259 case 23: /* Rotate */
8260 {
8261 if (attribute_flag[0] == 0)
8262 argument_list[0].real_reference=90.0;
8263 if (attribute_flag[1] != 0)
8264 {
8265 QueryColorCompliance(argument_list[1].string_reference,
8266 AllCompliance,&image->background_color,exception);
cristy17f11b02014-12-20 19:37:04 +00008267 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8268 (image->alpha_trait == UndefinedPixelTrait))
cristy4a3ce0a2013-08-03 20:06:59 +00008269 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8270 }
8271 image=RotateImage(image,argument_list[0].real_reference,exception);
8272 break;
8273 }
8274 case 24: /* Sample */
8275 {
8276 if (attribute_flag[0] != 0)
8277 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8278 &geometry,exception);
8279 if (attribute_flag[1] != 0)
8280 geometry.width=argument_list[1].integer_reference;
8281 if (attribute_flag[2] != 0)
8282 geometry.height=argument_list[2].integer_reference;
8283 image=SampleImage(image,geometry.width,geometry.height,exception);
8284 break;
8285 }
8286 case 25: /* Scale */
8287 {
8288 if (attribute_flag[0] != 0)
8289 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8290 &geometry,exception);
8291 if (attribute_flag[1] != 0)
8292 geometry.width=argument_list[1].integer_reference;
8293 if (attribute_flag[2] != 0)
8294 geometry.height=argument_list[2].integer_reference;
8295 image=ScaleImage(image,geometry.width,geometry.height,exception);
8296 break;
8297 }
8298 case 26: /* Shade */
8299 {
8300 if (attribute_flag[0] != 0)
8301 {
8302 flags=ParseGeometry(argument_list[0].string_reference,
8303 &geometry_info);
8304 if ((flags & SigmaValue) == 0)
8305 geometry_info.sigma=0.0;
8306 }
8307 if (attribute_flag[1] != 0)
8308 geometry_info.rho=argument_list[1].real_reference;
8309 if (attribute_flag[2] != 0)
8310 geometry_info.sigma=argument_list[2].real_reference;
8311 image=ShadeImage(image,
8312 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8313 geometry_info.rho,geometry_info.sigma,exception);
8314 break;
8315 }
8316 case 27: /* Sharpen */
8317 {
8318 if (attribute_flag[0] != 0)
8319 {
8320 flags=ParseGeometry(argument_list[0].string_reference,
8321 &geometry_info);
8322 if ((flags & SigmaValue) == 0)
8323 geometry_info.sigma=1.0;
8324 }
8325 if (attribute_flag[1] != 0)
8326 geometry_info.rho=argument_list[1].real_reference;
8327 if (attribute_flag[2] != 0)
8328 geometry_info.sigma=argument_list[2].real_reference;
8329 if (attribute_flag[3] != 0)
8330 channel=(ChannelType) argument_list[3].integer_reference;
8331 channel_mask=SetImageChannelMask(image,channel);
8332 image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8333 exception);
8334 if (image != (Image *) NULL)
8335 (void) SetImageChannelMask(image,channel_mask);
8336 break;
8337 }
8338 case 28: /* Shear */
8339 {
8340 if (attribute_flag[0] != 0)
8341 {
8342 flags=ParseGeometry(argument_list[0].string_reference,
8343 &geometry_info);
8344 if ((flags & SigmaValue) == 0)
8345 geometry_info.sigma=geometry_info.rho;
8346 }
8347 if (attribute_flag[1] != 0)
8348 geometry_info.rho=argument_list[1].real_reference;
8349 if (attribute_flag[2] != 0)
8350 geometry_info.sigma=argument_list[2].real_reference;
8351 if (attribute_flag[3] != 0)
8352 QueryColorCompliance(argument_list[3].string_reference,
8353 AllCompliance,&image->background_color,exception);
8354 if (attribute_flag[4] != 0)
8355 QueryColorCompliance(argument_list[4].string_reference,
8356 AllCompliance,&image->background_color,exception);
8357 image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8358 exception);
8359 break;
8360 }
8361 case 29: /* Spread */
8362 {
Cristye3319c12015-08-24 07:11:48 -04008363 PixelInterpolateMethod
8364 method;
8365
cristy4a3ce0a2013-08-03 20:06:59 +00008366 if (attribute_flag[0] == 0)
8367 argument_list[0].real_reference=1.0;
Cristye3319c12015-08-24 07:11:48 -04008368 method=UndefinedInterpolatePixel;
8369 if (attribute_flag[1] != 0)
8370 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8371 image=SpreadImage(image,method,argument_list[0].real_reference,
8372 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008373 break;
8374 }
8375 case 30: /* Swirl */
8376 {
8377 PixelInterpolateMethod
8378 method;
8379
8380 if (attribute_flag[0] == 0)
8381 argument_list[0].real_reference=50.0;
8382 method=UndefinedInterpolatePixel;
8383 if (attribute_flag[1] != 0)
8384 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8385 image=SwirlImage(image,argument_list[0].real_reference,
8386 method,exception);
8387 break;
8388 }
8389 case 31: /* Resize */
8390 case 32: /* Zoom */
8391 {
8392 if (attribute_flag[0] != 0)
8393 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8394 &geometry,exception);
8395 if (attribute_flag[1] != 0)
8396 geometry.width=argument_list[1].integer_reference;
8397 if (attribute_flag[2] != 0)
8398 geometry.height=argument_list[2].integer_reference;
8399 if (attribute_flag[3] == 0)
8400 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8401 if (attribute_flag[4] != 0)
8402 SetImageArtifact(image,"filter:support",
8403 argument_list[4].string_reference);
8404 image=ResizeImage(image,geometry.width,geometry.height,
Cristy8645e042016-02-03 16:35:29 -05008405 (FilterType) argument_list[3].integer_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00008406 exception);
8407 break;
8408 }
8409 case 33: /* Annotate */
8410 {
8411 DrawInfo
8412 *draw_info;
8413
8414 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8415 (DrawInfo *) NULL);
8416 if (attribute_flag[0] != 0)
8417 {
8418 char
8419 *text;
8420
8421 text=InterpretImageProperties(info ? info->image_info :
8422 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8423 exception);
8424 (void) CloneString(&draw_info->text,text);
8425 text=DestroyString(text);
8426 }
8427 if (attribute_flag[1] != 0)
8428 (void) CloneString(&draw_info->font,
8429 argument_list[1].string_reference);
8430 if (attribute_flag[2] != 0)
8431 draw_info->pointsize=argument_list[2].real_reference;
8432 if (attribute_flag[3] != 0)
8433 (void) CloneString(&draw_info->density,
8434 argument_list[3].string_reference);
8435 if (attribute_flag[4] != 0)
8436 (void) QueryColorCompliance(argument_list[4].string_reference,
8437 AllCompliance,&draw_info->undercolor,exception);
8438 if (attribute_flag[5] != 0)
8439 {
8440 (void) QueryColorCompliance(argument_list[5].string_reference,
8441 AllCompliance,&draw_info->stroke,exception);
8442 if (argument_list[5].image_reference != (Image *) NULL)
8443 draw_info->stroke_pattern=CloneImage(
8444 argument_list[5].image_reference,0,0,MagickTrue,exception);
8445 }
8446 if (attribute_flag[6] != 0)
8447 {
8448 (void) QueryColorCompliance(argument_list[6].string_reference,
8449 AllCompliance,&draw_info->fill,exception);
8450 if (argument_list[6].image_reference != (Image *) NULL)
8451 draw_info->fill_pattern=CloneImage(
8452 argument_list[6].image_reference,0,0,MagickTrue,exception);
8453 }
8454 if (attribute_flag[7] != 0)
8455 {
8456 (void) CloneString(&draw_info->geometry,
8457 argument_list[7].string_reference);
8458 flags=ParsePageGeometry(image,argument_list[7].string_reference,
8459 &geometry,exception);
8460 if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8461 geometry_info.sigma=geometry_info.xi;
8462 }
8463 if (attribute_flag[8] != 0)
8464 (void) QueryColorCompliance(argument_list[8].string_reference,
8465 AllCompliance,&draw_info->fill,exception);
8466 if (attribute_flag[11] != 0)
8467 draw_info->gravity=(GravityType)
8468 argument_list[11].integer_reference;
8469 if (attribute_flag[25] != 0)
8470 {
8471 AV
8472 *av;
8473
8474 av=(AV *) argument_list[25].array_reference;
8475 if ((av_len(av) != 3) && (av_len(av) != 5))
8476 {
8477 ThrowPerlException(exception,OptionError,
8478 "affine matrix must have 4 or 6 elements",PackageName);
8479 goto PerlException;
8480 }
8481 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8482 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8483 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8484 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8485 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8486 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8487 {
8488 ThrowPerlException(exception,OptionError,
8489 "affine matrix is singular",PackageName);
8490 goto PerlException;
8491 }
8492 if (av_len(av) == 5)
8493 {
8494 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8495 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8496 }
8497 }
8498 for (j=12; j < 17; j++)
8499 {
8500 if (attribute_flag[j] == 0)
8501 continue;
8502 value=argument_list[j].string_reference;
8503 angle=argument_list[j].real_reference;
8504 current=draw_info->affine;
8505 GetAffineMatrix(&affine);
8506 switch (j)
8507 {
8508 case 12:
8509 {
8510 /*
8511 Translate.
8512 */
8513 flags=ParseGeometry(value,&geometry_info);
8514 affine.tx=geometry_info.xi;
8515 affine.ty=geometry_info.psi;
8516 if ((flags & PsiValue) == 0)
8517 affine.ty=affine.tx;
8518 break;
8519 }
8520 case 13:
8521 {
8522 /*
8523 Scale.
8524 */
8525 flags=ParseGeometry(value,&geometry_info);
8526 affine.sx=geometry_info.rho;
8527 affine.sy=geometry_info.sigma;
8528 if ((flags & SigmaValue) == 0)
8529 affine.sy=affine.sx;
8530 break;
8531 }
8532 case 14:
8533 {
8534 /*
8535 Rotate.
8536 */
8537 if (angle == 0.0)
8538 break;
8539 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8540 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8541 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8542 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8543 break;
8544 }
8545 case 15:
8546 {
8547 /*
8548 SkewX.
8549 */
8550 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8551 break;
8552 }
8553 case 16:
8554 {
8555 /*
8556 SkewY.
8557 */
8558 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8559 break;
8560 }
8561 }
8562 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8563 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8564 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8565 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8566 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8567 current.tx;
8568 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8569 current.ty;
8570 }
8571 if (attribute_flag[9] == 0)
8572 argument_list[9].real_reference=0.0;
8573 if (attribute_flag[10] == 0)
8574 argument_list[10].real_reference=0.0;
8575 if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8576 {
8577 char
cristy151b66d2015-04-15 10:50:31 +00008578 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008579
cristy151b66d2015-04-15 10:50:31 +00008580 (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
cristy4a3ce0a2013-08-03 20:06:59 +00008581 (double) argument_list[9].real_reference+draw_info->affine.tx,
8582 (double) argument_list[10].real_reference+draw_info->affine.ty);
8583 (void) CloneString(&draw_info->geometry,geometry);
8584 }
8585 if (attribute_flag[17] != 0)
8586 draw_info->stroke_width=argument_list[17].real_reference;
8587 if (attribute_flag[18] != 0)
8588 {
8589 draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8590 MagickTrue : MagickFalse;
8591 draw_info->stroke_antialias=draw_info->text_antialias;
8592 }
8593 if (attribute_flag[19] != 0)
8594 (void) CloneString(&draw_info->family,
8595 argument_list[19].string_reference);
8596 if (attribute_flag[20] != 0)
8597 draw_info->style=(StyleType) argument_list[20].integer_reference;
8598 if (attribute_flag[21] != 0)
8599 draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8600 if (attribute_flag[22] != 0)
8601 draw_info->weight=argument_list[22].integer_reference;
8602 if (attribute_flag[23] != 0)
8603 draw_info->align=(AlignType) argument_list[23].integer_reference;
8604 if (attribute_flag[24] != 0)
8605 (void) CloneString(&draw_info->encoding,
8606 argument_list[24].string_reference);
8607 if (attribute_flag[25] != 0)
8608 draw_info->fill_pattern=CloneImage(
8609 argument_list[25].image_reference,0,0,MagickTrue,exception);
8610 if (attribute_flag[26] != 0)
8611 draw_info->fill_pattern=CloneImage(
8612 argument_list[26].image_reference,0,0,MagickTrue,exception);
8613 if (attribute_flag[27] != 0)
8614 draw_info->stroke_pattern=CloneImage(
8615 argument_list[27].image_reference,0,0,MagickTrue,exception);
8616 if (attribute_flag[29] != 0)
8617 draw_info->kerning=argument_list[29].real_reference;
8618 if (attribute_flag[30] != 0)
8619 draw_info->interline_spacing=argument_list[30].real_reference;
8620 if (attribute_flag[31] != 0)
8621 draw_info->interword_spacing=argument_list[31].real_reference;
8622 if (attribute_flag[32] != 0)
8623 draw_info->direction=(DirectionType)
8624 argument_list[32].integer_reference;
Cristy3d1de822019-02-15 18:06:30 -05008625 if (attribute_flag[33] != 0)
8626 draw_info->decorate=(DecorationType)
8627 argument_list[33].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00008628 (void) AnnotateImage(image,draw_info,exception);
8629 draw_info=DestroyDrawInfo(draw_info);
8630 break;
8631 }
8632 case 34: /* ColorFloodfill */
8633 {
8634 DrawInfo
8635 *draw_info;
8636
8637 MagickBooleanType
8638 invert;
8639
8640 PixelInfo
8641 target;
8642
8643 draw_info=CloneDrawInfo(info ? info->image_info :
8644 (ImageInfo *) NULL,(DrawInfo *) NULL);
8645 if (attribute_flag[0] != 0)
8646 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8647 &geometry,exception);
8648 if (attribute_flag[1] != 0)
8649 geometry.x=argument_list[1].integer_reference;
8650 if (attribute_flag[2] != 0)
8651 geometry.y=argument_list[2].integer_reference;
8652 if (attribute_flag[3] != 0)
8653 (void) QueryColorCompliance(argument_list[3].string_reference,
8654 AllCompliance,&draw_info->fill,exception);
8655 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8656 geometry.x,geometry.y,&target,exception);
8657 invert=MagickFalse;
8658 if (attribute_flag[4] != 0)
8659 {
8660 QueryColorCompliance(argument_list[4].string_reference,
8661 AllCompliance,&target,exception);
8662 invert=MagickTrue;
8663 }
8664 if (attribute_flag[5] != 0)
8665 image->fuzz=StringToDoubleInterval(
8666 argument_list[5].string_reference,(double) QuantumRange+1.0);
8667 if (attribute_flag[6] != 0)
8668 invert=(MagickBooleanType) argument_list[6].integer_reference;
8669 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8670 geometry.y,invert,exception);
8671 draw_info=DestroyDrawInfo(draw_info);
8672 break;
8673 }
8674 case 35: /* Composite */
8675 {
8676 char
cristy151b66d2015-04-15 10:50:31 +00008677 composite_geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008678
8679 Image
8680 *composite_image,
8681 *rotate_image;
8682
8683 MagickBooleanType
8684 clip_to_self;
8685
8686 compose=OverCompositeOp;
8687 if (attribute_flag[0] != 0)
8688 composite_image=argument_list[0].image_reference;
8689 else
8690 {
8691 ThrowPerlException(exception,OptionError,
8692 "CompositeImageRequired",PackageName);
8693 goto PerlException;
8694 }
8695 /*
8696 Parameter Handling used for BOTH normal and tiled composition.
8697 */
8698 if (attribute_flag[1] != 0) /* compose */
8699 compose=(CompositeOperator) argument_list[1].integer_reference;
8700 if (attribute_flag[6] != 0) /* opacity */
8701 {
8702 if (compose != DissolveCompositeOp)
8703 (void) SetImageAlpha(composite_image,(Quantum)
8704 StringToDoubleInterval(argument_list[6].string_reference,
8705 (double) QuantumRange+1.0),exception);
8706 else
8707 {
8708 CacheView
8709 *composite_view;
8710
8711 double
8712 opacity;
8713
8714 MagickBooleanType
8715 sync;
8716
8717 register ssize_t
8718 x;
8719
8720 register Quantum
8721 *q;
8722
8723 ssize_t
8724 y;
8725
8726 /*
8727 Handle dissolve composite operator (patch by
8728 Kevin A. McGrail).
8729 */
8730 (void) CloneString(&image->geometry,
8731 argument_list[6].string_reference);
8732 opacity=(Quantum) StringToDoubleInterval(
8733 argument_list[6].string_reference,(double) QuantumRange+
8734 1.0);
cristy17f11b02014-12-20 19:37:04 +00008735 if (composite_image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00008736 (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8737 composite_view=AcquireAuthenticCacheView(composite_image,exception);
8738 for (y=0; y < (ssize_t) composite_image->rows ; y++)
8739 {
8740 q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8741 composite_image->columns,1,exception);
8742 for (x=0; x < (ssize_t) composite_image->columns; x++)
8743 {
8744 if (GetPixelAlpha(image,q) == OpaqueAlpha)
8745 SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8746 q);
8747 q+=GetPixelChannels(composite_image);
8748 }
8749 sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8750 if (sync == MagickFalse)
8751 break;
8752 }
8753 composite_view=DestroyCacheView(composite_view);
8754 }
8755 }
8756 if (attribute_flag[9] != 0) /* "color=>" */
8757 QueryColorCompliance(argument_list[9].string_reference,
8758 AllCompliance,&composite_image->background_color,exception);
8759 if (attribute_flag[12] != 0) /* "interpolate=>" */
8760 image->interpolate=(PixelInterpolateMethod)
8761 argument_list[12].integer_reference;
8762 if (attribute_flag[13] != 0) /* "args=>" */
8763 (void) SetImageArtifact(composite_image,"compose:args",
8764 argument_list[13].string_reference);
8765 if (attribute_flag[14] != 0) /* "blend=>" depreciated */
8766 (void) SetImageArtifact(composite_image,"compose:args",
8767 argument_list[14].string_reference);
Cristy72aed842018-07-08 18:25:50 -04008768 clip_to_self=MagickTrue;
8769 switch (compose)
8770 {
8771 case ClearCompositeOp:
8772 case SrcCompositeOp:
8773 case InCompositeOp:
8774 case SrcInCompositeOp:
8775 case OutCompositeOp:
8776 case SrcOutCompositeOp:
8777 case DstInCompositeOp:
8778 case DstAtopCompositeOp:
Cristy901f5212018-07-08 18:43:34 -04008779 case CopyAlphaCompositeOp:
Cristy72aed842018-07-08 18:25:50 -04008780 case ChangeMaskCompositeOp:
8781 case DissolveCompositeOp:
8782 case BlendCompositeOp:
8783 {
Cristy901f5212018-07-08 18:43:34 -04008784 clip_to_self=MagickFalse;
Cristy72aed842018-07-08 18:25:50 -04008785 break;
8786 }
8787 default:
8788 break;
8789 }
cristy4a3ce0a2013-08-03 20:06:59 +00008790 if (attribute_flag[15] != 0)
8791 clip_to_self=(MagickBooleanType)
8792 argument_list[15].integer_reference;
8793 /*
8794 Tiling Composition (with orthogonal rotate).
8795 */
8796 rotate_image=(Image *) NULL;
8797 if (attribute_flag[8] != 0) /* "rotate=>" */
8798 {
8799 /*
8800 Rotate image.
8801 */
8802 rotate_image=RotateImage(composite_image,
8803 argument_list[8].real_reference,exception);
8804 if (rotate_image == (Image *) NULL)
8805 break;
8806 }
8807 if ((attribute_flag[7] != 0) &&
8808 (argument_list[7].integer_reference != 0)) /* tile */
8809 {
8810 ssize_t
8811 x,
8812 y;
8813
8814 /*
8815 Tile the composite image.
8816 */
cristy4a3ce0a2013-08-03 20:06:59 +00008817 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8818 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8819 {
8820 if (attribute_flag[8] != 0) /* rotate */
8821 (void) CompositeImage(image,rotate_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008822 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008823 else
8824 (void) CompositeImage(image,composite_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008825 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008826 }
8827 if (attribute_flag[8] != 0) /* rotate */
8828 rotate_image=DestroyImage(rotate_image);
8829 break;
8830 }
8831 /*
8832 Parameter Handling used used ONLY for normal composition.
8833 */
8834 if (attribute_flag[5] != 0) /* gravity */
8835 image->gravity=(GravityType) argument_list[5].integer_reference;
8836 if (attribute_flag[2] != 0) /* geometry offset */
8837 {
8838 SetGeometry(image,&geometry);
8839 (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8840 &geometry);
8841 GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8842 &geometry);
8843 }
8844 if (attribute_flag[3] != 0) /* x offset */
8845 geometry.x=argument_list[3].integer_reference;
8846 if (attribute_flag[4] != 0) /* y offset */
8847 geometry.y=argument_list[4].integer_reference;
8848 if (attribute_flag[10] != 0) /* mask */
8849 {
8850 if ((image->compose == DisplaceCompositeOp) ||
8851 (image->compose == DistortCompositeOp))
8852 {
8853 /*
8854 Merge Y displacement into X displacement image.
8855 */
8856 composite_image=CloneImage(composite_image,0,0,MagickTrue,
8857 exception);
8858 (void) CompositeImage(composite_image,
8859 argument_list[10].image_reference,CopyGreenCompositeOp,
Cristy74e39292018-07-08 13:13:20 -04008860 clip_to_self,0,0,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008861 }
8862 else
8863 {
8864 Image
8865 *mask_image;
8866
8867 /*
8868 Set a blending mask for the composition.
8869 */
8870 mask_image=CloneImage(argument_list[10].image_reference,0,0,
8871 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +00008872 (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
cristyf3023752015-07-28 17:13:22 +00008873 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008874 mask_image=DestroyImage(mask_image);
8875 }
8876 }
8877 if (attribute_flag[11] != 0) /* channel */
8878 channel=(ChannelType) argument_list[11].integer_reference;
8879 /*
8880 Composite two images (normal composition).
8881 */
cristy151b66d2015-04-15 10:50:31 +00008882 (void) FormatLocaleString(composite_geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00008883 "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8884 (double) composite_image->rows,(double) geometry.x,(double)
8885 geometry.y);
8886 flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8887 exception);
8888 channel_mask=SetImageChannelMask(image,channel);
8889 if (attribute_flag[8] == 0) /* no rotate */
8890 CompositeImage(image,composite_image,compose,clip_to_self,
8891 geometry.x,geometry.y,exception);
8892 else
8893 {
8894 /*
8895 Position adjust rotated image then composite.
8896 */
8897 geometry.x-=(ssize_t) (rotate_image->columns-
8898 composite_image->columns)/2;
8899 geometry.y-=(ssize_t) (rotate_image->rows-
8900 composite_image->rows)/2;
8901 CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8902 geometry.y,exception);
8903 rotate_image=DestroyImage(rotate_image);
8904 }
8905 if (attribute_flag[10] != 0) /* mask */
8906 {
8907 if ((image->compose == DisplaceCompositeOp) ||
8908 (image->compose == DistortCompositeOp))
8909 composite_image=DestroyImage(composite_image);
8910 else
cristy1f7ffb72015-07-29 11:07:03 +00008911 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
cristyf3023752015-07-28 17:13:22 +00008912 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008913 }
8914 (void) SetImageChannelMask(image,channel_mask);
8915 break;
8916 }
8917 case 36: /* Contrast */
8918 {
8919 if (attribute_flag[0] == 0)
8920 argument_list[0].integer_reference=0;
8921 (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8922 MagickTrue : MagickFalse,exception);
8923 break;
8924 }
8925 case 37: /* CycleColormap */
8926 {
8927 if (attribute_flag[0] == 0)
8928 argument_list[0].integer_reference=6;
8929 (void) CycleColormapImage(image,argument_list[0].integer_reference,
8930 exception);
8931 break;
8932 }
8933 case 38: /* Draw */
8934 {
8935 DrawInfo
8936 *draw_info;
8937
8938 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8939 (DrawInfo *) NULL);
8940 (void) CloneString(&draw_info->primitive,"point");
8941 if (attribute_flag[0] != 0)
8942 {
8943 if (argument_list[0].integer_reference < 0)
8944 (void) CloneString(&draw_info->primitive,
8945 argument_list[0].string_reference);
8946 else
8947 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8948 MagickPrimitiveOptions,argument_list[0].integer_reference));
8949 }
8950 if (attribute_flag[1] != 0)
8951 {
8952 if (LocaleCompare(draw_info->primitive,"path") == 0)
8953 {
8954 (void) ConcatenateString(&draw_info->primitive," '");
8955 ConcatenateString(&draw_info->primitive,
8956 argument_list[1].string_reference);
8957 (void) ConcatenateString(&draw_info->primitive,"'");
8958 }
8959 else
8960 {
8961 (void) ConcatenateString(&draw_info->primitive," ");
8962 ConcatenateString(&draw_info->primitive,
8963 argument_list[1].string_reference);
8964 }
8965 }
8966 if (attribute_flag[2] != 0)
8967 {
8968 (void) ConcatenateString(&draw_info->primitive," ");
8969 (void) ConcatenateString(&draw_info->primitive,
8970 CommandOptionToMnemonic(MagickMethodOptions,
8971 argument_list[2].integer_reference));
8972 }
8973 if (attribute_flag[3] != 0)
8974 {
8975 (void) QueryColorCompliance(argument_list[3].string_reference,
8976 AllCompliance,&draw_info->stroke,exception);
8977 if (argument_list[3].image_reference != (Image *) NULL)
8978 draw_info->stroke_pattern=CloneImage(
8979 argument_list[3].image_reference,0,0,MagickTrue,exception);
8980 }
8981 if (attribute_flag[4] != 0)
8982 {
8983 (void) QueryColorCompliance(argument_list[4].string_reference,
8984 AllCompliance,&draw_info->fill,exception);
8985 if (argument_list[4].image_reference != (Image *) NULL)
8986 draw_info->fill_pattern=CloneImage(
8987 argument_list[4].image_reference,0,0,MagickTrue,exception);
8988 }
8989 if (attribute_flag[5] != 0)
8990 draw_info->stroke_width=argument_list[5].real_reference;
8991 if (attribute_flag[6] != 0)
8992 (void) CloneString(&draw_info->font,
8993 argument_list[6].string_reference);
8994 if (attribute_flag[7] != 0)
8995 (void) QueryColorCompliance(argument_list[7].string_reference,
8996 AllCompliance,&draw_info->border_color,exception);
8997 if (attribute_flag[8] != 0)
8998 draw_info->affine.tx=argument_list[8].real_reference;
8999 if (attribute_flag[9] != 0)
9000 draw_info->affine.ty=argument_list[9].real_reference;
9001 if (attribute_flag[20] != 0)
9002 {
9003 AV
9004 *av;
9005
9006 av=(AV *) argument_list[20].array_reference;
9007 if ((av_len(av) != 3) && (av_len(av) != 5))
9008 {
9009 ThrowPerlException(exception,OptionError,
9010 "affine matrix must have 4 or 6 elements",PackageName);
9011 goto PerlException;
9012 }
9013 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9014 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9015 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9016 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9017 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9018 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9019 {
9020 ThrowPerlException(exception,OptionError,
9021 "affine matrix is singular",PackageName);
9022 goto PerlException;
9023 }
9024 if (av_len(av) == 5)
9025 {
9026 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9027 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9028 }
9029 }
9030 for (j=10; j < 15; j++)
9031 {
9032 if (attribute_flag[j] == 0)
9033 continue;
9034 value=argument_list[j].string_reference;
9035 angle=argument_list[j].real_reference;
9036 current=draw_info->affine;
9037 GetAffineMatrix(&affine);
9038 switch (j)
9039 {
9040 case 10:
9041 {
9042 /*
9043 Translate.
9044 */
9045 flags=ParseGeometry(value,&geometry_info);
9046 affine.tx=geometry_info.xi;
9047 affine.ty=geometry_info.psi;
9048 if ((flags & PsiValue) == 0)
9049 affine.ty=affine.tx;
9050 break;
9051 }
9052 case 11:
9053 {
9054 /*
9055 Scale.
9056 */
9057 flags=ParseGeometry(value,&geometry_info);
9058 affine.sx=geometry_info.rho;
9059 affine.sy=geometry_info.sigma;
9060 if ((flags & SigmaValue) == 0)
9061 affine.sy=affine.sx;
9062 break;
9063 }
9064 case 12:
9065 {
9066 /*
9067 Rotate.
9068 */
9069 if (angle == 0.0)
9070 break;
9071 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9072 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9073 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9074 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9075 break;
9076 }
9077 case 13:
9078 {
9079 /*
9080 SkewX.
9081 */
9082 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9083 break;
9084 }
9085 case 14:
9086 {
9087 /*
9088 SkewY.
9089 */
9090 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9091 break;
9092 }
9093 }
9094 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9095 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9096 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9097 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9098 draw_info->affine.tx=
9099 current.sx*affine.tx+current.ry*affine.ty+current.tx;
9100 draw_info->affine.ty=
9101 current.rx*affine.tx+current.sy*affine.ty+current.ty;
9102 }
9103 if (attribute_flag[15] != 0)
9104 draw_info->fill_pattern=CloneImage(
9105 argument_list[15].image_reference,0,0,MagickTrue,exception);
9106 if (attribute_flag[16] != 0)
9107 draw_info->pointsize=argument_list[16].real_reference;
9108 if (attribute_flag[17] != 0)
9109 {
Cristy36c30b62018-11-22 09:33:30 -05009110 draw_info->stroke_antialias=argument_list[17].integer_reference != 0 ? MagickTrue : MagickFalse;
cristy4a3ce0a2013-08-03 20:06:59 +00009111 draw_info->text_antialias=draw_info->stroke_antialias;
9112 }
9113 if (attribute_flag[18] != 0)
9114 (void) CloneString(&draw_info->density,
9115 argument_list[18].string_reference);
9116 if (attribute_flag[19] != 0)
9117 draw_info->stroke_width=argument_list[19].real_reference;
9118 if (attribute_flag[21] != 0)
9119 draw_info->dash_offset=argument_list[21].real_reference;
9120 if (attribute_flag[22] != 0)
9121 {
9122 AV
9123 *av;
9124
9125 av=(AV *) argument_list[22].array_reference;
9126 draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9127 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9128 if (draw_info->dash_pattern != (double *) NULL)
9129 {
9130 for (i=0; i <= av_len(av); i++)
9131 draw_info->dash_pattern[i]=(double)
9132 SvNV(*(av_fetch(av,i,0)));
9133 draw_info->dash_pattern[i]=0.0;
9134 }
9135 }
9136 if (attribute_flag[23] != 0)
9137 image->interpolate=(PixelInterpolateMethod)
9138 argument_list[23].integer_reference;
9139 if ((attribute_flag[24] != 0) &&
9140 (draw_info->fill_pattern != (Image *) NULL))
9141 flags=ParsePageGeometry(draw_info->fill_pattern,
9142 argument_list[24].string_reference,
9143 &draw_info->fill_pattern->tile_offset,exception);
9144 if (attribute_flag[25] != 0)
9145 {
9146 (void) ConcatenateString(&draw_info->primitive," '");
9147 (void) ConcatenateString(&draw_info->primitive,
9148 argument_list[25].string_reference);
9149 (void) ConcatenateString(&draw_info->primitive,"'");
9150 }
9151 if (attribute_flag[26] != 0)
9152 draw_info->fill_pattern=CloneImage(
9153 argument_list[26].image_reference,0,0,MagickTrue,exception);
9154 if (attribute_flag[27] != 0)
9155 draw_info->stroke_pattern=CloneImage(
9156 argument_list[27].image_reference,0,0,MagickTrue,exception);
9157 if (attribute_flag[28] != 0)
9158 (void) CloneString(&draw_info->primitive,
9159 argument_list[28].string_reference);
9160 if (attribute_flag[29] != 0)
9161 draw_info->kerning=argument_list[29].real_reference;
9162 if (attribute_flag[30] != 0)
9163 draw_info->interline_spacing=argument_list[30].real_reference;
9164 if (attribute_flag[31] != 0)
9165 draw_info->interword_spacing=argument_list[31].real_reference;
9166 if (attribute_flag[32] != 0)
9167 draw_info->direction=(DirectionType)
9168 argument_list[32].integer_reference;
Cristy36c30b62018-11-22 09:33:30 -05009169 (void) DrawImage(image,draw_info,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009170 draw_info=DestroyDrawInfo(draw_info);
9171 break;
9172 }
9173 case 39: /* Equalize */
9174 {
9175 if (attribute_flag[0] != 0)
9176 channel=(ChannelType) argument_list[0].integer_reference;
9177 channel_mask=SetImageChannelMask(image,channel);
Cristy36c30b62018-11-22 09:33:30 -05009178 (void) EqualizeImage(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009179 (void) SetImageChannelMask(image,channel_mask);
9180 break;
9181 }
9182 case 40: /* Gamma */
9183 {
9184 if (attribute_flag[1] != 0)
9185 channel=(ChannelType) argument_list[1].integer_reference;
9186 if (attribute_flag[2] == 0)
9187 argument_list[2].real_reference=1.0;
9188 if (attribute_flag[3] == 0)
9189 argument_list[3].real_reference=1.0;
9190 if (attribute_flag[4] == 0)
9191 argument_list[4].real_reference=1.0;
9192 if (attribute_flag[0] == 0)
9193 {
cristy151b66d2015-04-15 10:50:31 +00009194 (void) FormatLocaleString(message,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -05009195 "%.20g,%.20g,%.20g",(double) argument_list[2].real_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009196 (double) argument_list[3].real_reference,
9197 (double) argument_list[4].real_reference);
9198 argument_list[0].string_reference=message;
9199 }
9200 (void) GammaImage(image,StringToDouble(
9201 argument_list[0].string_reference,(char **) NULL),exception);
9202 break;
9203 }
9204 case 41: /* Map */
9205 {
9206 QuantizeInfo
9207 *quantize_info;
9208
9209 if (attribute_flag[0] == 0)
9210 {
9211 ThrowPerlException(exception,OptionError,"MapImageRequired",
9212 PackageName);
9213 goto PerlException;
9214 }
9215 quantize_info=AcquireQuantizeInfo(info->image_info);
9216 if (attribute_flag[1] != 0)
9217 quantize_info->dither_method=(DitherMethod)
9218 argument_list[1].integer_reference;
9219 (void) RemapImages(quantize_info,image,
9220 argument_list[0].image_reference,exception);
9221 quantize_info=DestroyQuantizeInfo(quantize_info);
9222 break;
9223 }
9224 case 42: /* MatteFloodfill */
9225 {
9226 DrawInfo
9227 *draw_info;
9228
9229 MagickBooleanType
9230 invert;
9231
9232 PixelInfo
9233 target;
9234
9235 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9236 (DrawInfo *) NULL);
9237 if (attribute_flag[0] != 0)
9238 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9239 &geometry,exception);
9240 if (attribute_flag[1] != 0)
9241 geometry.x=argument_list[1].integer_reference;
9242 if (attribute_flag[2] != 0)
9243 geometry.y=argument_list[2].integer_reference;
cristy17f11b02014-12-20 19:37:04 +00009244 if (image->alpha_trait == UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00009245 (void) SetImageAlpha(image,OpaqueAlpha,exception);
9246 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9247 geometry.x,geometry.y,&target,exception);
9248 if (attribute_flag[4] != 0)
9249 QueryColorCompliance(argument_list[4].string_reference,
9250 AllCompliance,&target,exception);
9251 if (attribute_flag[3] != 0)
9252 target.alpha=StringToDoubleInterval(
9253 argument_list[3].string_reference,(double) (double) QuantumRange+
9254 1.0);
9255 if (attribute_flag[5] != 0)
9256 image->fuzz=StringToDoubleInterval(
9257 argument_list[5].string_reference,(double) QuantumRange+1.0);
9258 invert=MagickFalse;
9259 if (attribute_flag[6] != 0)
9260 invert=(MagickBooleanType) argument_list[6].integer_reference;
9261 channel_mask=SetImageChannelMask(image,AlphaChannel);
9262 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9263 geometry.y,invert,exception);
9264 (void) SetImageChannelMask(image,channel_mask);
9265 draw_info=DestroyDrawInfo(draw_info);
9266 break;
9267 }
9268 case 43: /* Modulate */
9269 {
9270 char
cristy151b66d2015-04-15 10:50:31 +00009271 modulate[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00009272
9273 geometry_info.rho=100.0;
9274 geometry_info.sigma=100.0;
9275 geometry_info.xi=100.0;
9276 if (attribute_flag[0] != 0)
9277 (void)ParseGeometry(argument_list[0].string_reference,
9278 &geometry_info);
9279 if (attribute_flag[1] != 0)
9280 geometry_info.xi=argument_list[1].real_reference;
9281 if (attribute_flag[2] != 0)
9282 geometry_info.sigma=argument_list[2].real_reference;
9283 if (attribute_flag[3] != 0)
9284 {
9285 geometry_info.sigma=argument_list[3].real_reference;
9286 SetImageArtifact(image,"modulate:colorspace","HWB");
9287 }
9288 if (attribute_flag[4] != 0)
9289 {
9290 geometry_info.rho=argument_list[4].real_reference;
9291 SetImageArtifact(image,"modulate:colorspace","HSB");
9292 }
9293 if (attribute_flag[5] != 0)
9294 {
9295 geometry_info.sigma=argument_list[5].real_reference;
9296 SetImageArtifact(image,"modulate:colorspace","HSL");
9297 }
9298 if (attribute_flag[6] != 0)
9299 {
9300 geometry_info.rho=argument_list[6].real_reference;
9301 SetImageArtifact(image,"modulate:colorspace","HWB");
9302 }
Cristy935a4052017-03-31 17:45:37 -04009303 (void) FormatLocaleString(modulate,MagickPathExtent,"%.20g,%.20g,%.20g",
9304 geometry_info.rho,geometry_info.sigma,geometry_info.xi);
cristy4a3ce0a2013-08-03 20:06:59 +00009305 (void) ModulateImage(image,modulate,exception);
9306 break;
9307 }
9308 case 44: /* Negate */
9309 {
9310 if (attribute_flag[0] == 0)
9311 argument_list[0].integer_reference=0;
9312 if (attribute_flag[1] != 0)
9313 channel=(ChannelType) argument_list[1].integer_reference;
9314 channel_mask=SetImageChannelMask(image,channel);
9315 (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9316 MagickTrue : MagickFalse,exception);
9317 (void) SetImageChannelMask(image,channel_mask);
9318 break;
9319 }
9320 case 45: /* Normalize */
9321 {
9322 if (attribute_flag[0] != 0)
9323 channel=(ChannelType) argument_list[0].integer_reference;
9324 channel_mask=SetImageChannelMask(image,channel);
9325 NormalizeImage(image,exception);
9326 (void) SetImageChannelMask(image,channel_mask);
9327 break;
9328 }
9329 case 46: /* NumberColors */
9330 break;
9331 case 47: /* Opaque */
9332 {
9333 MagickBooleanType
9334 invert;
9335
9336 PixelInfo
9337 fill_color,
9338 target;
9339
9340 (void) QueryColorCompliance("none",AllCompliance,&target,
9341 exception);
9342 (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9343 exception);
9344 if (attribute_flag[0] != 0)
9345 (void) QueryColorCompliance(argument_list[0].string_reference,
9346 AllCompliance,&target,exception);
9347 if (attribute_flag[1] != 0)
9348 (void) QueryColorCompliance(argument_list[1].string_reference,
9349 AllCompliance,&fill_color,exception);
9350 if (attribute_flag[2] != 0)
9351 image->fuzz=StringToDoubleInterval(
9352 argument_list[2].string_reference,(double) QuantumRange+1.0);
9353 if (attribute_flag[3] != 0)
9354 channel=(ChannelType) argument_list[3].integer_reference;
9355 invert=MagickFalse;
9356 if (attribute_flag[4] != 0)
9357 invert=(MagickBooleanType) argument_list[4].integer_reference;
9358 channel_mask=SetImageChannelMask(image,channel);
9359 (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9360 (void) SetImageChannelMask(image,channel_mask);
9361 break;
9362 }
9363 case 48: /* Quantize */
9364 {
9365 QuantizeInfo
9366 *quantize_info;
9367
9368 quantize_info=AcquireQuantizeInfo(info->image_info);
9369 if (attribute_flag[0] != 0)
9370 quantize_info->number_colors=(size_t)
9371 argument_list[0].integer_reference;
9372 if (attribute_flag[1] != 0)
9373 quantize_info->tree_depth=(size_t)
9374 argument_list[1].integer_reference;
9375 if (attribute_flag[2] != 0)
9376 quantize_info->colorspace=(ColorspaceType)
9377 argument_list[2].integer_reference;
9378 if (attribute_flag[3] != 0)
cristy785c9342014-03-19 22:06:39 +00009379 quantize_info->dither_method=(DitherMethod)
9380 argument_list[3].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00009381 if (attribute_flag[4] != 0)
cristy71716d52014-03-19 10:11:11 +00009382 quantize_info->measure_error=
9383 argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
cristy4a3ce0a2013-08-03 20:06:59 +00009384 if (attribute_flag[6] != 0)
cristyd472dd82014-03-19 22:04:36 +00009385 (void) QueryColorCompliance(argument_list[6].string_reference,
cristyf7563392014-03-25 13:54:04 +00009386 AllCompliance,&image->transparent_color,exception);
cristy71716d52014-03-19 10:11:11 +00009387 if (attribute_flag[7] != 0)
cristy4a3ce0a2013-08-03 20:06:59 +00009388 quantize_info->dither_method=(DitherMethod)
cristy71716d52014-03-19 10:11:11 +00009389 argument_list[7].integer_reference;
9390 if (attribute_flag[5] && argument_list[5].integer_reference)
cristyf7563392014-03-25 13:54:04 +00009391 (void) QuantizeImages(quantize_info,image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009392 else
cristyf7563392014-03-25 13:54:04 +00009393 if ((image->storage_class == DirectClass) ||
9394 (image->colors > quantize_info->number_colors) ||
9395 (quantize_info->colorspace == GRAYColorspace))
9396 (void) QuantizeImage(quantize_info,image,exception);
9397 else
9398 CompressImageColormap(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009399 quantize_info=DestroyQuantizeInfo(quantize_info);
9400 break;
9401 }
9402 case 49: /* Raise */
9403 {
9404 if (attribute_flag[0] != 0)
9405 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9406 &geometry,exception);
9407 if (attribute_flag[1] != 0)
9408 geometry.width=argument_list[1].integer_reference;
9409 if (attribute_flag[2] != 0)
9410 geometry.height=argument_list[2].integer_reference;
9411 if (attribute_flag[3] == 0)
9412 argument_list[3].integer_reference=1;
9413 (void) RaiseImage(image,&geometry,
9414 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9415 exception);
9416 break;
9417 }
9418 case 50: /* Segment */
9419 {
9420 ColorspaceType
9421 colorspace;
9422
9423 double
9424 cluster_threshold,
9425 smoothing_threshold;
9426
9427 MagickBooleanType
9428 verbose;
9429
9430 cluster_threshold=1.0;
9431 smoothing_threshold=1.5;
9432 colorspace=sRGBColorspace;
9433 verbose=MagickFalse;
9434 if (attribute_flag[0] != 0)
9435 {
9436 flags=ParseGeometry(argument_list[0].string_reference,
9437 &geometry_info);
9438 cluster_threshold=geometry_info.rho;
9439 if (flags & SigmaValue)
9440 smoothing_threshold=geometry_info.sigma;
9441 }
9442 if (attribute_flag[1] != 0)
9443 cluster_threshold=argument_list[1].real_reference;
9444 if (attribute_flag[2] != 0)
9445 smoothing_threshold=argument_list[2].real_reference;
9446 if (attribute_flag[3] != 0)
9447 colorspace=(ColorspaceType) argument_list[3].integer_reference;
9448 if (attribute_flag[4] != 0)
9449 verbose=argument_list[4].integer_reference != 0 ?
9450 MagickTrue : MagickFalse;
9451 (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9452 smoothing_threshold,exception);
9453 break;
9454 }
9455 case 51: /* Signature */
9456 {
9457 (void) SignatureImage(image,exception);
9458 break;
9459 }
9460 case 52: /* Solarize */
9461 {
9462 geometry_info.rho=QuantumRange/2.0;
9463 if (attribute_flag[0] != 0)
9464 flags=ParseGeometry(argument_list[0].string_reference,
9465 &geometry_info);
9466 if (attribute_flag[1] != 0)
9467 geometry_info.rho=StringToDoubleInterval(
9468 argument_list[1].string_reference,(double) QuantumRange+1.0);
9469 (void) SolarizeImage(image,geometry_info.rho,exception);
9470 break;
9471 }
9472 case 53: /* Sync */
9473 {
9474 (void) SyncImage(image,exception);
9475 break;
9476 }
9477 case 54: /* Texture */
9478 {
9479 if (attribute_flag[0] == 0)
9480 break;
9481 TextureImage(image,argument_list[0].image_reference,exception);
9482 break;
9483 }
9484 case 55: /* Evalute */
9485 {
9486 MagickEvaluateOperator
9487 op;
9488
9489 op=SetEvaluateOperator;
9490 if (attribute_flag[0] == MagickFalse)
9491 argument_list[0].real_reference=0.0;
9492 if (attribute_flag[1] != MagickFalse)
9493 op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9494 if (attribute_flag[2] != MagickFalse)
9495 channel=(ChannelType) argument_list[2].integer_reference;
9496 channel_mask=SetImageChannelMask(image,channel);
9497 (void) EvaluateImage(image,op,argument_list[0].real_reference,
9498 exception);
9499 (void) SetImageChannelMask(image,channel_mask);
9500 break;
9501 }
9502 case 56: /* Transparent */
9503 {
9504 double
9505 opacity;
9506
9507 MagickBooleanType
9508 invert;
9509
9510 PixelInfo
9511 target;
9512
9513 (void) QueryColorCompliance("none",AllCompliance,&target,
9514 exception);
9515 if (attribute_flag[0] != 0)
9516 (void) QueryColorCompliance(argument_list[0].string_reference,
9517 AllCompliance,&target,exception);
9518 opacity=TransparentAlpha;
9519 if (attribute_flag[1] != 0)
9520 opacity=StringToDoubleInterval(argument_list[1].string_reference,
9521 (double) QuantumRange+1.0);
9522 if (attribute_flag[2] != 0)
9523 image->fuzz=StringToDoubleInterval(
9524 argument_list[2].string_reference,(double) QuantumRange+1.0);
9525 if (attribute_flag[3] == 0)
9526 argument_list[3].integer_reference=0;
9527 invert=MagickFalse;
9528 if (attribute_flag[3] != 0)
9529 invert=(MagickBooleanType) argument_list[3].integer_reference;
9530 (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9531 invert,exception);
9532 break;
9533 }
9534 case 57: /* Threshold */
9535 {
9536 double
9537 threshold;
9538
9539 if (attribute_flag[0] == 0)
9540 argument_list[0].string_reference="50%";
9541 if (attribute_flag[1] != 0)
9542 channel=(ChannelType) argument_list[1].integer_reference;
9543 threshold=StringToDoubleInterval(argument_list[0].string_reference,
9544 (double) QuantumRange+1.0);
9545 channel_mask=SetImageChannelMask(image,channel);
9546 (void) BilevelImage(image,threshold,exception);
9547 (void) SetImageChannelMask(image,channel_mask);
9548 break;
9549 }
9550 case 58: /* Charcoal */
9551 {
9552 if (attribute_flag[0] != 0)
9553 {
9554 flags=ParseGeometry(argument_list[0].string_reference,
9555 &geometry_info);
9556 if ((flags & SigmaValue) == 0)
9557 geometry_info.sigma=1.0;
9558 }
9559 if (attribute_flag[1] != 0)
9560 geometry_info.rho=argument_list[1].real_reference;
9561 if (attribute_flag[2] != 0)
9562 geometry_info.sigma=argument_list[2].real_reference;
9563 image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9564 exception);
9565 break;
9566 }
9567 case 59: /* Trim */
9568 {
9569 if (attribute_flag[0] != 0)
9570 image->fuzz=StringToDoubleInterval(
9571 argument_list[0].string_reference,(double) QuantumRange+1.0);
9572 image=TrimImage(image,exception);
9573 break;
9574 }
9575 case 60: /* Wave */
9576 {
9577 PixelInterpolateMethod
9578 method;
9579
9580 if (attribute_flag[0] != 0)
9581 {
9582 flags=ParseGeometry(argument_list[0].string_reference,
9583 &geometry_info);
9584 if ((flags & SigmaValue) == 0)
9585 geometry_info.sigma=1.0;
9586 }
9587 if (attribute_flag[1] != 0)
9588 geometry_info.rho=argument_list[1].real_reference;
9589 if (attribute_flag[2] != 0)
9590 geometry_info.sigma=argument_list[2].real_reference;
9591 method=UndefinedInterpolatePixel;
9592 if (attribute_flag[3] != 0)
9593 method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9594 image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9595 method,exception);
9596 break;
9597 }
9598 case 61: /* Separate */
9599 {
9600 if (attribute_flag[0] != 0)
9601 channel=(ChannelType) argument_list[0].integer_reference;
9602 image=SeparateImage(image,channel,exception);
9603 break;
9604 }
9605 case 63: /* Stereo */
9606 {
9607 if (attribute_flag[0] == 0)
9608 {
9609 ThrowPerlException(exception,OptionError,"StereoImageRequired",
9610 PackageName);
9611 goto PerlException;
9612 }
9613 if (attribute_flag[1] != 0)
9614 geometry.x=argument_list[1].integer_reference;
9615 if (attribute_flag[2] != 0)
9616 geometry.y=argument_list[2].integer_reference;
9617 image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9618 geometry.x,geometry.y,exception);
9619 break;
9620 }
9621 case 64: /* Stegano */
9622 {
9623 if (attribute_flag[0] == 0)
9624 {
9625 ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9626 PackageName);
9627 goto PerlException;
9628 }
9629 if (attribute_flag[1] == 0)
9630 argument_list[1].integer_reference=0;
9631 image->offset=argument_list[1].integer_reference;
9632 image=SteganoImage(image,argument_list[0].image_reference,exception);
9633 break;
9634 }
9635 case 65: /* Deconstruct */
9636 {
9637 image=CompareImagesLayers(image,CompareAnyLayer,exception);
9638 break;
9639 }
9640 case 66: /* GaussianBlur */
9641 {
9642 if (attribute_flag[0] != 0)
9643 {
9644 flags=ParseGeometry(argument_list[0].string_reference,
9645 &geometry_info);
9646 if ((flags & SigmaValue) == 0)
9647 geometry_info.sigma=1.0;
9648 }
9649 if (attribute_flag[1] != 0)
9650 geometry_info.rho=argument_list[1].real_reference;
9651 if (attribute_flag[2] != 0)
9652 geometry_info.sigma=argument_list[2].real_reference;
9653 if (attribute_flag[3] != 0)
9654 channel=(ChannelType) argument_list[3].integer_reference;
9655 channel_mask=SetImageChannelMask(image,channel);
9656 image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9657 exception);
9658 if (image != (Image *) NULL)
9659 (void) SetImageChannelMask(image,channel_mask);
9660 break;
9661 }
9662 case 67: /* Convolve */
9663 {
9664 KernelInfo
9665 *kernel;
9666
9667 kernel=(KernelInfo *) NULL;
9668 if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9669 break;
9670 if (attribute_flag[0] != 0)
9671 {
9672 AV
9673 *av;
9674
9675 size_t
9676 order;
9677
cristy2c57b742014-10-31 00:40:34 +00009678 kernel=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009679 if (kernel == (KernelInfo *) NULL)
9680 break;
9681 av=(AV *) argument_list[0].array_reference;
9682 order=(size_t) sqrt(av_len(av)+1);
9683 kernel->width=order;
9684 kernel->height=order;
9685 kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9686 order*sizeof(*kernel->values));
9687 if (kernel->values == (MagickRealType *) NULL)
9688 {
9689 kernel=DestroyKernelInfo(kernel);
9690 ThrowPerlException(exception,ResourceLimitFatalError,
9691 "MemoryAllocationFailed",PackageName);
9692 goto PerlException;
9693 }
9694 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9695 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9696 for ( ; j < (ssize_t) (order*order); j++)
9697 kernel->values[j]=0.0;
9698 }
9699 if (attribute_flag[1] != 0)
9700 channel=(ChannelType) argument_list[1].integer_reference;
9701 if (attribute_flag[2] != 0)
Cristyc4ff6bd2017-07-05 21:00:11 -04009702 SetImageArtifact(image,"convolve:bias",
cristy4a3ce0a2013-08-03 20:06:59 +00009703 argument_list[2].string_reference);
9704 if (attribute_flag[3] != 0)
9705 {
cristy2c57b742014-10-31 00:40:34 +00009706 kernel=AcquireKernelInfo(argument_list[3].string_reference,
9707 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009708 if (kernel == (KernelInfo *) NULL)
9709 break;
9710 }
9711 channel_mask=SetImageChannelMask(image,channel);
9712 image=ConvolveImage(image,kernel,exception);
9713 if (image != (Image *) NULL)
9714 (void) SetImageChannelMask(image,channel_mask);
9715 kernel=DestroyKernelInfo(kernel);
9716 break;
9717 }
9718 case 68: /* Profile */
9719 {
9720 const char
9721 *name;
9722
9723 Image
9724 *profile_image;
9725
9726 ImageInfo
9727 *profile_info;
9728
9729 StringInfo
9730 *profile;
9731
9732 name="*";
9733 if (attribute_flag[0] != 0)
9734 name=argument_list[0].string_reference;
9735 if (attribute_flag[2] != 0)
9736 image->rendering_intent=(RenderingIntent)
9737 argument_list[2].integer_reference;
9738 if (attribute_flag[3] != 0)
9739 image->black_point_compensation=
9740 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9741 if (attribute_flag[1] != 0)
9742 {
9743 if (argument_list[1].length == 0)
9744 {
9745 /*
9746 Remove a profile from the image.
9747 */
9748 (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9749 exception);
9750 break;
9751 }
9752 /*
9753 Associate user supplied profile with the image.
9754 */
9755 profile=AcquireStringInfo(argument_list[1].length);
9756 SetStringInfoDatum(profile,(const unsigned char *)
9757 argument_list[1].string_reference);
9758 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9759 (size_t) GetStringInfoLength(profile),exception);
9760 profile=DestroyStringInfo(profile);
9761 break;
9762 }
9763 /*
9764 Associate a profile with the image.
9765 */
9766 profile_info=CloneImageInfo(info ? info->image_info :
9767 (ImageInfo *) NULL);
9768 profile_image=ReadImages(profile_info,name,exception);
9769 if (profile_image == (Image *) NULL)
9770 break;
9771 ResetImageProfileIterator(profile_image);
9772 name=GetNextImageProfile(profile_image);
9773 while (name != (const char *) NULL)
9774 {
9775 const StringInfo
9776 *profile;
9777
9778 profile=GetImageProfile(profile_image,name);
9779 if (profile != (const StringInfo *) NULL)
9780 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9781 (size_t) GetStringInfoLength(profile),exception);
9782 name=GetNextImageProfile(profile_image);
9783 }
9784 profile_image=DestroyImage(profile_image);
9785 profile_info=DestroyImageInfo(profile_info);
9786 break;
9787 }
9788 case 69: /* UnsharpMask */
9789 {
9790 if (attribute_flag[0] != 0)
9791 {
9792 flags=ParseGeometry(argument_list[0].string_reference,
9793 &geometry_info);
9794 if ((flags & SigmaValue) == 0)
9795 geometry_info.sigma=1.0;
9796 if ((flags & XiValue) == 0)
9797 geometry_info.xi=1.0;
9798 if ((flags & PsiValue) == 0)
9799 geometry_info.psi=0.5;
9800 }
9801 if (attribute_flag[1] != 0)
9802 geometry_info.rho=argument_list[1].real_reference;
9803 if (attribute_flag[2] != 0)
9804 geometry_info.sigma=argument_list[2].real_reference;
9805 if (attribute_flag[3] != 0)
9806 geometry_info.xi=argument_list[3].real_reference;
9807 if (attribute_flag[4] != 0)
9808 geometry_info.psi=argument_list[4].real_reference;
9809 if (attribute_flag[5] != 0)
9810 channel=(ChannelType) argument_list[5].integer_reference;
9811 channel_mask=SetImageChannelMask(image,channel);
9812 image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9813 geometry_info.xi,geometry_info.psi,exception);
9814 if (image != (Image *) NULL)
9815 (void) SetImageChannelMask(image,channel_mask);
9816 break;
9817 }
9818 case 70: /* MotionBlur */
9819 {
9820 if (attribute_flag[0] != 0)
9821 {
9822 flags=ParseGeometry(argument_list[0].string_reference,
9823 &geometry_info);
9824 if ((flags & SigmaValue) == 0)
9825 geometry_info.sigma=1.0;
9826 if ((flags & XiValue) == 0)
9827 geometry_info.xi=1.0;
9828 }
9829 if (attribute_flag[1] != 0)
9830 geometry_info.rho=argument_list[1].real_reference;
9831 if (attribute_flag[2] != 0)
9832 geometry_info.sigma=argument_list[2].real_reference;
9833 if (attribute_flag[3] != 0)
9834 geometry_info.xi=argument_list[3].real_reference;
9835 if (attribute_flag[4] != 0)
9836 channel=(ChannelType) argument_list[4].integer_reference;
9837 channel_mask=SetImageChannelMask(image,channel);
9838 image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9839 geometry_info.xi,exception);
9840 if (image != (Image *) NULL)
9841 (void) SetImageChannelMask(image,channel_mask);
9842 break;
9843 }
9844 case 71: /* OrderedDither */
9845 {
9846 if (attribute_flag[0] == 0)
9847 argument_list[0].string_reference="o8x8";
9848 if (attribute_flag[1] != 0)
9849 channel=(ChannelType) argument_list[1].integer_reference;
9850 channel_mask=SetImageChannelMask(image,channel);
Cristy6b93c072016-02-04 07:45:48 -05009851 (void) OrderedDitherImage(image,argument_list[0].string_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009852 exception);
9853 (void) SetImageChannelMask(image,channel_mask);
9854 break;
9855 }
9856 case 72: /* Shave */
9857 {
9858 if (attribute_flag[0] != 0)
9859 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9860 &geometry,exception);
9861 if (attribute_flag[1] != 0)
9862 geometry.width=argument_list[1].integer_reference;
9863 if (attribute_flag[2] != 0)
9864 geometry.height=argument_list[2].integer_reference;
9865 image=ShaveImage(image,&geometry,exception);
9866 break;
9867 }
9868 case 73: /* Level */
9869 {
9870 double
9871 black_point,
9872 gamma,
9873 white_point;
9874
9875 black_point=0.0;
9876 white_point=(double) image->columns*image->rows;
9877 gamma=1.0;
9878 if (attribute_flag[0] != 0)
9879 {
9880 flags=ParseGeometry(argument_list[0].string_reference,
9881 &geometry_info);
9882 black_point=geometry_info.rho;
9883 if ((flags & SigmaValue) != 0)
9884 white_point=geometry_info.sigma;
9885 if ((flags & XiValue) != 0)
9886 gamma=geometry_info.xi;
9887 if ((flags & PercentValue) != 0)
9888 {
9889 black_point*=(double) (QuantumRange/100.0);
9890 white_point*=(double) (QuantumRange/100.0);
9891 }
9892 if ((flags & SigmaValue) == 0)
9893 white_point=(double) QuantumRange-black_point;
9894 }
9895 if (attribute_flag[1] != 0)
9896 black_point=argument_list[1].real_reference;
9897 if (attribute_flag[2] != 0)
9898 white_point=argument_list[2].real_reference;
9899 if (attribute_flag[3] != 0)
9900 gamma=argument_list[3].real_reference;
9901 if (attribute_flag[4] != 0)
9902 channel=(ChannelType) argument_list[4].integer_reference;
9903 if (attribute_flag[5] != 0)
9904 {
9905 argument_list[0].real_reference=argument_list[5].real_reference;
9906 attribute_flag[0]=attribute_flag[5];
9907 }
9908 channel_mask=SetImageChannelMask(image,channel);
9909 (void) LevelImage(image,black_point,white_point,gamma,exception);
9910 (void) SetImageChannelMask(image,channel_mask);
9911 break;
9912 }
9913 case 74: /* Clip */
9914 {
9915 if (attribute_flag[0] == 0)
9916 argument_list[0].string_reference="#1";
9917 if (attribute_flag[1] == 0)
9918 argument_list[1].integer_reference=MagickTrue;
9919 (void) ClipImagePath(image,argument_list[0].string_reference,
9920 argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9921 exception);
9922 break;
9923 }
9924 case 75: /* AffineTransform */
9925 {
9926 DrawInfo
9927 *draw_info;
9928
9929 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9930 (DrawInfo *) NULL);
9931 if (attribute_flag[0] != 0)
9932 {
9933 AV
9934 *av;
9935
9936 av=(AV *) argument_list[0].array_reference;
9937 if ((av_len(av) != 3) && (av_len(av) != 5))
9938 {
9939 ThrowPerlException(exception,OptionError,
9940 "affine matrix must have 4 or 6 elements",PackageName);
9941 goto PerlException;
9942 }
9943 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9944 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9945 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9946 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9947 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9948 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9949 {
9950 ThrowPerlException(exception,OptionError,
9951 "affine matrix is singular",PackageName);
9952 goto PerlException;
9953 }
9954 if (av_len(av) == 5)
9955 {
9956 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9957 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9958 }
9959 }
9960 for (j=1; j < 6; j++)
9961 {
9962 if (attribute_flag[j] == 0)
9963 continue;
9964 value=argument_list[j].string_reference;
9965 angle=argument_list[j].real_reference;
9966 current=draw_info->affine;
9967 GetAffineMatrix(&affine);
9968 switch (j)
9969 {
9970 case 1:
9971 {
9972 /*
9973 Translate.
9974 */
9975 flags=ParseGeometry(value,&geometry_info);
9976 affine.tx=geometry_info.xi;
9977 affine.ty=geometry_info.psi;
9978 if ((flags & PsiValue) == 0)
9979 affine.ty=affine.tx;
9980 break;
9981 }
9982 case 2:
9983 {
9984 /*
9985 Scale.
9986 */
9987 flags=ParseGeometry(value,&geometry_info);
9988 affine.sx=geometry_info.rho;
9989 affine.sy=geometry_info.sigma;
9990 if ((flags & SigmaValue) == 0)
9991 affine.sy=affine.sx;
9992 break;
9993 }
9994 case 3:
9995 {
9996 /*
9997 Rotate.
9998 */
9999 if (angle == 0.0)
10000 break;
10001 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
10002 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
10003 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
10004 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
10005 break;
10006 }
10007 case 4:
10008 {
10009 /*
10010 SkewX.
10011 */
10012 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
10013 break;
10014 }
10015 case 5:
10016 {
10017 /*
10018 SkewY.
10019 */
10020 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
10021 break;
10022 }
10023 }
10024 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
10025 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
10026 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
10027 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
10028 draw_info->affine.tx=
10029 current.sx*affine.tx+current.ry*affine.ty+current.tx;
10030 draw_info->affine.ty=
10031 current.rx*affine.tx+current.sy*affine.ty+current.ty;
10032 }
10033 if (attribute_flag[6] != 0)
10034 image->interpolate=(PixelInterpolateMethod)
10035 argument_list[6].integer_reference;
10036 if (attribute_flag[7] != 0)
10037 QueryColorCompliance(argument_list[7].string_reference,
10038 AllCompliance,&image->background_color,exception);
10039 image=AffineTransformImage(image,&draw_info->affine,exception);
10040 draw_info=DestroyDrawInfo(draw_info);
10041 break;
10042 }
10043 case 76: /* Difference */
10044 {
10045 if (attribute_flag[0] == 0)
10046 {
10047 ThrowPerlException(exception,OptionError,
10048 "ReferenceImageRequired",PackageName);
10049 goto PerlException;
10050 }
10051 if (attribute_flag[1] != 0)
10052 image->fuzz=StringToDoubleInterval(
10053 argument_list[1].string_reference,(double) QuantumRange+1.0);
Cristyf2479812015-12-12 12:17:43 -050010054 (void) SetImageColorMetric(image,argument_list[0].image_reference,
cristy4a3ce0a2013-08-03 20:06:59 +000010055 exception);
10056 break;
10057 }
10058 case 77: /* AdaptiveThreshold */
10059 {
10060 if (attribute_flag[0] != 0)
10061 {
10062 flags=ParseGeometry(argument_list[0].string_reference,
10063 &geometry_info);
10064 if ((flags & PercentValue) != 0)
10065 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10066 }
10067 if (attribute_flag[1] != 0)
10068 geometry_info.rho=argument_list[1].integer_reference;
10069 if (attribute_flag[2] != 0)
10070 geometry_info.sigma=argument_list[2].integer_reference;
10071 if (attribute_flag[3] != 0)
10072 geometry_info.xi=argument_list[3].integer_reference;;
10073 image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
10074 (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
10075 break;
10076 }
10077 case 78: /* Resample */
10078 {
10079 size_t
10080 height,
10081 width;
10082
10083 if (attribute_flag[0] != 0)
10084 {
10085 flags=ParseGeometry(argument_list[0].string_reference,
10086 &geometry_info);
10087 if ((flags & SigmaValue) == 0)
10088 geometry_info.sigma=geometry_info.rho;
10089 }
10090 if (attribute_flag[1] != 0)
10091 geometry_info.rho=argument_list[1].real_reference;
10092 if (attribute_flag[2] != 0)
10093 geometry_info.sigma=argument_list[2].real_reference;
10094 if (attribute_flag[3] == 0)
10095 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10096 if (attribute_flag[4] == 0)
10097 SetImageArtifact(image,"filter:support",
10098 argument_list[4].string_reference);
10099 width=(size_t) (geometry_info.rho*image->columns/
10100 (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10101 height=(size_t) (geometry_info.sigma*image->rows/
10102 (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
Cristy8645e042016-02-03 16:35:29 -050010103 image=ResizeImage(image,width,height,(FilterType)
cristy4a3ce0a2013-08-03 20:06:59 +000010104 argument_list[3].integer_reference,exception);
10105 if (image != (Image *) NULL)
10106 {
10107 image->resolution.x=geometry_info.rho;
10108 image->resolution.y=geometry_info.sigma;
10109 }
10110 break;
10111 }
10112 case 79: /* Describe */
10113 {
10114 if (attribute_flag[0] == 0)
10115 argument_list[0].file_reference=(FILE *) NULL;
cristy4a3ce0a2013-08-03 20:06:59 +000010116 (void) IdentifyImage(image,argument_list[0].file_reference,
10117 MagickTrue,exception);
10118 break;
10119 }
10120 case 80: /* BlackThreshold */
10121 {
10122 if (attribute_flag[0] == 0)
10123 argument_list[0].string_reference="50%";
10124 if (attribute_flag[2] != 0)
10125 channel=(ChannelType) argument_list[2].integer_reference;
10126 channel_mask=SetImageChannelMask(image,channel);
10127 BlackThresholdImage(image,argument_list[0].string_reference,
10128 exception);
10129 (void) SetImageChannelMask(image,channel_mask);
10130 break;
10131 }
10132 case 81: /* WhiteThreshold */
10133 {
10134 if (attribute_flag[0] == 0)
10135 argument_list[0].string_reference="50%";
10136 if (attribute_flag[2] != 0)
10137 channel=(ChannelType) argument_list[2].integer_reference;
10138 channel_mask=SetImageChannelMask(image,channel);
10139 WhiteThresholdImage(image,argument_list[0].string_reference,
10140 exception);
10141 (void) SetImageChannelMask(image,channel_mask);
10142 break;
10143 }
cristy60c73c02014-03-25 12:09:58 +000010144 case 82: /* RotationalBlur */
cristy4a3ce0a2013-08-03 20:06:59 +000010145 {
10146 if (attribute_flag[0] != 0)
10147 {
10148 flags=ParseGeometry(argument_list[0].string_reference,
10149 &geometry_info);
10150 }
10151 if (attribute_flag[1] != 0)
10152 geometry_info.rho=argument_list[1].real_reference;
10153 if (attribute_flag[2] != 0)
10154 channel=(ChannelType) argument_list[2].integer_reference;
10155 channel_mask=SetImageChannelMask(image,channel);
cristy49d4d222014-03-16 00:37:58 +000010156 image=RotationalBlurImage(image,geometry_info.rho,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010157 if (image != (Image *) NULL)
10158 (void) SetImageChannelMask(image,channel_mask);
10159 break;
10160 }
10161 case 83: /* Thumbnail */
10162 {
10163 if (attribute_flag[0] != 0)
10164 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10165 &geometry,exception);
10166 if (attribute_flag[1] != 0)
10167 geometry.width=argument_list[1].integer_reference;
10168 if (attribute_flag[2] != 0)
10169 geometry.height=argument_list[2].integer_reference;
10170 image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10171 break;
10172 }
10173 case 84: /* Strip */
10174 {
10175 (void) StripImage(image,exception);
10176 break;
10177 }
10178 case 85: /* Tint */
10179 {
10180 PixelInfo
10181 tint;
10182
10183 GetPixelInfo(image,&tint);
10184 if (attribute_flag[0] != 0)
10185 (void) QueryColorCompliance(argument_list[0].string_reference,
10186 AllCompliance,&tint,exception);
10187 if (attribute_flag[1] == 0)
10188 argument_list[1].string_reference="100";
10189 image=TintImage(image,argument_list[1].string_reference,&tint,
10190 exception);
10191 break;
10192 }
10193 case 86: /* Channel */
10194 {
10195 if (attribute_flag[0] != 0)
10196 channel=(ChannelType) argument_list[0].integer_reference;
10197 image=SeparateImage(image,channel,exception);
10198 break;
10199 }
10200 case 87: /* Splice */
10201 {
cristy260bd762014-08-15 12:46:34 +000010202 if (attribute_flag[7] != 0)
10203 image->gravity=(GravityType) argument_list[7].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010204 if (attribute_flag[0] != 0)
10205 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10206 &geometry,exception);
10207 if (attribute_flag[1] != 0)
10208 geometry.width=argument_list[1].integer_reference;
10209 if (attribute_flag[2] != 0)
10210 geometry.height=argument_list[2].integer_reference;
10211 if (attribute_flag[3] != 0)
10212 geometry.x=argument_list[3].integer_reference;
10213 if (attribute_flag[4] != 0)
10214 geometry.y=argument_list[4].integer_reference;
10215 if (attribute_flag[5] != 0)
10216 image->fuzz=StringToDoubleInterval(
10217 argument_list[5].string_reference,(double) QuantumRange+1.0);
10218 if (attribute_flag[6] != 0)
10219 (void) QueryColorCompliance(argument_list[6].string_reference,
10220 AllCompliance,&image->background_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010221 image=SpliceImage(image,&geometry,exception);
10222 break;
10223 }
10224 case 88: /* Posterize */
10225 {
10226 if (attribute_flag[0] == 0)
10227 argument_list[0].integer_reference=3;
10228 if (attribute_flag[1] == 0)
10229 argument_list[1].integer_reference=0;
10230 (void) PosterizeImage(image,argument_list[0].integer_reference,
10231 argument_list[1].integer_reference ? RiemersmaDitherMethod :
10232 NoDitherMethod,exception);
10233 break;
10234 }
10235 case 89: /* Shadow */
10236 {
10237 if (attribute_flag[0] != 0)
10238 {
10239 flags=ParseGeometry(argument_list[0].string_reference,
10240 &geometry_info);
10241 if ((flags & SigmaValue) == 0)
10242 geometry_info.sigma=1.0;
10243 if ((flags & XiValue) == 0)
10244 geometry_info.xi=4.0;
10245 if ((flags & PsiValue) == 0)
10246 geometry_info.psi=4.0;
10247 }
10248 if (attribute_flag[1] != 0)
10249 geometry_info.rho=argument_list[1].real_reference;
10250 if (attribute_flag[2] != 0)
10251 geometry_info.sigma=argument_list[2].real_reference;
10252 if (attribute_flag[3] != 0)
10253 geometry_info.xi=argument_list[3].integer_reference;
10254 if (attribute_flag[4] != 0)
10255 geometry_info.psi=argument_list[4].integer_reference;
10256 image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10257 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10258 ceil(geometry_info.psi-0.5),exception);
10259 break;
10260 }
10261 case 90: /* Identify */
10262 {
10263 if (attribute_flag[0] == 0)
10264 argument_list[0].file_reference=(FILE *) NULL;
10265 if (attribute_flag[1] != 0)
10266 (void) SetImageArtifact(image,"identify:features",
10267 argument_list[1].string_reference);
10268 if ((attribute_flag[2] != 0) &&
10269 (argument_list[2].integer_reference != 0))
Cristy8b3ffe62020-02-17 12:36:53 -050010270 (void) SetImageArtifact(image,"identify:moments","true");
10271 if ((attribute_flag[3] != 0) &&
10272 (argument_list[3].integer_reference != 0))
cristy4a3ce0a2013-08-03 20:06:59 +000010273 (void) SetImageArtifact(image,"identify:unique","true");
10274 (void) IdentifyImage(image,argument_list[0].file_reference,
10275 MagickTrue,exception);
10276 break;
10277 }
10278 case 91: /* SepiaTone */
10279 {
10280 if (attribute_flag[0] == 0)
10281 argument_list[0].real_reference=80.0*QuantumRange/100.0;
10282 image=SepiaToneImage(image,argument_list[0].real_reference,
10283 exception);
10284 break;
10285 }
10286 case 92: /* SigmoidalContrast */
10287 {
10288 MagickBooleanType
10289 sharpen;
10290
10291 if (attribute_flag[0] != 0)
10292 {
10293 flags=ParseGeometry(argument_list[0].string_reference,
10294 &geometry_info);
10295 if ((flags & SigmaValue) == 0)
10296 geometry_info.sigma=QuantumRange/2.0;
10297 if ((flags & PercentValue) != 0)
10298 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10299 }
10300 if (attribute_flag[1] != 0)
10301 geometry_info.rho=argument_list[1].real_reference;
10302 if (attribute_flag[2] != 0)
10303 geometry_info.sigma=argument_list[2].real_reference;
10304 if (attribute_flag[3] != 0)
10305 channel=(ChannelType) argument_list[3].integer_reference;
10306 sharpen=MagickTrue;
10307 if (attribute_flag[4] != 0)
10308 sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10309 MagickFalse;
10310 channel_mask=SetImageChannelMask(image,channel);
10311 (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10312 geometry_info.sigma,exception);
10313 (void) SetImageChannelMask(image,channel_mask);
10314 break;
10315 }
10316 case 93: /* Extent */
10317 {
10318 if (attribute_flag[7] != 0)
10319 image->gravity=(GravityType) argument_list[7].integer_reference;
10320 if (attribute_flag[0] != 0)
10321 {
10322 int
10323 flags;
10324
10325 flags=ParseGravityGeometry(image,
10326 argument_list[0].string_reference,&geometry,exception);
10327 (void) flags;
10328 if (geometry.width == 0)
10329 geometry.width=image->columns;
10330 if (geometry.height == 0)
10331 geometry.height=image->rows;
10332 }
10333 if (attribute_flag[1] != 0)
10334 geometry.width=argument_list[1].integer_reference;
10335 if (attribute_flag[2] != 0)
10336 geometry.height=argument_list[2].integer_reference;
10337 if (attribute_flag[3] != 0)
10338 geometry.x=argument_list[3].integer_reference;
10339 if (attribute_flag[4] != 0)
10340 geometry.y=argument_list[4].integer_reference;
10341 if (attribute_flag[5] != 0)
10342 image->fuzz=StringToDoubleInterval(
10343 argument_list[5].string_reference,(double) QuantumRange+1.0);
10344 if (attribute_flag[6] != 0)
10345 (void) QueryColorCompliance(argument_list[6].string_reference,
10346 AllCompliance,&image->background_color,exception);
10347 image=ExtentImage(image,&geometry,exception);
10348 break;
10349 }
10350 case 94: /* Vignette */
10351 {
10352 if (attribute_flag[0] != 0)
10353 {
10354 flags=ParseGeometry(argument_list[0].string_reference,
10355 &geometry_info);
10356 if ((flags & SigmaValue) == 0)
10357 geometry_info.sigma=1.0;
10358 if ((flags & XiValue) == 0)
10359 geometry_info.xi=0.1*image->columns;
10360 if ((flags & PsiValue) == 0)
10361 geometry_info.psi=0.1*image->rows;
10362 }
10363 if (attribute_flag[1] != 0)
10364 geometry_info.rho=argument_list[1].real_reference;
10365 if (attribute_flag[2] != 0)
10366 geometry_info.sigma=argument_list[2].real_reference;
10367 if (attribute_flag[3] != 0)
10368 geometry_info.xi=argument_list[3].integer_reference;
10369 if (attribute_flag[4] != 0)
10370 geometry_info.psi=argument_list[4].integer_reference;
10371 if (attribute_flag[5] != 0)
10372 (void) QueryColorCompliance(argument_list[5].string_reference,
10373 AllCompliance,&image->background_color,exception);
10374 image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10375 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10376 ceil(geometry_info.psi-0.5),exception);
10377 break;
10378 }
10379 case 95: /* ContrastStretch */
10380 {
10381 double
10382 black_point,
10383 white_point;
10384
10385 black_point=0.0;
10386 white_point=(double) image->columns*image->rows;
10387 if (attribute_flag[0] != 0)
10388 {
10389 flags=ParseGeometry(argument_list[0].string_reference,
10390 &geometry_info);
10391 black_point=geometry_info.rho;
10392 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10393 black_point;
10394 if ((flags & PercentValue) != 0)
10395 {
10396 black_point*=(double) image->columns*image->rows/100.0;
10397 white_point*=(double) image->columns*image->rows/100.0;
10398 }
10399 white_point=(double) image->columns*image->rows-
10400 white_point;
10401 }
10402 if (attribute_flag[1] != 0)
10403 black_point=argument_list[1].real_reference;
10404 if (attribute_flag[2] != 0)
10405 white_point=argument_list[2].real_reference;
10406 if (attribute_flag[4] != 0)
10407 channel=(ChannelType) argument_list[4].integer_reference;
10408 channel_mask=SetImageChannelMask(image,channel);
10409 (void) ContrastStretchImage(image,black_point,white_point,exception);
10410 (void) SetImageChannelMask(image,channel_mask);
10411 break;
10412 }
10413 case 96: /* Sans0 */
10414 {
10415 break;
10416 }
10417 case 97: /* Sans1 */
10418 {
10419 break;
10420 }
10421 case 98: /* AdaptiveSharpen */
10422 {
10423 if (attribute_flag[0] != 0)
10424 {
10425 flags=ParseGeometry(argument_list[0].string_reference,
10426 &geometry_info);
10427 if ((flags & SigmaValue) == 0)
10428 geometry_info.sigma=1.0;
10429 if ((flags & XiValue) == 0)
10430 geometry_info.xi=0.0;
10431 }
10432 if (attribute_flag[1] != 0)
10433 geometry_info.rho=argument_list[1].real_reference;
10434 if (attribute_flag[2] != 0)
10435 geometry_info.sigma=argument_list[2].real_reference;
10436 if (attribute_flag[3] != 0)
10437 geometry_info.xi=argument_list[3].real_reference;
10438 if (attribute_flag[4] != 0)
10439 channel=(ChannelType) argument_list[4].integer_reference;
10440 channel_mask=SetImageChannelMask(image,channel);
10441 image=AdaptiveSharpenImage(image,geometry_info.rho,
10442 geometry_info.sigma,exception);
10443 if (image != (Image *) NULL)
10444 (void) SetImageChannelMask(image,channel_mask);
10445 break;
10446 }
10447 case 99: /* Transpose */
10448 {
10449 image=TransposeImage(image,exception);
10450 break;
10451 }
10452 case 100: /* Tranverse */
10453 {
10454 image=TransverseImage(image,exception);
10455 break;
10456 }
10457 case 101: /* AutoOrient */
10458 {
10459 image=AutoOrientImage(image,image->orientation,exception);
10460 break;
10461 }
10462 case 102: /* AdaptiveBlur */
10463 {
10464 if (attribute_flag[0] != 0)
10465 {
10466 flags=ParseGeometry(argument_list[0].string_reference,
10467 &geometry_info);
10468 if ((flags & SigmaValue) == 0)
10469 geometry_info.sigma=1.0;
10470 if ((flags & XiValue) == 0)
10471 geometry_info.xi=0.0;
10472 }
10473 if (attribute_flag[1] != 0)
10474 geometry_info.rho=argument_list[1].real_reference;
10475 if (attribute_flag[2] != 0)
10476 geometry_info.sigma=argument_list[2].real_reference;
10477 if (attribute_flag[3] != 0)
10478 channel=(ChannelType) argument_list[3].integer_reference;
10479 channel_mask=SetImageChannelMask(image,channel);
10480 image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10481 exception);
10482 if (image != (Image *) NULL)
10483 (void) SetImageChannelMask(image,channel_mask);
10484 break;
10485 }
10486 case 103: /* Sketch */
10487 {
10488 if (attribute_flag[0] != 0)
10489 {
10490 flags=ParseGeometry(argument_list[0].string_reference,
10491 &geometry_info);
10492 if ((flags & SigmaValue) == 0)
10493 geometry_info.sigma=1.0;
10494 if ((flags & XiValue) == 0)
10495 geometry_info.xi=1.0;
10496 }
10497 if (attribute_flag[1] != 0)
10498 geometry_info.rho=argument_list[1].real_reference;
10499 if (attribute_flag[2] != 0)
10500 geometry_info.sigma=argument_list[2].real_reference;
10501 if (attribute_flag[3] != 0)
10502 geometry_info.xi=argument_list[3].real_reference;
10503 image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10504 geometry_info.xi,exception);
10505 break;
10506 }
10507 case 104: /* UniqueColors */
10508 {
10509 image=UniqueImageColors(image,exception);
10510 break;
10511 }
10512 case 105: /* AdaptiveResize */
10513 {
10514 if (attribute_flag[0] != 0)
10515 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10516 &geometry,exception);
10517 if (attribute_flag[1] != 0)
10518 geometry.width=argument_list[1].integer_reference;
10519 if (attribute_flag[2] != 0)
10520 geometry.height=argument_list[2].integer_reference;
10521 if (attribute_flag[3] != 0)
Cristy8645e042016-02-03 16:35:29 -050010522 image->filter=(FilterType) argument_list[4].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010523 if (attribute_flag[4] != 0)
10524 SetImageArtifact(image,"filter:support",
10525 argument_list[4].string_reference);
10526 image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10527 exception);
10528 break;
10529 }
10530 case 106: /* ClipMask */
10531 {
10532 Image
10533 *mask_image;
10534
10535 if (attribute_flag[0] == 0)
10536 {
10537 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10538 PackageName);
10539 goto PerlException;
10540 }
10541 mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10542 exception);
cristy1f7ffb72015-07-29 11:07:03 +000010543 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010544 mask_image=DestroyImage(mask_image);
10545 break;
10546 }
10547 case 107: /* LinearStretch */
10548 {
10549 double
10550 black_point,
10551 white_point;
10552
10553 black_point=0.0;
10554 white_point=(double) image->columns*image->rows;
10555 if (attribute_flag[0] != 0)
10556 {
10557 flags=ParseGeometry(argument_list[0].string_reference,
10558 &geometry_info);
10559 if ((flags & SigmaValue) != 0)
10560 white_point=geometry_info.sigma;
10561 if ((flags & PercentValue) != 0)
10562 {
10563 black_point*=(double) image->columns*image->rows/100.0;
10564 white_point*=(double) image->columns*image->rows/100.0;
10565 }
10566 if ((flags & SigmaValue) == 0)
10567 white_point=(double) image->columns*image->rows-black_point;
10568 }
10569 if (attribute_flag[1] != 0)
10570 black_point=argument_list[1].real_reference;
10571 if (attribute_flag[2] != 0)
10572 white_point=argument_list[2].real_reference;
10573 (void) LinearStretchImage(image,black_point,white_point,exception);
10574 break;
10575 }
10576 case 108: /* ColorMatrix */
10577 {
10578 AV
10579 *av;
10580
10581 double
10582 *color_matrix;
10583
10584 KernelInfo
10585 *kernel_info;
10586
10587 size_t
10588 order;
10589
10590 if (attribute_flag[0] == 0)
10591 break;
10592 av=(AV *) argument_list[0].array_reference;
10593 order=(size_t) sqrt(av_len(av)+1);
10594 color_matrix=(double *) AcquireQuantumMemory(order,order*
10595 sizeof(*color_matrix));
10596 if (color_matrix == (double *) NULL)
10597 {
10598 ThrowPerlException(exception,ResourceLimitFatalError,
10599 "MemoryAllocationFailed",PackageName);
10600 goto PerlException;
10601 }
10602 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10603 color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10604 for ( ; j < (ssize_t) (order*order); j++)
10605 color_matrix[j]=0.0;
cristy2c57b742014-10-31 00:40:34 +000010606 kernel_info=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010607 if (kernel_info == (KernelInfo *) NULL)
10608 break;
10609 kernel_info->width=order;
10610 kernel_info->height=order;
10611 kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10612 order*sizeof(*kernel_info->values));
10613 if (kernel_info->values != (MagickRealType *) NULL)
10614 {
10615 for (i=0; i < (ssize_t) (order*order); i++)
10616 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10617 image=ColorMatrixImage(image,kernel_info,exception);
10618 }
10619 kernel_info=DestroyKernelInfo(kernel_info);
10620 color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10621 break;
10622 }
10623 case 109: /* Mask */
10624 {
10625 Image
10626 *mask_image;
10627
10628 if (attribute_flag[0] == 0)
10629 {
10630 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10631 PackageName);
10632 goto PerlException;
10633 }
10634 mask_image=CloneImage(argument_list[0].image_reference,0,0,
10635 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +000010636 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010637 mask_image=DestroyImage(mask_image);
10638 break;
10639 }
10640 case 110: /* Polaroid */
10641 {
10642 char
10643 *caption;
10644
10645 DrawInfo
10646 *draw_info;
10647
10648 double
10649 angle;
10650
10651 PixelInterpolateMethod
10652 method;
10653
10654 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10655 (DrawInfo *) NULL);
10656 caption=(char *) NULL;
10657 if (attribute_flag[0] != 0)
10658 caption=InterpretImageProperties(info ? info->image_info :
10659 (ImageInfo *) NULL,image,argument_list[0].string_reference,
10660 exception);
10661 angle=0.0;
10662 if (attribute_flag[1] != 0)
10663 angle=argument_list[1].real_reference;
10664 if (attribute_flag[2] != 0)
10665 (void) CloneString(&draw_info->font,
10666 argument_list[2].string_reference);
10667 if (attribute_flag[3] != 0)
10668 (void) QueryColorCompliance(argument_list[3].string_reference,
10669 AllCompliance,&draw_info->stroke,exception);
10670 if (attribute_flag[4] != 0)
10671 (void) QueryColorCompliance(argument_list[4].string_reference,
10672 AllCompliance,&draw_info->fill,exception);
10673 if (attribute_flag[5] != 0)
10674 draw_info->stroke_width=argument_list[5].real_reference;
10675 if (attribute_flag[6] != 0)
10676 draw_info->pointsize=argument_list[6].real_reference;
10677 if (attribute_flag[7] != 0)
10678 draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10679 if (attribute_flag[8] != 0)
10680 (void) QueryColorCompliance(argument_list[8].string_reference,
10681 AllCompliance,&image->background_color,exception);
10682 method=UndefinedInterpolatePixel;
10683 if (attribute_flag[9] != 0)
10684 method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10685 image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10686 draw_info=DestroyDrawInfo(draw_info);
10687 if (caption != (char *) NULL)
10688 caption=DestroyString(caption);
10689 break;
10690 }
10691 case 111: /* FloodfillPaint */
10692 {
10693 DrawInfo
10694 *draw_info;
10695
10696 MagickBooleanType
10697 invert;
10698
10699 PixelInfo
10700 target;
10701
10702 draw_info=CloneDrawInfo(info ? info->image_info :
10703 (ImageInfo *) NULL,(DrawInfo *) NULL);
10704 if (attribute_flag[0] != 0)
10705 flags=ParsePageGeometry(image,argument_list[0].string_reference,
10706 &geometry,exception);
10707 if (attribute_flag[1] != 0)
10708 geometry.x=argument_list[1].integer_reference;
10709 if (attribute_flag[2] != 0)
10710 geometry.y=argument_list[2].integer_reference;
10711 if (attribute_flag[3] != 0)
10712 (void) QueryColorCompliance(argument_list[3].string_reference,
10713 AllCompliance,&draw_info->fill,exception);
10714 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10715 geometry.x,geometry.y,&target,exception);
10716 if (attribute_flag[4] != 0)
10717 QueryColorCompliance(argument_list[4].string_reference,
10718 AllCompliance,&target,exception);
10719 if (attribute_flag[5] != 0)
10720 image->fuzz=StringToDoubleInterval(
10721 argument_list[5].string_reference,(double) QuantumRange+1.0);
10722 if (attribute_flag[6] != 0)
10723 channel=(ChannelType) argument_list[6].integer_reference;
10724 invert=MagickFalse;
10725 if (attribute_flag[7] != 0)
10726 invert=(MagickBooleanType) argument_list[7].integer_reference;
10727 channel_mask=SetImageChannelMask(image,channel);
10728 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10729 geometry.y,invert,exception);
10730 (void) SetImageChannelMask(image,channel_mask);
10731 draw_info=DestroyDrawInfo(draw_info);
10732 break;
10733 }
10734 case 112: /* Distort */
10735 {
10736 AV
10737 *av;
10738
10739 double
10740 *coordinates;
10741
Cristy8645e042016-02-03 16:35:29 -050010742 DistortMethod
cristy4a3ce0a2013-08-03 20:06:59 +000010743 method;
10744
10745 size_t
10746 number_coordinates;
10747
10748 VirtualPixelMethod
10749 virtual_pixel;
10750
10751 if (attribute_flag[0] == 0)
10752 break;
10753 method=UndefinedDistortion;
10754 if (attribute_flag[1] != 0)
Cristy8645e042016-02-03 16:35:29 -050010755 method=(DistortMethod) argument_list[1].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010756 av=(AV *) argument_list[0].array_reference;
10757 number_coordinates=(size_t) av_len(av)+1;
10758 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10759 sizeof(*coordinates));
10760 if (coordinates == (double *) NULL)
10761 {
10762 ThrowPerlException(exception,ResourceLimitFatalError,
10763 "MemoryAllocationFailed",PackageName);
10764 goto PerlException;
10765 }
10766 for (j=0; j < (ssize_t) number_coordinates; j++)
10767 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10768 virtual_pixel=UndefinedVirtualPixelMethod;
10769 if (attribute_flag[2] != 0)
10770 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10771 argument_list[2].integer_reference,exception);
10772 image=DistortImage(image,method,number_coordinates,coordinates,
10773 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10774 exception);
10775 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10776 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10777 exception);
10778 coordinates=(double *) RelinquishMagickMemory(coordinates);
10779 break;
10780 }
10781 case 113: /* Clut */
10782 {
10783 PixelInterpolateMethod
10784 method;
10785
10786 if (attribute_flag[0] == 0)
10787 {
10788 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10789 PackageName);
10790 goto PerlException;
10791 }
10792 method=UndefinedInterpolatePixel;
10793 if (attribute_flag[1] != 0)
10794 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10795 if (attribute_flag[2] != 0)
10796 channel=(ChannelType) argument_list[2].integer_reference;
10797 channel_mask=SetImageChannelMask(image,channel);
10798 (void) ClutImage(image,argument_list[0].image_reference,method,
10799 exception);
10800 (void) SetImageChannelMask(image,channel_mask);
10801 break;
10802 }
10803 case 114: /* LiquidRescale */
10804 {
10805 if (attribute_flag[0] != 0)
10806 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10807 &geometry,exception);
10808 if (attribute_flag[1] != 0)
10809 geometry.width=argument_list[1].integer_reference;
10810 if (attribute_flag[2] != 0)
10811 geometry.height=argument_list[2].integer_reference;
10812 if (attribute_flag[3] == 0)
10813 argument_list[3].real_reference=1.0;
10814 if (attribute_flag[4] == 0)
10815 argument_list[4].real_reference=0.0;
10816 image=LiquidRescaleImage(image,geometry.width,geometry.height,
10817 argument_list[3].real_reference,argument_list[4].real_reference,
10818 exception);
10819 break;
10820 }
10821 case 115: /* EncipherImage */
10822 {
10823 (void) EncipherImage(image,argument_list[0].string_reference,
10824 exception);
10825 break;
10826 }
10827 case 116: /* DecipherImage */
10828 {
10829 (void) DecipherImage(image,argument_list[0].string_reference,
10830 exception);
10831 break;
10832 }
10833 case 117: /* Deskew */
10834 {
10835 geometry_info.rho=QuantumRange/2.0;
10836 if (attribute_flag[0] != 0)
10837 flags=ParseGeometry(argument_list[0].string_reference,
10838 &geometry_info);
10839 if (attribute_flag[1] != 0)
10840 geometry_info.rho=StringToDoubleInterval(
10841 argument_list[1].string_reference,(double) QuantumRange+1.0);
10842 image=DeskewImage(image,geometry_info.rho,exception);
10843 break;
10844 }
10845 case 118: /* Remap */
10846 {
10847 QuantizeInfo
10848 *quantize_info;
10849
10850 if (attribute_flag[0] == 0)
10851 {
10852 ThrowPerlException(exception,OptionError,"RemapImageRequired",
10853 PackageName);
10854 goto PerlException;
10855 }
10856 quantize_info=AcquireQuantizeInfo(info->image_info);
10857 if (attribute_flag[1] != 0)
10858 quantize_info->dither_method=(DitherMethod)
10859 argument_list[1].integer_reference;
10860 (void) RemapImages(quantize_info,image,
10861 argument_list[0].image_reference,exception);
10862 quantize_info=DestroyQuantizeInfo(quantize_info);
10863 break;
10864 }
10865 case 119: /* SparseColor */
10866 {
10867 AV
10868 *av;
10869
10870 double
10871 *coordinates;
10872
10873 SparseColorMethod
10874 method;
10875
10876 size_t
10877 number_coordinates;
10878
10879 VirtualPixelMethod
10880 virtual_pixel;
10881
10882 if (attribute_flag[0] == 0)
10883 break;
10884 method=UndefinedColorInterpolate;
10885 if (attribute_flag[1] != 0)
10886 method=(SparseColorMethod) argument_list[1].integer_reference;
10887 av=(AV *) argument_list[0].array_reference;
10888 number_coordinates=(size_t) av_len(av)+1;
10889 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10890 sizeof(*coordinates));
10891 if (coordinates == (double *) NULL)
10892 {
10893 ThrowPerlException(exception,ResourceLimitFatalError,
10894 "MemoryAllocationFailed",PackageName);
10895 goto PerlException;
10896 }
10897 for (j=0; j < (ssize_t) number_coordinates; j++)
10898 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10899 virtual_pixel=UndefinedVirtualPixelMethod;
10900 if (attribute_flag[2] != 0)
10901 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10902 argument_list[2].integer_reference,exception);
10903 if (attribute_flag[3] != 0)
10904 channel=(ChannelType) argument_list[3].integer_reference;
10905 channel_mask=SetImageChannelMask(image,channel);
10906 image=SparseColorImage(image,method,number_coordinates,coordinates,
10907 exception);
10908 if (image != (Image *) NULL)
10909 (void) SetImageChannelMask(image,channel_mask);
10910 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10911 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10912 exception);
10913 coordinates=(double *) RelinquishMagickMemory(coordinates);
10914 break;
10915 }
10916 case 120: /* Function */
10917 {
10918 AV
10919 *av;
10920
10921 double
10922 *parameters;
10923
10924 MagickFunction
10925 function;
10926
10927 size_t
10928 number_parameters;
10929
10930 VirtualPixelMethod
10931 virtual_pixel;
10932
10933 if (attribute_flag[0] == 0)
10934 break;
10935 function=UndefinedFunction;
10936 if (attribute_flag[1] != 0)
10937 function=(MagickFunction) argument_list[1].integer_reference;
10938 av=(AV *) argument_list[0].array_reference;
10939 number_parameters=(size_t) av_len(av)+1;
10940 parameters=(double *) AcquireQuantumMemory(number_parameters,
10941 sizeof(*parameters));
10942 if (parameters == (double *) NULL)
10943 {
10944 ThrowPerlException(exception,ResourceLimitFatalError,
10945 "MemoryAllocationFailed",PackageName);
10946 goto PerlException;
10947 }
10948 for (j=0; j < (ssize_t) number_parameters; j++)
10949 parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10950 virtual_pixel=UndefinedVirtualPixelMethod;
10951 if (attribute_flag[2] != 0)
10952 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10953 argument_list[2].integer_reference,exception);
10954 (void) FunctionImage(image,function,number_parameters,parameters,
10955 exception);
10956 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10957 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10958 exception);
10959 parameters=(double *) RelinquishMagickMemory(parameters);
10960 break;
10961 }
10962 case 121: /* SelectiveBlur */
10963 {
10964 if (attribute_flag[0] != 0)
10965 {
10966 flags=ParseGeometry(argument_list[0].string_reference,
10967 &geometry_info);
10968 if ((flags & SigmaValue) == 0)
10969 geometry_info.sigma=1.0;
10970 if ((flags & PercentValue) != 0)
10971 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10972 }
10973 if (attribute_flag[1] != 0)
10974 geometry_info.rho=argument_list[1].real_reference;
10975 if (attribute_flag[2] != 0)
10976 geometry_info.sigma=argument_list[2].real_reference;
10977 if (attribute_flag[3] != 0)
10978 geometry_info.xi=argument_list[3].integer_reference;;
10979 if (attribute_flag[5] != 0)
10980 channel=(ChannelType) argument_list[5].integer_reference;
10981 channel_mask=SetImageChannelMask(image,channel);
10982 image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10983 geometry_info.xi,exception);
10984 if (image != (Image *) NULL)
10985 (void) SetImageChannelMask(image,channel_mask);
10986 break;
10987 }
10988 case 122: /* HaldClut */
10989 {
10990 if (attribute_flag[0] == 0)
10991 {
10992 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10993 PackageName);
10994 goto PerlException;
10995 }
10996 if (attribute_flag[1] != 0)
10997 channel=(ChannelType) argument_list[1].integer_reference;
10998 channel_mask=SetImageChannelMask(image,channel);
10999 (void) HaldClutImage(image,argument_list[0].image_reference,
11000 exception);
11001 (void) SetImageChannelMask(image,channel_mask);
11002 break;
11003 }
11004 case 123: /* BlueShift */
11005 {
11006 if (attribute_flag[0] != 0)
11007 (void) ParseGeometry(argument_list[0].string_reference,
11008 &geometry_info);
11009 image=BlueShiftImage(image,geometry_info.rho,exception);
11010 break;
11011 }
11012 case 124: /* ForwardFourierTransformImage */
11013 {
11014 image=ForwardFourierTransformImage(image,
11015 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11016 exception);
11017 break;
11018 }
11019 case 125: /* InverseFourierTransformImage */
11020 {
11021 image=InverseFourierTransformImage(image,image->next,
11022 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11023 exception);
11024 break;
11025 }
11026 case 126: /* ColorDecisionList */
11027 {
11028 if (attribute_flag[0] == 0)
11029 argument_list[0].string_reference=(char *) NULL;
11030 (void) ColorDecisionListImage(image,
11031 argument_list[0].string_reference,exception);
11032 break;
11033 }
11034 case 127: /* AutoGamma */
11035 {
11036 if (attribute_flag[0] != 0)
11037 channel=(ChannelType) argument_list[0].integer_reference;
11038 channel_mask=SetImageChannelMask(image,channel);
11039 (void) AutoGammaImage(image,exception);
11040 (void) SetImageChannelMask(image,channel_mask);
11041 break;
11042 }
11043 case 128: /* AutoLevel */
11044 {
11045 if (attribute_flag[0] != 0)
11046 channel=(ChannelType) argument_list[0].integer_reference;
11047 channel_mask=SetImageChannelMask(image,channel);
11048 (void) AutoLevelImage(image,exception);
11049 (void) SetImageChannelMask(image,channel_mask);
11050 break;
11051 }
11052 case 129: /* LevelColors */
11053 {
11054 PixelInfo
11055 black_point,
11056 white_point;
11057
11058 (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
11059 exception);
11060 (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
11061 exception);
11062 if (attribute_flag[1] != 0)
11063 (void) QueryColorCompliance(
11064 argument_list[1].string_reference,AllCompliance,&black_point,
11065 exception);
11066 if (attribute_flag[2] != 0)
11067 (void) QueryColorCompliance(
11068 argument_list[2].string_reference,AllCompliance,&white_point,
11069 exception);
11070 if (attribute_flag[3] != 0)
11071 channel=(ChannelType) argument_list[3].integer_reference;
11072 channel_mask=SetImageChannelMask(image,channel);
11073 (void) LevelImageColors(image,&black_point,&white_point,
11074 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11075 exception);
11076 (void) SetImageChannelMask(image,channel_mask);
11077 break;
11078 }
11079 case 130: /* Clamp */
11080 {
11081 if (attribute_flag[0] != 0)
11082 channel=(ChannelType) argument_list[0].integer_reference;
11083 channel_mask=SetImageChannelMask(image,channel);
11084 (void) ClampImage(image,exception);
11085 (void) SetImageChannelMask(image,channel_mask);
11086 break;
11087 }
11088 case 131: /* BrightnessContrast */
11089 {
11090 double
11091 brightness,
11092 contrast;
11093
11094 brightness=0.0;
11095 contrast=0.0;
11096 if (attribute_flag[0] != 0)
11097 {
11098 flags=ParseGeometry(argument_list[0].string_reference,
11099 &geometry_info);
11100 brightness=geometry_info.rho;
11101 if ((flags & SigmaValue) == 0)
11102 contrast=geometry_info.sigma;
11103 }
11104 if (attribute_flag[1] != 0)
11105 brightness=argument_list[1].real_reference;
11106 if (attribute_flag[2] != 0)
11107 contrast=argument_list[2].real_reference;
11108 if (attribute_flag[4] != 0)
11109 channel=(ChannelType) argument_list[4].integer_reference;
11110 channel_mask=SetImageChannelMask(image,channel);
11111 (void) BrightnessContrastImage(image,brightness,contrast,exception);
11112 (void) SetImageChannelMask(image,channel_mask);
11113 break;
11114 }
11115 case 132: /* Morphology */
11116 {
11117 KernelInfo
11118 *kernel;
11119
11120 MorphologyMethod
11121 method;
11122
11123 ssize_t
11124 iterations;
11125
11126 if (attribute_flag[0] == 0)
11127 break;
cristy2c57b742014-10-31 00:40:34 +000011128 kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011129 if (kernel == (KernelInfo *) NULL)
11130 break;
11131 if (attribute_flag[1] != 0)
11132 channel=(ChannelType) argument_list[1].integer_reference;
11133 method=UndefinedMorphology;
11134 if (attribute_flag[2] != 0)
11135 method=argument_list[2].integer_reference;
11136 iterations=1;
11137 if (attribute_flag[3] != 0)
11138 iterations=argument_list[3].integer_reference;
11139 channel_mask=SetImageChannelMask(image,channel);
11140 image=MorphologyImage(image,method,iterations,kernel,exception);
11141 if (image != (Image *) NULL)
11142 (void) SetImageChannelMask(image,channel_mask);
11143 kernel=DestroyKernelInfo(kernel);
11144 break;
11145 }
11146 case 133: /* Mode */
11147 {
11148 if (attribute_flag[0] != 0)
11149 {
11150 flags=ParseGeometry(argument_list[0].string_reference,
11151 &geometry_info);
11152 if ((flags & SigmaValue) == 0)
11153 geometry_info.sigma=1.0;
11154 }
11155 if (attribute_flag[1] != 0)
11156 geometry_info.rho=argument_list[1].real_reference;
11157 if (attribute_flag[2] != 0)
11158 geometry_info.sigma=argument_list[2].real_reference;
11159 if (attribute_flag[3] != 0)
11160 channel=(ChannelType) argument_list[3].integer_reference;
11161 channel_mask=SetImageChannelMask(image,channel);
11162 image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11163 (size_t) geometry_info.sigma,exception);
11164 if (image != (Image *) NULL)
11165 (void) SetImageChannelMask(image,channel_mask);
11166 break;
11167 }
11168 case 134: /* Statistic */
11169 {
11170 StatisticType
11171 statistic;
11172
11173 statistic=UndefinedStatistic;
11174 if (attribute_flag[0] != 0)
11175 {
11176 flags=ParseGeometry(argument_list[0].string_reference,
11177 &geometry_info);
11178 if ((flags & SigmaValue) == 0)
11179 geometry_info.sigma=1.0;
11180 }
11181 if (attribute_flag[1] != 0)
11182 geometry_info.rho=argument_list[1].real_reference;
11183 if (attribute_flag[2] != 0)
11184 geometry_info.sigma=argument_list[2].real_reference;
11185 if (attribute_flag[3] != 0)
11186 channel=(ChannelType) argument_list[3].integer_reference;
11187 if (attribute_flag[4] != 0)
11188 statistic=(StatisticType) argument_list[4].integer_reference;
11189 channel_mask=SetImageChannelMask(image,channel);
11190 image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11191 (size_t) geometry_info.sigma,exception);
11192 if (image != (Image *) NULL)
11193 (void) SetImageChannelMask(image,channel_mask);
11194 break;
11195 }
11196 case 135: /* Perceptible */
11197 {
11198 double
11199 epsilon;
11200
11201 epsilon=MagickEpsilon;
11202 if (attribute_flag[0] != 0)
11203 epsilon=argument_list[0].real_reference;
11204 if (attribute_flag[1] != 0)
11205 channel=(ChannelType) argument_list[1].integer_reference;
11206 channel_mask=SetImageChannelMask(image,channel);
11207 (void) PerceptibleImage(image,epsilon,exception);
11208 (void) SetImageChannelMask(image,channel_mask);
11209 break;
11210 }
11211 case 136: /* Poly */
11212 {
11213 AV
11214 *av;
11215
11216 double
11217 *terms;
11218
11219 size_t
11220 number_terms;
11221
11222 if (attribute_flag[0] == 0)
11223 break;
11224 if (attribute_flag[1] != 0)
11225 channel=(ChannelType) argument_list[1].integer_reference;
11226 av=(AV *) argument_list[0].array_reference;
11227 number_terms=(size_t) av_len(av);
11228 terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11229 if (terms == (double *) NULL)
11230 {
11231 ThrowPerlException(exception,ResourceLimitFatalError,
11232 "MemoryAllocationFailed",PackageName);
11233 goto PerlException;
11234 }
11235 for (j=0; j < av_len(av); j++)
11236 terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11237 image=PolynomialImage(image,number_terms >> 1,terms,exception);
11238 terms=(double *) RelinquishMagickMemory(terms);
11239 break;
11240 }
11241 case 137: /* Grayscale */
11242 {
11243 PixelIntensityMethod
11244 method;
11245
11246 method=UndefinedPixelIntensityMethod;
11247 if (attribute_flag[0] != 0)
11248 method=(PixelIntensityMethod) argument_list[0].integer_reference;
11249 (void) GrayscaleImage(image,method,exception);
11250 break;
11251 }
cristy4ceadb82014-03-29 15:30:43 +000011252 case 138: /* Canny */
11253 {
11254 if (attribute_flag[0] != 0)
11255 {
11256 flags=ParseGeometry(argument_list[0].string_reference,
11257 &geometry_info);
11258 if ((flags & SigmaValue) == 0)
11259 geometry_info.sigma=1.0;
11260 if ((flags & XiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011261 geometry_info.xi=0.10;
cristy4ceadb82014-03-29 15:30:43 +000011262 if ((flags & PsiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011263 geometry_info.psi=0.30;
cristy41814f22014-04-09 20:53:11 +000011264 if ((flags & PercentValue) != 0)
11265 {
11266 geometry_info.xi/=100.0;
11267 geometry_info.psi/=100.0;
11268 }
cristy4ceadb82014-03-29 15:30:43 +000011269 }
11270 if (attribute_flag[1] != 0)
11271 geometry_info.rho=argument_list[1].real_reference;
11272 if (attribute_flag[2] != 0)
11273 geometry_info.sigma=argument_list[2].real_reference;
11274 if (attribute_flag[3] != 0)
11275 geometry_info.xi=argument_list[3].real_reference;
11276 if (attribute_flag[4] != 0)
11277 geometry_info.psi=argument_list[4].real_reference;
11278 if (attribute_flag[5] != 0)
11279 channel=(ChannelType) argument_list[5].integer_reference;
11280 channel_mask=SetImageChannelMask(image,channel);
11281 image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11282 geometry_info.xi,geometry_info.psi,exception);
11283 if (image != (Image *) NULL)
11284 (void) SetImageChannelMask(image,channel_mask);
11285 break;
11286 }
cristy2fc10e52014-04-26 14:13:53 +000011287 case 139: /* HoughLine */
cristy4e215022014-04-19 18:02:35 +000011288 {
11289 if (attribute_flag[0] != 0)
11290 {
11291 flags=ParseGeometry(argument_list[0].string_reference,
11292 &geometry_info);
11293 if ((flags & SigmaValue) == 0)
11294 geometry_info.sigma=geometry_info.rho;
cristy20f90422014-04-27 13:34:21 +000011295 if ((flags & XiValue) == 0)
11296 geometry_info.xi=40;
cristy4e215022014-04-19 18:02:35 +000011297 }
11298 if (attribute_flag[1] != 0)
11299 geometry_info.rho=(double) argument_list[1].integer_reference;
11300 if (attribute_flag[2] != 0)
11301 geometry_info.sigma=(double) argument_list[2].integer_reference;
11302 if (attribute_flag[3] != 0)
11303 geometry_info.xi=(double) argument_list[3].integer_reference;
cristy2fc10e52014-04-26 14:13:53 +000011304 image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11305 geometry_info.sigma,(size_t) geometry_info.xi,exception);
11306 break;
11307 }
11308 case 140: /* MeanShift */
11309 {
11310 if (attribute_flag[0] != 0)
11311 {
11312 flags=ParseGeometry(argument_list[0].string_reference,
11313 &geometry_info);
11314 if ((flags & SigmaValue) == 0)
11315 geometry_info.sigma=geometry_info.rho;
cristy2fc10e52014-04-26 14:13:53 +000011316 if ((flags & XiValue) == 0)
cristy1309fc32014-04-26 18:48:37 +000011317 geometry_info.xi=0.10*QuantumRange;
11318 if ((flags & PercentValue) != 0)
11319 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
cristy2fc10e52014-04-26 14:13:53 +000011320 }
11321 if (attribute_flag[1] != 0)
11322 geometry_info.rho=(double) argument_list[1].integer_reference;
11323 if (attribute_flag[2] != 0)
11324 geometry_info.sigma=(double) argument_list[2].integer_reference;
11325 if (attribute_flag[3] != 0)
11326 geometry_info.xi=(double) argument_list[3].integer_reference;
11327 image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
cristy1309fc32014-04-26 18:48:37 +000011328 geometry_info.sigma,geometry_info.xi,exception);
cristy4e215022014-04-19 18:02:35 +000011329 break;
11330 }
cristy3b207f82014-09-27 14:21:20 +000011331 case 141: /* Kuwahara */
11332 {
11333 if (attribute_flag[0] != 0)
11334 {
11335 flags=ParseGeometry(argument_list[0].string_reference,
11336 &geometry_info);
11337 if ((flags & SigmaValue) == 0)
cristy3a9903c2014-10-04 01:14:20 +000011338 geometry_info.sigma=geometry_info.rho-0.5;
cristy3b207f82014-09-27 14:21:20 +000011339 }
11340 if (attribute_flag[1] != 0)
11341 geometry_info.rho=argument_list[1].real_reference;
11342 if (attribute_flag[2] != 0)
11343 geometry_info.sigma=argument_list[2].real_reference;
11344 if (attribute_flag[3] != 0)
11345 channel=(ChannelType) argument_list[3].integer_reference;
11346 channel_mask=SetImageChannelMask(image,channel);
11347 image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11348 exception);
11349 if (image != (Image *) NULL)
11350 (void) SetImageChannelMask(image,channel_mask);
11351 break;
11352 }
Cristy0f5df812017-07-04 18:30:05 -040011353 case 142: /* ConnectedComponents */
cristy6e0b3bc2014-10-19 17:51:42 +000011354 {
11355 size_t
11356 connectivity;
11357
11358 connectivity=4;
11359 if (attribute_flag[0] != 0)
11360 connectivity=argument_list[0].integer_reference;
Cristy2ca0e9a2016-01-01 08:36:14 -050011361 image=ConnectedComponentsImage(image,connectivity,
Cristy4f83be82015-12-31 08:40:53 -050011362 (CCObjectInfo **) NULL,exception);
cristy6e0b3bc2014-10-19 17:51:42 +000011363 break;
11364 }
cristy0b94b392015-06-22 18:56:37 +000011365 case 143: /* Copy */
11366 {
11367 Image
11368 *source_image;
11369
11370 OffsetInfo
11371 offset;
11372
cristy2ffdb092015-06-25 14:31:20 +000011373 RectangleInfo
11374 offset_geometry;
11375
cristyf3a724a2015-06-25 13:02:53 +000011376 source_image=image;
cristy0b94b392015-06-22 18:56:37 +000011377 if (attribute_flag[0] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011378 source_image=argument_list[0].image_reference;
cristy2ffdb092015-06-25 14:31:20 +000011379 SetGeometry(source_image,&geometry);
cristy0b94b392015-06-22 18:56:37 +000011380 if (attribute_flag[1] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011381 flags=ParseGravityGeometry(source_image,
11382 argument_list[1].string_reference,&geometry,exception);
cristy0b94b392015-06-22 18:56:37 +000011383 if (attribute_flag[2] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011384 geometry.width=argument_list[2].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011385 if (attribute_flag[3] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011386 geometry.height=argument_list[3].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011387 if (attribute_flag[4] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011388 geometry.x=argument_list[4].integer_reference;
11389 if (attribute_flag[5] != 0)
11390 geometry.y=argument_list[5].integer_reference;
11391 if (attribute_flag[6] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011392 image->gravity=(GravityType) argument_list[6].integer_reference;
dirk169d1642015-06-27 19:51:08 +000011393 SetGeometry(image,&offset_geometry);
cristyf3a724a2015-06-25 13:02:53 +000011394 if (attribute_flag[7] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011395 flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11396 &offset_geometry,exception);
11397 offset.x=offset_geometry.x;
11398 offset.y=offset_geometry.y;
cristyf3a724a2015-06-25 13:02:53 +000011399 if (attribute_flag[8] != 0)
11400 offset.x=argument_list[8].integer_reference;
11401 if (attribute_flag[9] != 0)
11402 offset.y=argument_list[9].integer_reference;
cristycd6d5182015-06-23 17:22:15 +000011403 (void) CopyImagePixels(image,source_image,&geometry,&offset,
11404 exception);
cristy0b94b392015-06-22 18:56:37 +000011405 break;
11406 }
Cristy5488c982016-02-13 14:07:50 -050011407 case 144: /* Color */
11408 {
11409 PixelInfo
11410 color;
11411
Cristyf20e3562016-02-14 09:08:15 -050011412 (void) QueryColorCompliance("none",AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011413 if (attribute_flag[0] != 0)
Cristyf20e3562016-02-14 09:08:15 -050011414 (void) QueryColorCompliance(argument_list[0].string_reference,
11415 AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011416 (void) SetImageColor(image,&color,exception);
11417 break;
11418 }
Cristy2d830ed2016-02-21 10:54:16 -050011419 case 145: /* WaveletDenoise */
11420 {
Cristyc1759412016-02-27 12:17:58 -050011421 if (attribute_flag[0] != 0)
Cristyee21f7f2016-02-27 15:56:49 -050011422 {
11423 flags=ParseGeometry(argument_list[0].string_reference,
11424 &geometry_info);
11425 if ((flags & PercentValue) != 0)
Cristy23446632016-02-29 09:36:34 -050011426 {
11427 geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11428 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11429 }
Cristyee21f7f2016-02-27 15:56:49 -050011430 if ((flags & SigmaValue) == 0)
11431 geometry_info.sigma=0.0;
11432 }
Cristyc1759412016-02-27 12:17:58 -050011433 if (attribute_flag[1] != 0)
11434 geometry_info.rho=argument_list[1].real_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011435 if (attribute_flag[2] != 0)
Cristyc1759412016-02-27 12:17:58 -050011436 geometry_info.sigma=argument_list[2].real_reference;
11437 if (attribute_flag[3] != 0)
11438 channel=(ChannelType) argument_list[3].integer_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011439 channel_mask=SetImageChannelMask(image,channel);
Cristyc1759412016-02-27 12:17:58 -050011440 image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11441 exception);
Cristy2d830ed2016-02-21 10:54:16 -050011442 if (image != (Image *) NULL)
11443 (void) SetImageChannelMask(image,channel_mask);
11444 break;
11445 }
Cristy99a57162016-12-05 11:47:57 -050011446 case 146: /* Colorspace */
11447 {
11448 ColorspaceType
11449 colorspace;
11450
11451 colorspace=sRGBColorspace;
11452 if (attribute_flag[0] != 0)
11453 colorspace=(ColorspaceType) argument_list[0].integer_reference;
11454 (void) TransformImageColorspace(image,colorspace,exception);
11455 break;
11456 }
Cristy53353872017-07-02 12:24:24 -040011457 case 147: /* AutoThreshold */
11458 {
11459 AutoThresholdMethod
11460 method;
11461
11462 method=UndefinedThresholdMethod;
11463 if (attribute_flag[0] != 0)
Cristyb63e7752017-07-02 13:22:01 -040011464 method=(AutoThresholdMethod) argument_list[0].integer_reference;
Cristy53353872017-07-02 12:24:24 -040011465 (void) AutoThresholdImage(image,method,exception);
11466 break;
11467 }
Cristy532b3382018-08-05 17:56:56 -040011468 case 148: /* RangeThreshold */
11469 {
11470 if (attribute_flag[0] != 0)
11471 {
11472 flags=ParseGeometry(argument_list[0].string_reference,
11473 &geometry_info);
11474 if ((flags & SigmaValue) == 0)
11475 geometry_info.sigma=geometry_info.rho;
11476 if ((flags & XiValue) == 0)
11477 geometry_info.xi=geometry_info.sigma;
11478 if ((flags & PsiValue) == 0)
11479 geometry_info.psi=geometry_info.xi;
11480 }
11481 if (attribute_flag[1] != 0)
11482 geometry_info.rho=argument_list[1].real_reference;
11483 if (attribute_flag[2] != 0)
11484 geometry_info.sigma=argument_list[2].real_reference;
11485 if (attribute_flag[3] != 0)
11486 geometry_info.xi=argument_list[3].real_reference;
11487 if (attribute_flag[4] != 0)
11488 geometry_info.psi=argument_list[4].real_reference;
11489 if (attribute_flag[5] != 0)
11490 channel=(ChannelType) argument_list[5].integer_reference;
11491 channel_mask=SetImageChannelMask(image,channel);
Cristy9b220db2018-08-05 18:02:28 -040011492 (void) RangeThresholdImage(image,geometry_info.rho,
11493 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
Cristy532b3382018-08-05 17:56:56 -040011494 if (image != (Image *) NULL)
11495 (void) SetImageChannelMask(image,channel_mask);
11496 break;
11497 }
Cristy9f252542018-11-21 19:13:46 -050011498 case 149: /* CLAHE */
11499 {
11500 if (attribute_flag[0] != 0)
Cristy768e9002019-01-08 07:35:16 -050011501 {
11502 flags=ParseGeometry(argument_list[0].string_reference,
11503 &geometry_info);
11504 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
11505 &geometry,exception);
11506 }
Cristy9f252542018-11-21 19:13:46 -050011507 if (attribute_flag[1] != 0)
Cristy30263282018-12-11 16:40:25 -050011508 geometry.width=argument_list[1].integer_reference;
Cristy9f252542018-11-21 19:13:46 -050011509 if (attribute_flag[2] != 0)
Cristy30263282018-12-11 16:40:25 -050011510 geometry.height=argument_list[2].integer_reference;
Cristy9f252542018-11-21 19:13:46 -050011511 if (attribute_flag[3] != 0)
Cristy768e9002019-01-08 07:35:16 -050011512 geometry.x=argument_list[3].integer_reference;
Cristy9f252542018-11-21 19:13:46 -050011513 if (attribute_flag[4] != 0)
Cristy768e9002019-01-08 07:35:16 -050011514 geometry_info.psi=argument_list[4].real_reference;
Cristyd9b98812018-12-16 09:30:05 -050011515 (void) CLAHEImage(image,geometry.width,geometry.height,geometry.x,
Cristy768e9002019-01-08 07:35:16 -050011516 geometry_info.psi,exception);
Cristy9f252542018-11-21 19:13:46 -050011517 break;
11518 }
Cristyb4ab5192019-12-19 06:53:46 -050011519 case 150: /* Kmeans */
11520 {
11521 if (attribute_flag[0] != 0)
11522 {
11523 flags=ParseGeometry(argument_list[0].string_reference,
11524 &geometry_info);
11525 if ((flags & SigmaValue) == 0)
Cristyc809e482019-12-21 09:59:52 -050011526 geometry_info.sigma=100.0;
Cristyb4ab5192019-12-19 06:53:46 -050011527 if ((flags & XiValue) == 0)
Cristyc809e482019-12-21 09:59:52 -050011528 geometry_info.xi=0.01;
Cristyb4ab5192019-12-19 06:53:46 -050011529 }
11530 if (attribute_flag[1] != 0)
11531 geometry_info.rho=argument_list[1].integer_reference;
11532 if (attribute_flag[2] != 0)
11533 geometry_info.sigma=argument_list[2].integer_reference;
11534 if (attribute_flag[3] != 0)
11535 geometry_info.xi=(ChannelType) argument_list[3].real_reference;
11536 (void) KmeansImage(image,geometry_info.rho,geometry_info.sigma,
11537 geometry_info.xi,exception);
11538 break;
11539 }
cristy4a3ce0a2013-08-03 20:06:59 +000011540 }
11541 if (next != (Image *) NULL)
11542 (void) CatchImageException(next);
Cristy7e567962018-02-03 12:42:20 -050011543 if ((region_info.width*region_info.height) != 0)
11544 (void) SetImageRegionMask(image,WritePixelMask,
11545 (const RectangleInfo *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011546 if (image != (Image *) NULL)
11547 {
11548 number_images++;
11549 if (next && (next != image))
11550 {
11551 image->next=next->next;
11552 if (image->next != (Image *) NULL)
11553 image->next->previous=image;
11554 DeleteImageFromRegistry(*pv,next);
11555 }
11556 sv_setiv(*pv,PTR2IV(image));
11557 next=image;
11558 }
11559 if (*pv)
11560 pv++;
11561 }
11562
11563 PerlException:
11564 if (reference_vector)
11565 reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11566 InheritPerlException(exception,perl_exception);
11567 exception=DestroyExceptionInfo(exception);
11568 sv_setiv(perl_exception,(IV) number_images);
11569 SvPOK_on(perl_exception);
11570 ST(0)=sv_2mortal(perl_exception);
11571 XSRETURN(1);
11572 }
11573
11574#
11575###############################################################################
11576# #
11577# #
11578# #
11579# M o n t a g e #
11580# #
11581# #
11582# #
11583###############################################################################
11584#
11585#
11586void
11587Montage(ref,...)
11588 Image::Magick ref=NO_INIT
11589 ALIAS:
11590 MontageImage = 1
11591 montage = 2
11592 montageimage = 3
11593 PPCODE:
11594 {
11595 AV
11596 *av;
11597
11598 char
11599 *attribute;
11600
11601 ExceptionInfo
11602 *exception;
11603
11604 HV
11605 *hv;
11606
11607 Image
11608 *image,
11609 *next;
11610
11611 PixelInfo
11612 transparent_color;
11613
11614 MontageInfo
11615 *montage_info;
11616
11617 register ssize_t
11618 i;
11619
11620 ssize_t
11621 sp;
11622
11623 struct PackageInfo
11624 *info;
11625
11626 SV
11627 *av_reference,
11628 *perl_exception,
11629 *reference,
11630 *rv,
11631 *sv;
11632
11633 PERL_UNUSED_VAR(ref);
11634 PERL_UNUSED_VAR(ix);
11635 exception=AcquireExceptionInfo();
11636 perl_exception=newSVpv("",0);
11637 sv=NULL;
11638 attribute=NULL;
11639 if (sv_isobject(ST(0)) == 0)
11640 {
11641 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11642 PackageName);
11643 goto PerlException;
11644 }
11645 reference=SvRV(ST(0));
11646 hv=SvSTASH(reference);
11647 av=newAV();
11648 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11649 SvREFCNT_dec(av);
11650 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11651 if (image == (Image *) NULL)
11652 {
11653 ThrowPerlException(exception,OptionError,"NoImagesDefined",
11654 PackageName);
11655 goto PerlException;
11656 }
11657 /*
11658 Get options.
11659 */
11660 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11661 montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11662 (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11663 exception);
11664 for (i=2; i < items; i+=2)
11665 {
11666 attribute=(char *) SvPV(ST(i-1),na);
11667 switch (*attribute)
11668 {
11669 case 'B':
11670 case 'b':
11671 {
11672 if (LocaleCompare(attribute,"background") == 0)
11673 {
11674 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11675 &montage_info->background_color,exception);
11676 for (next=image; next; next=next->next)
11677 next->background_color=montage_info->background_color;
11678 break;
11679 }
11680 if (LocaleCompare(attribute,"border") == 0)
11681 {
11682 montage_info->border_width=SvIV(ST(i));
11683 break;
11684 }
11685 if (LocaleCompare(attribute,"bordercolor") == 0)
11686 {
11687 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11688 &montage_info->border_color,exception);
11689 for (next=image; next; next=next->next)
11690 next->border_color=montage_info->border_color;
11691 break;
11692 }
11693 if (LocaleCompare(attribute,"borderwidth") == 0)
11694 {
11695 montage_info->border_width=SvIV(ST(i));
11696 break;
11697 }
11698 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11699 attribute);
11700 break;
11701 }
11702 case 'C':
11703 case 'c':
11704 {
11705 if (LocaleCompare(attribute,"compose") == 0)
11706 {
11707 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11708 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11709 if (sp < 0)
11710 {
11711 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11712 SvPV(ST(i),na));
11713 break;
11714 }
11715 for (next=image; next; next=next->next)
11716 next->compose=(CompositeOperator) sp;
11717 break;
11718 }
11719 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11720 attribute);
11721 break;
11722 }
11723 case 'F':
11724 case 'f':
11725 {
11726 if (LocaleCompare(attribute,"fill") == 0)
11727 {
11728 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11729 &montage_info->fill,exception);
11730 break;
11731 }
11732 if (LocaleCompare(attribute,"font") == 0)
11733 {
11734 (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11735 break;
11736 }
11737 if (LocaleCompare(attribute,"frame") == 0)
11738 {
11739 char
11740 *p;
11741
11742 p=SvPV(ST(i),na);
11743 if (IsGeometry(p) == MagickFalse)
11744 {
11745 ThrowPerlException(exception,OptionError,"MissingGeometry",
11746 p);
11747 break;
11748 }
11749 (void) CloneString(&montage_info->frame,p);
11750 if (*p == '\0')
11751 montage_info->frame=(char *) NULL;
11752 break;
11753 }
11754 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11755 attribute);
11756 break;
11757 }
11758 case 'G':
11759 case 'g':
11760 {
11761 if (LocaleCompare(attribute,"geometry") == 0)
11762 {
11763 char
11764 *p;
11765
11766 p=SvPV(ST(i),na);
11767 if (IsGeometry(p) == MagickFalse)
11768 {
11769 ThrowPerlException(exception,OptionError,"MissingGeometry",
11770 p);
11771 break;
11772 }
11773 (void) CloneString(&montage_info->geometry,p);
11774 if (*p == '\0')
11775 montage_info->geometry=(char *) NULL;
11776 break;
11777 }
11778 if (LocaleCompare(attribute,"gravity") == 0)
11779 {
11780 ssize_t
11781 in;
11782
11783 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11784 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11785 if (in < 0)
11786 {
11787 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11788 SvPV(ST(i),na));
11789 return;
11790 }
11791 montage_info->gravity=(GravityType) in;
11792 for (next=image; next; next=next->next)
11793 next->gravity=(GravityType) in;
11794 break;
11795 }
11796 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11797 attribute);
11798 break;
11799 }
11800 case 'L':
11801 case 'l':
11802 {
11803 if (LocaleCompare(attribute,"label") == 0)
11804 {
11805 for (next=image; next; next=next->next)
Cristy935a4052017-03-31 17:45:37 -040011806 (void) SetImageProperty(next,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +000011807 info ? info->image_info : (ImageInfo *) NULL,next,
Cristy935a4052017-03-31 17:45:37 -040011808 SvPV(ST(i),na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011809 break;
11810 }
11811 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11812 attribute);
11813 break;
11814 }
11815 case 'M':
11816 case 'm':
11817 {
11818 if (LocaleCompare(attribute,"mattecolor") == 0)
11819 {
11820 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
Cristy8645e042016-02-03 16:35:29 -050011821 &montage_info->alpha_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011822 for (next=image; next; next=next->next)
Cristy8645e042016-02-03 16:35:29 -050011823 next->alpha_color=montage_info->alpha_color;
cristy4a3ce0a2013-08-03 20:06:59 +000011824 break;
11825 }
11826 if (LocaleCompare(attribute,"mode") == 0)
11827 {
11828 ssize_t
11829 in;
11830
11831 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11832 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11833 switch (in)
11834 {
11835 default:
11836 {
11837 ThrowPerlException(exception,OptionError,
11838 "UnrecognizedModeType",SvPV(ST(i),na));
11839 break;
11840 }
11841 case FrameMode:
11842 {
11843 (void) CloneString(&montage_info->frame,"15x15+3+3");
11844 montage_info->shadow=MagickTrue;
11845 break;
11846 }
11847 case UnframeMode:
11848 {
11849 montage_info->frame=(char *) NULL;
11850 montage_info->shadow=MagickFalse;
11851 montage_info->border_width=0;
11852 break;
11853 }
11854 case ConcatenateMode:
11855 {
11856 montage_info->frame=(char *) NULL;
11857 montage_info->shadow=MagickFalse;
11858 (void) CloneString(&montage_info->geometry,"+0+0");
11859 montage_info->border_width=0;
11860 }
11861 }
11862 break;
11863 }
11864 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11865 attribute);
11866 break;
11867 }
11868 case 'P':
11869 case 'p':
11870 {
11871 if (LocaleCompare(attribute,"pointsize") == 0)
11872 {
11873 montage_info->pointsize=SvIV(ST(i));
11874 break;
11875 }
11876 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11877 attribute);
11878 break;
11879 }
11880 case 'S':
11881 case 's':
11882 {
11883 if (LocaleCompare(attribute,"shadow") == 0)
11884 {
11885 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11886 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11887 if (sp < 0)
11888 {
11889 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11890 SvPV(ST(i),na));
11891 break;
11892 }
11893 montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11894 break;
11895 }
11896 if (LocaleCompare(attribute,"stroke") == 0)
11897 {
11898 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11899 &montage_info->stroke,exception);
11900 break;
11901 }
11902 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11903 attribute);
11904 break;
11905 }
11906 case 'T':
11907 case 't':
11908 {
11909 if (LocaleCompare(attribute,"texture") == 0)
11910 {
11911 (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11912 break;
11913 }
11914 if (LocaleCompare(attribute,"tile") == 0)
11915 {
11916 char *p=SvPV(ST(i),na);
11917 if (IsGeometry(p) == MagickFalse)
11918 {
11919 ThrowPerlException(exception,OptionError,"MissingGeometry",
11920 p);
11921 break;
11922 }
11923 (void) CloneString(&montage_info->tile,p);
11924 if (*p == '\0')
11925 montage_info->tile=(char *) NULL;
11926 break;
11927 }
11928 if (LocaleCompare(attribute,"title") == 0)
11929 {
11930 (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11931 break;
11932 }
11933 if (LocaleCompare(attribute,"transparent") == 0)
11934 {
11935 PixelInfo
11936 transparent_color;
11937
11938 QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11939 &transparent_color,exception);
11940 for (next=image; next; next=next->next)
11941 (void) TransparentPaintImage(next,&transparent_color,
11942 TransparentAlpha,MagickFalse,exception);
11943 break;
11944 }
11945 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11946 attribute);
11947 break;
11948 }
11949 default:
11950 {
11951 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11952 attribute);
11953 break;
11954 }
11955 }
11956 }
11957 image=MontageImageList(info->image_info,montage_info,image,exception);
11958 montage_info=DestroyMontageInfo(montage_info);
11959 if (image == (Image *) NULL)
11960 goto PerlException;
11961 if (transparent_color.alpha != TransparentAlpha)
11962 for (next=image; next; next=next->next)
11963 (void) TransparentPaintImage(next,&transparent_color,
11964 TransparentAlpha,MagickFalse,exception);
11965 for ( ; image; image=image->next)
11966 {
11967 AddImageToRegistry(sv,image);
11968 rv=newRV(sv);
11969 av_push(av,sv_bless(rv,hv));
11970 SvREFCNT_dec(sv);
11971 }
11972 exception=DestroyExceptionInfo(exception);
11973 ST(0)=av_reference;
11974 SvREFCNT_dec(perl_exception);
11975 XSRETURN(1);
11976
11977 PerlException:
11978 InheritPerlException(exception,perl_exception);
11979 exception=DestroyExceptionInfo(exception);
11980 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11981 SvPOK_on(perl_exception);
11982 ST(0)=sv_2mortal(perl_exception);
11983 XSRETURN(1);
11984 }
11985
11986#
11987###############################################################################
11988# #
11989# #
11990# #
11991# M o r p h #
11992# #
11993# #
11994# #
11995###############################################################################
11996#
11997#
11998void
11999Morph(ref,...)
12000 Image::Magick ref=NO_INIT
12001 ALIAS:
12002 MorphImage = 1
12003 morph = 2
12004 morphimage = 3
12005 PPCODE:
12006 {
12007 AV
12008 *av;
12009
12010 char
12011 *attribute;
12012
12013 ExceptionInfo
12014 *exception;
12015
12016 HV
12017 *hv;
12018
12019 Image
12020 *image;
12021
12022 register ssize_t
12023 i;
12024
12025 ssize_t
12026 number_frames;
12027
12028 struct PackageInfo
12029 *info;
12030
12031 SV
12032 *av_reference,
12033 *perl_exception,
12034 *reference,
12035 *rv,
12036 *sv;
12037
12038 PERL_UNUSED_VAR(ref);
12039 PERL_UNUSED_VAR(ix);
12040 exception=AcquireExceptionInfo();
12041 perl_exception=newSVpv("",0);
12042 sv=NULL;
12043 av=NULL;
12044 attribute=NULL;
12045 if (sv_isobject(ST(0)) == 0)
12046 {
12047 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12048 PackageName);
12049 goto PerlException;
12050 }
12051 reference=SvRV(ST(0));
12052 hv=SvSTASH(reference);
12053 av=newAV();
12054 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12055 SvREFCNT_dec(av);
12056 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12057 if (image == (Image *) NULL)
12058 {
12059 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12060 PackageName);
12061 goto PerlException;
12062 }
12063 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12064 /*
12065 Get attribute.
12066 */
12067 number_frames=30;
12068 for (i=2; i < items; i+=2)
12069 {
12070 attribute=(char *) SvPV(ST(i-1),na);
12071 switch (*attribute)
12072 {
12073 case 'F':
12074 case 'f':
12075 {
12076 if (LocaleCompare(attribute,"frames") == 0)
12077 {
12078 number_frames=SvIV(ST(i));
12079 break;
12080 }
12081 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12082 attribute);
12083 break;
12084 }
12085 default:
12086 {
12087 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12088 attribute);
12089 break;
12090 }
12091 }
12092 }
12093 image=MorphImages(image,number_frames,exception);
12094 if (image == (Image *) NULL)
12095 goto PerlException;
12096 for ( ; image; image=image->next)
12097 {
12098 AddImageToRegistry(sv,image);
12099 rv=newRV(sv);
12100 av_push(av,sv_bless(rv,hv));
12101 SvREFCNT_dec(sv);
12102 }
12103 exception=DestroyExceptionInfo(exception);
12104 ST(0)=av_reference;
12105 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12106 XSRETURN(1);
12107
12108 PerlException:
12109 InheritPerlException(exception,perl_exception);
12110 exception=DestroyExceptionInfo(exception);
12111 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12112 SvPOK_on(perl_exception);
12113 ST(0)=sv_2mortal(perl_exception);
12114 XSRETURN(1);
12115 }
12116
12117#
12118###############################################################################
12119# #
12120# #
12121# #
12122# M o s a i c #
12123# #
12124# #
12125# #
12126###############################################################################
12127#
12128#
12129void
12130Mosaic(ref)
12131 Image::Magick ref=NO_INIT
12132 ALIAS:
12133 MosaicImage = 1
12134 mosaic = 2
12135 mosaicimage = 3
12136 PPCODE:
12137 {
12138 AV
12139 *av;
12140
12141 ExceptionInfo
12142 *exception;
12143
12144 HV
12145 *hv;
12146
12147 Image
12148 *image;
12149
12150 struct PackageInfo
12151 *info;
12152
12153 SV
12154 *perl_exception,
12155 *reference,
12156 *rv,
12157 *sv;
12158
12159 PERL_UNUSED_VAR(ref);
12160 PERL_UNUSED_VAR(ix);
12161 exception=AcquireExceptionInfo();
12162 perl_exception=newSVpv("",0);
12163 sv=NULL;
12164 if (sv_isobject(ST(0)) == 0)
12165 {
12166 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12167 PackageName);
12168 goto PerlException;
12169 }
12170 reference=SvRV(ST(0));
12171 hv=SvSTASH(reference);
12172 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12173 if (image == (Image *) NULL)
12174 {
12175 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12176 PackageName);
12177 goto PerlException;
12178 }
12179 image=MergeImageLayers(image,MosaicLayer,exception);
12180 /*
12181 Create blessed Perl array for the returned image.
12182 */
12183 av=newAV();
12184 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12185 SvREFCNT_dec(av);
12186 AddImageToRegistry(sv,image);
12187 rv=newRV(sv);
12188 av_push(av,sv_bless(rv,hv));
12189 SvREFCNT_dec(sv);
cristy4a3ce0a2013-08-03 20:06:59 +000012190 (void) CopyMagickString(info->image_info->filename,image->filename,
cristy151b66d2015-04-15 10:50:31 +000012191 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012192 SetImageInfo(info->image_info,0,exception);
12193 exception=DestroyExceptionInfo(exception);
12194 SvREFCNT_dec(perl_exception);
12195 XSRETURN(1);
12196
12197 PerlException:
12198 InheritPerlException(exception,perl_exception);
12199 exception=DestroyExceptionInfo(exception);
12200 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12201 SvPOK_on(perl_exception); /* return messages in string context */
12202 ST(0)=sv_2mortal(perl_exception);
12203 XSRETURN(1);
12204 }
12205
12206#
12207###############################################################################
12208# #
12209# #
12210# #
12211# P i n g #
12212# #
12213# #
12214# #
12215###############################################################################
12216#
12217#
12218void
12219Ping(ref,...)
12220 Image::Magick ref=NO_INIT
12221 ALIAS:
12222 PingImage = 1
12223 ping = 2
12224 pingimage = 3
12225 PPCODE:
12226 {
12227 AV
12228 *av;
12229
12230 char
12231 **keep,
12232 **list;
12233
12234 ExceptionInfo
12235 *exception;
12236
12237 Image
12238 *image,
12239 *next;
12240
12241 int
12242 n;
12243
12244 MagickBooleanType
12245 status;
12246
12247 register char
12248 **p;
12249
12250 register ssize_t
12251 i;
12252
12253 ssize_t
12254 ac;
12255
12256 STRLEN
12257 *length;
12258
12259 struct PackageInfo
12260 *info,
12261 *package_info;
12262
12263 SV
12264 *perl_exception,
12265 *reference;
12266
12267 size_t
12268 count;
12269
12270 PERL_UNUSED_VAR(ref);
12271 PERL_UNUSED_VAR(ix);
12272 exception=AcquireExceptionInfo();
12273 perl_exception=newSVpv("",0);
12274 package_info=(struct PackageInfo *) NULL;
12275 ac=(items < 2) ? 1 : items-1;
12276 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12277 keep=list;
12278 length=(STRLEN *) NULL;
12279 if (list == (char **) NULL)
12280 {
12281 ThrowPerlException(exception,ResourceLimitError,
12282 "MemoryAllocationFailed",PackageName);
12283 goto PerlException;
12284 }
12285 keep=list;
12286 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12287 if (length == (STRLEN *) NULL)
12288 {
12289 ThrowPerlException(exception,ResourceLimitError,
12290 "MemoryAllocationFailed",PackageName);
12291 goto PerlException;
12292 }
12293 if (sv_isobject(ST(0)) == 0)
12294 {
12295 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12296 PackageName);
12297 goto PerlException;
12298 }
12299 reference=SvRV(ST(0));
12300 if (SvTYPE(reference) != SVt_PVAV)
12301 {
12302 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12303 PackageName);
12304 goto PerlException;
12305 }
12306 av=(AV *) reference;
12307 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12308 exception);
12309 package_info=ClonePackageInfo(info,exception);
12310 n=1;
12311 if (items <= 1)
12312 *list=(char *) (*package_info->image_info->filename ?
12313 package_info->image_info->filename : "XC:black");
12314 else
12315 for (n=0, i=0; i < ac; i++)
12316 {
12317 list[n]=(char *) SvPV(ST(i+1),length[n]);
12318 if ((items >= 3) && strEQcase(list[n],"blob"))
12319 {
12320 void
12321 *blob;
12322
12323 i++;
12324 blob=(void *) (SvPV(ST(i+1),length[n]));
12325 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12326 }
12327 if ((items >= 3) && strEQcase(list[n],"filename"))
12328 continue;
12329 if ((items >= 3) && strEQcase(list[n],"file"))
12330 {
12331 FILE
12332 *file;
12333
12334 PerlIO
12335 *io_info;
12336
12337 i++;
12338 io_info=IoIFP(sv_2io(ST(i+1)));
12339 if (io_info == (PerlIO *) NULL)
12340 {
12341 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12342 PackageName);
12343 continue;
12344 }
12345 file=PerlIO_findFILE(io_info);
12346 if (file == (FILE *) NULL)
12347 {
12348 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12349 PackageName);
12350 continue;
12351 }
12352 SetImageInfoFile(package_info->image_info,file);
12353 }
12354 if ((items >= 3) && strEQcase(list[n],"magick"))
12355 continue;
12356 n++;
12357 }
12358 list[n]=(char *) NULL;
12359 keep=list;
12360 status=ExpandFilenames(&n,&list);
12361 if (status == MagickFalse)
12362 {
12363 ThrowPerlException(exception,ResourceLimitError,
12364 "MemoryAllocationFailed",PackageName);
12365 goto PerlException;
12366 }
12367 count=0;
12368 for (i=0; i < n; i++)
12369 {
12370 (void) CopyMagickString(package_info->image_info->filename,list[i],
cristy151b66d2015-04-15 10:50:31 +000012371 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012372 image=PingImage(package_info->image_info,exception);
12373 if (image == (Image *) NULL)
12374 break;
12375 if ((package_info->image_info->file != (FILE *) NULL) ||
12376 (package_info->image_info->blob != (void *) NULL))
12377 DisassociateImageStream(image);
12378 count+=GetImageListLength(image);
12379 EXTEND(sp,4*count);
12380 for (next=image; next; next=next->next)
12381 {
12382 PUSHs(sv_2mortal(newSViv(next->columns)));
12383 PUSHs(sv_2mortal(newSViv(next->rows)));
12384 PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12385 PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12386 }
12387 image=DestroyImageList(image);
12388 }
12389 /*
12390 Free resources.
12391 */
12392 for (i=0; i < n; i++)
12393 if (list[i] != (char *) NULL)
12394 for (p=keep; list[i] != *p++; )
12395 if (*p == NULL)
12396 {
12397 list[i]=(char *) RelinquishMagickMemory(list[i]);
12398 break;
12399 }
12400
12401 PerlException:
12402 if (package_info != (struct PackageInfo *) NULL)
12403 DestroyPackageInfo(package_info);
12404 if (list && (list != keep))
12405 list=(char **) RelinquishMagickMemory(list);
12406 if (keep)
12407 keep=(char **) RelinquishMagickMemory(keep);
12408 if (length)
12409 length=(STRLEN *) RelinquishMagickMemory(length);
12410 InheritPerlException(exception,perl_exception);
12411 exception=DestroyExceptionInfo(exception);
12412 SvREFCNT_dec(perl_exception); /* throw away all errors */
12413 }
12414
12415#
12416###############################################################################
12417# #
12418# #
12419# #
12420# P r e v i e w #
12421# #
12422# #
12423# #
12424###############################################################################
12425#
12426#
12427void
12428Preview(ref,...)
12429 Image::Magick ref=NO_INIT
12430 ALIAS:
12431 PreviewImage = 1
12432 preview = 2
12433 previewimage = 3
12434 PPCODE:
12435 {
12436 AV
12437 *av;
12438
12439 ExceptionInfo
12440 *exception;
12441
12442 HV
12443 *hv;
12444
12445 Image
12446 *image,
12447 *preview_image;
12448
12449 PreviewType
12450 preview_type;
12451
12452 struct PackageInfo
12453 *info;
12454
12455 SV
12456 *av_reference,
12457 *perl_exception,
12458 *reference,
12459 *rv,
12460 *sv;
12461
12462 PERL_UNUSED_VAR(ref);
12463 PERL_UNUSED_VAR(ix);
12464 exception=AcquireExceptionInfo();
12465 perl_exception=newSVpv("",0);
12466 sv=NULL;
12467 av=NULL;
12468 if (sv_isobject(ST(0)) == 0)
12469 {
12470 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12471 PackageName);
12472 goto PerlException;
12473 }
12474 reference=SvRV(ST(0));
12475 hv=SvSTASH(reference);
12476 av=newAV();
12477 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12478 SvREFCNT_dec(av);
12479 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12480 if (image == (Image *) NULL)
12481 {
12482 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12483 PackageName);
12484 goto PerlException;
12485 }
12486 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12487 preview_type=GammaPreview;
12488 if (items > 1)
12489 preview_type=(PreviewType)
12490 ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12491 for ( ; image; image=image->next)
12492 {
12493 preview_image=PreviewImage(image,preview_type,exception);
12494 if (preview_image == (Image *) NULL)
12495 goto PerlException;
12496 AddImageToRegistry(sv,preview_image);
12497 rv=newRV(sv);
12498 av_push(av,sv_bless(rv,hv));
12499 SvREFCNT_dec(sv);
12500 }
12501 exception=DestroyExceptionInfo(exception);
12502 ST(0)=av_reference;
12503 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12504 XSRETURN(1);
12505
12506 PerlException:
12507 InheritPerlException(exception,perl_exception);
12508 exception=DestroyExceptionInfo(exception);
12509 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12510 SvPOK_on(perl_exception);
12511 ST(0)=sv_2mortal(perl_exception);
12512 XSRETURN(1);
12513 }
12514
12515#
12516###############################################################################
12517# #
12518# #
12519# #
12520# Q u e r y C o l o r #
12521# #
12522# #
12523# #
12524###############################################################################
12525#
12526#
12527void
12528QueryColor(ref,...)
12529 Image::Magick ref=NO_INIT
12530 ALIAS:
12531 querycolor = 1
12532 PPCODE:
12533 {
12534 char
12535 *name;
12536
12537 ExceptionInfo
12538 *exception;
12539
12540 PixelInfo
12541 color;
12542
12543 register ssize_t
12544 i;
12545
12546 SV
12547 *perl_exception;
12548
12549 PERL_UNUSED_VAR(ref);
12550 PERL_UNUSED_VAR(ix);
12551 exception=AcquireExceptionInfo();
12552 perl_exception=newSVpv("",0);
12553 if (items == 1)
12554 {
12555 const ColorInfo
12556 **colorlist;
12557
12558 size_t
12559 colors;
12560
12561 colorlist=GetColorInfoList("*",&colors,exception);
12562 EXTEND(sp,colors);
12563 for (i=0; i < (ssize_t) colors; i++)
12564 {
12565 PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12566 }
12567 colorlist=(const ColorInfo **)
12568 RelinquishMagickMemory((ColorInfo **) colorlist);
12569 goto PerlException;
12570 }
12571 EXTEND(sp,5*items);
12572 for (i=1; i < items; i++)
12573 {
12574 name=(char *) SvPV(ST(i),na);
12575 if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12576 {
12577 PUSHs(&sv_undef);
12578 continue;
12579 }
12580 PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12581 PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12582 PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12583 if (color.colorspace == CMYKColorspace)
12584 PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
cristy17f11b02014-12-20 19:37:04 +000012585 if (color.alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +000012586 PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12587 }
12588
12589 PerlException:
12590 InheritPerlException(exception,perl_exception);
12591 exception=DestroyExceptionInfo(exception);
12592 SvREFCNT_dec(perl_exception);
12593 }
12594
12595#
12596###############################################################################
12597# #
12598# #
12599# #
12600# Q u e r y C o l o r N a m e #
12601# #
12602# #
12603# #
12604###############################################################################
12605#
12606#
12607void
12608QueryColorname(ref,...)
12609 Image::Magick ref=NO_INIT
12610 ALIAS:
12611 querycolorname = 1
12612 PPCODE:
12613 {
12614 AV
12615 *av;
12616
12617 char
cristy151b66d2015-04-15 10:50:31 +000012618 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012619
12620 ExceptionInfo
12621 *exception;
12622
12623 Image
12624 *image;
12625
12626 PixelInfo
12627 target_color;
12628
12629 register ssize_t
12630 i;
12631
12632 struct PackageInfo
12633 *info;
12634
12635 SV
12636 *perl_exception,
12637 *reference; /* reference is the SV* of ref=SvIV(reference) */
12638
12639 PERL_UNUSED_VAR(ref);
12640 PERL_UNUSED_VAR(ix);
12641 exception=AcquireExceptionInfo();
12642 perl_exception=newSVpv("",0);
12643 reference=SvRV(ST(0));
12644 av=(AV *) reference;
12645 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12646 exception);
12647 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12648 if (image == (Image *) NULL)
12649 {
12650 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12651 PackageName);
12652 goto PerlException;
12653 }
12654 EXTEND(sp,items);
12655 for (i=1; i < items; i++)
12656 {
12657 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12658 exception);
12659 (void) QueryColorname(image,&target_color,SVGCompliance,message,
12660 exception);
12661 PUSHs(sv_2mortal(newSVpv(message,0)));
12662 }
12663
12664 PerlException:
12665 InheritPerlException(exception,perl_exception);
12666 exception=DestroyExceptionInfo(exception);
12667 SvREFCNT_dec(perl_exception);
12668 }
12669
12670#
12671###############################################################################
12672# #
12673# #
12674# #
12675# Q u e r y F o n t #
12676# #
12677# #
12678# #
12679###############################################################################
12680#
12681#
12682void
12683QueryFont(ref,...)
12684 Image::Magick ref=NO_INIT
12685 ALIAS:
12686 queryfont = 1
12687 PPCODE:
12688 {
12689 char
12690 *name,
cristy151b66d2015-04-15 10:50:31 +000012691 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012692
12693 ExceptionInfo
12694 *exception;
12695
12696 register ssize_t
12697 i;
12698
12699 SV
12700 *perl_exception;
12701
12702 volatile const TypeInfo
12703 *type_info;
12704
12705 PERL_UNUSED_VAR(ref);
12706 PERL_UNUSED_VAR(ix);
12707 exception=AcquireExceptionInfo();
12708 perl_exception=newSVpv("",0);
12709 if (items == 1)
12710 {
12711 const TypeInfo
12712 **typelist;
12713
12714 size_t
12715 types;
12716
12717 typelist=GetTypeInfoList("*",&types,exception);
12718 EXTEND(sp,types);
12719 for (i=0; i < (ssize_t) types; i++)
12720 {
12721 PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12722 }
12723 typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12724 typelist);
12725 goto PerlException;
12726 }
12727 EXTEND(sp,10*items);
12728 for (i=1; i < items; i++)
12729 {
12730 name=(char *) SvPV(ST(i),na);
12731 type_info=GetTypeInfo(name,exception);
12732 if (type_info == (TypeInfo *) NULL)
12733 {
12734 PUSHs(&sv_undef);
12735 continue;
12736 }
12737 if (type_info->name == (char *) NULL)
12738 PUSHs(&sv_undef);
12739 else
12740 PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12741 if (type_info->description == (char *) NULL)
12742 PUSHs(&sv_undef);
12743 else
12744 PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12745 if (type_info->family == (char *) NULL)
12746 PUSHs(&sv_undef);
12747 else
12748 PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12749 if (type_info->style == UndefinedStyle)
12750 PUSHs(&sv_undef);
12751 else
12752 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12753 type_info->style),0)));
12754 if (type_info->stretch == UndefinedStretch)
12755 PUSHs(&sv_undef);
12756 else
12757 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12758 type_info->stretch),0)));
cristy151b66d2015-04-15 10:50:31 +000012759 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
cristy4a3ce0a2013-08-03 20:06:59 +000012760 type_info->weight);
12761 PUSHs(sv_2mortal(newSVpv(message,0)));
12762 if (type_info->encoding == (char *) NULL)
12763 PUSHs(&sv_undef);
12764 else
12765 PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12766 if (type_info->foundry == (char *) NULL)
12767 PUSHs(&sv_undef);
12768 else
12769 PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12770 if (type_info->format == (char *) NULL)
12771 PUSHs(&sv_undef);
12772 else
12773 PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12774 if (type_info->metrics == (char *) NULL)
12775 PUSHs(&sv_undef);
12776 else
12777 PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12778 if (type_info->glyphs == (char *) NULL)
12779 PUSHs(&sv_undef);
12780 else
12781 PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12782 }
12783
12784 PerlException:
12785 InheritPerlException(exception,perl_exception);
12786 exception=DestroyExceptionInfo(exception);
12787 SvREFCNT_dec(perl_exception);
12788 }
12789
12790#
12791###############################################################################
12792# #
12793# #
12794# #
12795# Q u e r y F o n t M e t r i c s #
12796# #
12797# #
12798# #
12799###############################################################################
12800#
12801#
12802void
12803QueryFontMetrics(ref,...)
12804 Image::Magick ref=NO_INIT
12805 ALIAS:
12806 queryfontmetrics = 1
12807 PPCODE:
12808 {
12809 AffineMatrix
12810 affine,
12811 current;
12812
12813 AV
12814 *av;
12815
12816 char
12817 *attribute;
12818
12819 double
12820 x,
12821 y;
12822
12823 DrawInfo
12824 *draw_info;
12825
12826 ExceptionInfo
12827 *exception;
12828
12829 GeometryInfo
12830 geometry_info;
12831
12832 Image
12833 *image;
12834
12835 MagickBooleanType
12836 status;
12837
12838 MagickStatusType
12839 flags;
12840
12841 register ssize_t
12842 i;
12843
12844 ssize_t
12845 type;
12846
12847 struct PackageInfo
12848 *info,
12849 *package_info;
12850
12851 SV
12852 *perl_exception,
12853 *reference; /* reference is the SV* of ref=SvIV(reference) */
12854
12855 TypeMetric
12856 metrics;
12857
12858 PERL_UNUSED_VAR(ref);
12859 PERL_UNUSED_VAR(ix);
12860 exception=AcquireExceptionInfo();
12861 package_info=(struct PackageInfo *) NULL;
12862 perl_exception=newSVpv("",0);
12863 reference=SvRV(ST(0));
12864 av=(AV *) reference;
12865 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12866 exception);
12867 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12868 if (image == (Image *) NULL)
12869 {
12870 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12871 PackageName);
12872 goto PerlException;
12873 }
12874 package_info=ClonePackageInfo(info,exception);
12875 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12876 CloneString(&draw_info->text,"");
12877 current=draw_info->affine;
12878 GetAffineMatrix(&affine);
12879 x=0.0;
12880 y=0.0;
12881 EXTEND(sp,7*items);
12882 for (i=2; i < items; i+=2)
12883 {
12884 attribute=(char *) SvPV(ST(i-1),na);
12885 switch (*attribute)
12886 {
12887 case 'A':
12888 case 'a':
12889 {
12890 if (LocaleCompare(attribute,"antialias") == 0)
12891 {
12892 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12893 SvPV(ST(i),na));
12894 if (type < 0)
12895 {
12896 ThrowPerlException(exception,OptionError,"UnrecognizedType",
12897 SvPV(ST(i),na));
12898 break;
12899 }
12900 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12901 break;
12902 }
12903 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12904 attribute);
12905 break;
12906 }
12907 case 'd':
12908 case 'D':
12909 {
12910 if (LocaleCompare(attribute,"density") == 0)
12911 {
12912 CloneString(&draw_info->density,SvPV(ST(i),na));
12913 break;
12914 }
12915 if (LocaleCompare(attribute,"direction") == 0)
12916 {
12917 draw_info->direction=(DirectionType) ParseCommandOption(
12918 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12919 break;
12920 }
12921 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12922 attribute);
12923 break;
12924 }
12925 case 'e':
12926 case 'E':
12927 {
12928 if (LocaleCompare(attribute,"encoding") == 0)
12929 {
12930 CloneString(&draw_info->encoding,SvPV(ST(i),na));
12931 break;
12932 }
12933 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12934 attribute);
12935 break;
12936 }
12937 case 'f':
12938 case 'F':
12939 {
12940 if (LocaleCompare(attribute,"family") == 0)
12941 {
12942 CloneString(&draw_info->family,SvPV(ST(i),na));
12943 break;
12944 }
12945 if (LocaleCompare(attribute,"fill") == 0)
12946 {
12947 if (info)
12948 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12949 &draw_info->fill,exception);
12950 break;
12951 }
12952 if (LocaleCompare(attribute,"font") == 0)
12953 {
12954 CloneString(&draw_info->font,SvPV(ST(i),na));
12955 break;
12956 }
12957 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12958 attribute);
12959 break;
12960 }
12961 case 'g':
12962 case 'G':
12963 {
12964 if (LocaleCompare(attribute,"geometry") == 0)
12965 {
12966 CloneString(&draw_info->geometry,SvPV(ST(i),na));
12967 break;
12968 }
12969 if (LocaleCompare(attribute,"gravity") == 0)
12970 {
12971 draw_info->gravity=(GravityType) ParseCommandOption(
12972 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12973 break;
12974 }
12975 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12976 attribute);
12977 break;
12978 }
12979 case 'i':
12980 case 'I':
12981 {
12982 if (LocaleCompare(attribute,"interline-spacing") == 0)
12983 {
12984 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12985 draw_info->interline_spacing=geometry_info.rho;
12986 break;
12987 }
12988 if (LocaleCompare(attribute,"interword-spacing") == 0)
12989 {
12990 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12991 draw_info->interword_spacing=geometry_info.rho;
12992 break;
12993 }
12994 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12995 attribute);
12996 break;
12997 }
12998 case 'k':
12999 case 'K':
13000 {
13001 if (LocaleCompare(attribute,"kerning") == 0)
13002 {
13003 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13004 draw_info->kerning=geometry_info.rho;
13005 break;
13006 }
13007 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13008 attribute);
13009 break;
13010 }
13011 case 'p':
13012 case 'P':
13013 {
13014 if (LocaleCompare(attribute,"pointsize") == 0)
13015 {
13016 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13017 draw_info->pointsize=geometry_info.rho;
13018 break;
13019 }
13020 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13021 attribute);
13022 break;
13023 }
13024 case 'r':
13025 case 'R':
13026 {
13027 if (LocaleCompare(attribute,"rotate") == 0)
13028 {
13029 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13030 affine.rx=geometry_info.rho;
13031 affine.ry=geometry_info.sigma;
13032 if ((flags & SigmaValue) == 0)
13033 affine.ry=affine.rx;
13034 break;
13035 }
13036 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13037 attribute);
13038 break;
13039 }
13040 case 's':
13041 case 'S':
13042 {
13043 if (LocaleCompare(attribute,"scale") == 0)
13044 {
13045 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13046 affine.sx=geometry_info.rho;
13047 affine.sy=geometry_info.sigma;
13048 if ((flags & SigmaValue) == 0)
13049 affine.sy=affine.sx;
13050 break;
13051 }
13052 if (LocaleCompare(attribute,"skew") == 0)
13053 {
13054 double
13055 x_angle,
13056 y_angle;
13057
13058 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13059 x_angle=geometry_info.rho;
13060 y_angle=geometry_info.sigma;
13061 if ((flags & SigmaValue) == 0)
13062 y_angle=x_angle;
13063 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13064 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13065 break;
13066 }
13067 if (LocaleCompare(attribute,"stroke") == 0)
13068 {
13069 if (info)
13070 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13071 &draw_info->stroke,exception);
13072 break;
13073 }
13074 if (LocaleCompare(attribute,"style") == 0)
13075 {
13076 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13077 SvPV(ST(i),na));
13078 if (type < 0)
13079 {
13080 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13081 SvPV(ST(i),na));
13082 break;
13083 }
13084 draw_info->style=(StyleType) type;
13085 break;
13086 }
13087 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13088 attribute);
13089 break;
13090 }
13091 case 't':
13092 case 'T':
13093 {
13094 if (LocaleCompare(attribute,"text") == 0)
13095 {
13096 CloneString(&draw_info->text,SvPV(ST(i),na));
13097 break;
13098 }
13099 if (LocaleCompare(attribute,"translate") == 0)
13100 {
13101 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13102 affine.tx=geometry_info.rho;
13103 affine.ty=geometry_info.sigma;
13104 if ((flags & SigmaValue) == 0)
13105 affine.ty=affine.tx;
13106 break;
13107 }
13108 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13109 attribute);
13110 break;
13111 }
13112 case 'w':
13113 case 'W':
13114 {
13115 if (LocaleCompare(attribute,"weight") == 0)
13116 {
13117 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13118 draw_info->weight=(size_t) geometry_info.rho;
13119 break;
13120 }
13121 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13122 attribute);
13123 break;
13124 }
13125 case 'x':
13126 case 'X':
13127 {
13128 if (LocaleCompare(attribute,"x") == 0)
13129 {
13130 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13131 x=geometry_info.rho;
13132 break;
13133 }
13134 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13135 attribute);
13136 break;
13137 }
13138 case 'y':
13139 case 'Y':
13140 {
13141 if (LocaleCompare(attribute,"y") == 0)
13142 {
13143 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13144 y=geometry_info.rho;
13145 break;
13146 }
13147 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13148 attribute);
13149 break;
13150 }
13151 default:
13152 {
13153 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13154 attribute);
13155 break;
13156 }
13157 }
13158 }
13159 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13160 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13161 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13162 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13163 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13164 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13165 if (draw_info->geometry == (char *) NULL)
13166 {
13167 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013168 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013169 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013170 }
13171 status=GetTypeMetrics(image,draw_info,&metrics,exception);
13172 (void) CatchImageException(image);
13173 if (status == MagickFalse)
13174 PUSHs(&sv_undef);
13175 else
13176 {
13177 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13178 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13179 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13180 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13181 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13182 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13183 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13184 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13185 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13186 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13187 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13188 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13189 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13190 }
13191 draw_info=DestroyDrawInfo(draw_info);
13192
13193 PerlException:
13194 if (package_info != (struct PackageInfo *) NULL)
13195 DestroyPackageInfo(package_info);
13196 InheritPerlException(exception,perl_exception);
13197 exception=DestroyExceptionInfo(exception);
13198 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13199 }
13200
13201#
13202###############################################################################
13203# #
13204# #
13205# #
13206# 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 #
13207# #
13208# #
13209# #
13210###############################################################################
13211#
13212#
13213void
13214QueryMultilineFontMetrics(ref,...)
13215 Image::Magick ref=NO_INIT
13216 ALIAS:
13217 querymultilinefontmetrics = 1
13218 PPCODE:
13219 {
13220 AffineMatrix
13221 affine,
13222 current;
13223
13224 AV
13225 *av;
13226
13227 char
13228 *attribute;
13229
13230 double
13231 x,
13232 y;
13233
13234 DrawInfo
13235 *draw_info;
13236
13237 ExceptionInfo
13238 *exception;
13239
13240 GeometryInfo
13241 geometry_info;
13242
13243 Image
13244 *image;
13245
13246 MagickBooleanType
13247 status;
13248
13249 MagickStatusType
13250 flags;
13251
13252 register ssize_t
13253 i;
13254
13255 ssize_t
13256 type;
13257
13258 struct PackageInfo
13259 *info,
13260 *package_info;
13261
13262 SV
13263 *perl_exception,
13264 *reference; /* reference is the SV* of ref=SvIV(reference) */
13265
13266 TypeMetric
13267 metrics;
13268
13269 PERL_UNUSED_VAR(ref);
13270 PERL_UNUSED_VAR(ix);
13271 exception=AcquireExceptionInfo();
13272 package_info=(struct PackageInfo *) NULL;
13273 perl_exception=newSVpv("",0);
13274 reference=SvRV(ST(0));
13275 av=(AV *) reference;
13276 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13277 exception);
13278 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13279 if (image == (Image *) NULL)
13280 {
13281 ThrowPerlException(exception,OptionError,"NoImagesDefined",
13282 PackageName);
13283 goto PerlException;
13284 }
13285 package_info=ClonePackageInfo(info,exception);
13286 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13287 CloneString(&draw_info->text,"");
13288 current=draw_info->affine;
13289 GetAffineMatrix(&affine);
13290 x=0.0;
13291 y=0.0;
13292 EXTEND(sp,7*items);
13293 for (i=2; i < items; i+=2)
13294 {
13295 attribute=(char *) SvPV(ST(i-1),na);
13296 switch (*attribute)
13297 {
13298 case 'A':
13299 case 'a':
13300 {
13301 if (LocaleCompare(attribute,"antialias") == 0)
13302 {
13303 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13304 SvPV(ST(i),na));
13305 if (type < 0)
13306 {
13307 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13308 SvPV(ST(i),na));
13309 break;
13310 }
13311 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13312 break;
13313 }
13314 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13315 attribute);
13316 break;
13317 }
13318 case 'd':
13319 case 'D':
13320 {
13321 if (LocaleCompare(attribute,"density") == 0)
13322 {
13323 CloneString(&draw_info->density,SvPV(ST(i),na));
13324 break;
13325 }
13326 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13327 attribute);
13328 break;
13329 }
13330 case 'e':
13331 case 'E':
13332 {
13333 if (LocaleCompare(attribute,"encoding") == 0)
13334 {
13335 CloneString(&draw_info->encoding,SvPV(ST(i),na));
13336 break;
13337 }
13338 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13339 attribute);
13340 break;
13341 }
13342 case 'f':
13343 case 'F':
13344 {
13345 if (LocaleCompare(attribute,"family") == 0)
13346 {
13347 CloneString(&draw_info->family,SvPV(ST(i),na));
13348 break;
13349 }
13350 if (LocaleCompare(attribute,"fill") == 0)
13351 {
13352 if (info)
13353 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13354 &draw_info->fill,exception);
13355 break;
13356 }
13357 if (LocaleCompare(attribute,"font") == 0)
13358 {
13359 CloneString(&draw_info->font,SvPV(ST(i),na));
13360 break;
13361 }
13362 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13363 attribute);
13364 break;
13365 }
13366 case 'g':
13367 case 'G':
13368 {
13369 if (LocaleCompare(attribute,"geometry") == 0)
13370 {
13371 CloneString(&draw_info->geometry,SvPV(ST(i),na));
13372 break;
13373 }
13374 if (LocaleCompare(attribute,"gravity") == 0)
13375 {
13376 draw_info->gravity=(GravityType) ParseCommandOption(
13377 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13378 break;
13379 }
13380 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13381 attribute);
13382 break;
13383 }
13384 case 'p':
13385 case 'P':
13386 {
13387 if (LocaleCompare(attribute,"pointsize") == 0)
13388 {
13389 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13390 draw_info->pointsize=geometry_info.rho;
13391 break;
13392 }
13393 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13394 attribute);
13395 break;
13396 }
13397 case 'r':
13398 case 'R':
13399 {
13400 if (LocaleCompare(attribute,"rotate") == 0)
13401 {
13402 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13403 affine.rx=geometry_info.rho;
13404 affine.ry=geometry_info.sigma;
13405 if ((flags & SigmaValue) == 0)
13406 affine.ry=affine.rx;
13407 break;
13408 }
13409 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13410 attribute);
13411 break;
13412 }
13413 case 's':
13414 case 'S':
13415 {
13416 if (LocaleCompare(attribute,"scale") == 0)
13417 {
13418 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13419 affine.sx=geometry_info.rho;
13420 affine.sy=geometry_info.sigma;
13421 if ((flags & SigmaValue) == 0)
13422 affine.sy=affine.sx;
13423 break;
13424 }
13425 if (LocaleCompare(attribute,"skew") == 0)
13426 {
13427 double
13428 x_angle,
13429 y_angle;
13430
13431 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13432 x_angle=geometry_info.rho;
13433 y_angle=geometry_info.sigma;
13434 if ((flags & SigmaValue) == 0)
13435 y_angle=x_angle;
13436 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13437 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13438 break;
13439 }
13440 if (LocaleCompare(attribute,"stroke") == 0)
13441 {
13442 if (info)
13443 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13444 &draw_info->stroke,exception);
13445 break;
13446 }
13447 if (LocaleCompare(attribute,"style") == 0)
13448 {
13449 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13450 SvPV(ST(i),na));
13451 if (type < 0)
13452 {
13453 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13454 SvPV(ST(i),na));
13455 break;
13456 }
13457 draw_info->style=(StyleType) type;
13458 break;
13459 }
13460 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13461 attribute);
13462 break;
13463 }
13464 case 't':
13465 case 'T':
13466 {
13467 if (LocaleCompare(attribute,"text") == 0)
13468 {
13469 CloneString(&draw_info->text,SvPV(ST(i),na));
13470 break;
13471 }
13472 if (LocaleCompare(attribute,"translate") == 0)
13473 {
13474 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13475 affine.tx=geometry_info.rho;
13476 affine.ty=geometry_info.sigma;
13477 if ((flags & SigmaValue) == 0)
13478 affine.ty=affine.tx;
13479 break;
13480 }
13481 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13482 attribute);
13483 break;
13484 }
13485 case 'w':
13486 case 'W':
13487 {
13488 if (LocaleCompare(attribute,"weight") == 0)
13489 {
13490 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13491 draw_info->weight=(size_t) geometry_info.rho;
13492 break;
13493 }
13494 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13495 attribute);
13496 break;
13497 }
13498 case 'x':
13499 case 'X':
13500 {
13501 if (LocaleCompare(attribute,"x") == 0)
13502 {
13503 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13504 x=geometry_info.rho;
13505 break;
13506 }
13507 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13508 attribute);
13509 break;
13510 }
13511 case 'y':
13512 case 'Y':
13513 {
13514 if (LocaleCompare(attribute,"y") == 0)
13515 {
13516 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13517 y=geometry_info.rho;
13518 break;
13519 }
13520 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13521 attribute);
13522 break;
13523 }
13524 default:
13525 {
13526 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13527 attribute);
13528 break;
13529 }
13530 }
13531 }
13532 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13533 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13534 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13535 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13536 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13537 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13538 if (draw_info->geometry == (char *) NULL)
13539 {
13540 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013541 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013542 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013543 }
13544 status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13545 (void) CatchException(exception);
13546 if (status == MagickFalse)
13547 PUSHs(&sv_undef);
13548 else
13549 {
13550 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13551 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13552 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13553 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13554 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13555 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13556 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13557 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13558 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13559 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13560 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13561 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13562 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13563 }
13564 draw_info=DestroyDrawInfo(draw_info);
13565
13566 PerlException:
13567 if (package_info != (struct PackageInfo *) NULL)
13568 DestroyPackageInfo(package_info);
13569 InheritPerlException(exception,perl_exception);
13570 exception=DestroyExceptionInfo(exception);
13571 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13572 }
13573
13574#
13575###############################################################################
13576# #
13577# #
13578# #
13579# Q u e r y F o r m a t #
13580# #
13581# #
13582# #
13583###############################################################################
13584#
13585#
13586void
13587QueryFormat(ref,...)
13588 Image::Magick ref=NO_INIT
13589 ALIAS:
13590 queryformat = 1
13591 PPCODE:
13592 {
13593 char
13594 *name;
13595
13596 ExceptionInfo
13597 *exception;
13598
13599 register ssize_t
13600 i;
13601
13602 SV
13603 *perl_exception;
13604
13605 volatile const MagickInfo
13606 *magick_info;
13607
13608 PERL_UNUSED_VAR(ref);
13609 PERL_UNUSED_VAR(ix);
13610 exception=AcquireExceptionInfo();
13611 perl_exception=newSVpv("",0);
13612 if (items == 1)
13613 {
13614 char
cristy151b66d2015-04-15 10:50:31 +000013615 format[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000013616
13617 const MagickInfo
13618 **format_list;
13619
13620 size_t
13621 types;
13622
13623 format_list=GetMagickInfoList("*",&types,exception);
13624 EXTEND(sp,types);
13625 for (i=0; i < (ssize_t) types; i++)
13626 {
cristy151b66d2015-04-15 10:50:31 +000013627 (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000013628 LocaleLower(format);
13629 PUSHs(sv_2mortal(newSVpv(format,0)));
13630 }
13631 format_list=(const MagickInfo **)
13632 RelinquishMagickMemory((MagickInfo *) format_list);
13633 goto PerlException;
13634 }
13635 EXTEND(sp,8*items);
13636 for (i=1; i < items; i++)
13637 {
13638 name=(char *) SvPV(ST(i),na);
13639 magick_info=GetMagickInfo(name,exception);
13640 if (magick_info == (const MagickInfo *) NULL)
13641 {
13642 PUSHs(&sv_undef);
13643 continue;
13644 }
cristy4a3ce0a2013-08-03 20:06:59 +000013645 if (magick_info->description == (char *) NULL)
13646 PUSHs(&sv_undef);
13647 else
13648 PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
Cristy31756212019-07-31 15:55:08 -040013649 if (magick_info->magick_module == (char *) NULL)
cristy4a3ce0a2013-08-03 20:06:59 +000013650 PUSHs(&sv_undef);
13651 else
Cristy31756212019-07-31 15:55:08 -040013652 PUSHs(sv_2mortal(newSVpv(magick_info->magick_module,0)));
cristy4a3ce0a2013-08-03 20:06:59 +000013653 }
13654
13655 PerlException:
13656 InheritPerlException(exception,perl_exception);
13657 exception=DestroyExceptionInfo(exception);
13658 SvREFCNT_dec(perl_exception);
13659 }
13660
13661#
13662###############################################################################
13663# #
13664# #
13665# #
13666# Q u e r y O p t i o n #
13667# #
13668# #
13669# #
13670###############################################################################
13671#
13672#
13673void
13674QueryOption(ref,...)
13675 Image::Magick ref=NO_INIT
13676 ALIAS:
13677 queryoption = 1
13678 PPCODE:
13679 {
13680 char
13681 **options;
13682
13683 ExceptionInfo
13684 *exception;
13685
13686 register ssize_t
13687 i;
13688
13689 ssize_t
13690 j,
13691 option;
13692
13693 SV
13694 *perl_exception;
13695
13696 PERL_UNUSED_VAR(ref);
13697 PERL_UNUSED_VAR(ix);
13698 exception=AcquireExceptionInfo();
13699 perl_exception=newSVpv("",0);
13700 EXTEND(sp,8*items);
13701 for (i=1; i < items; i++)
13702 {
13703 option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13704 SvPV(ST(i),na));
13705 options=GetCommandOptions((CommandOption) option);
13706 if (options == (char **) NULL)
13707 PUSHs(&sv_undef);
13708 else
13709 {
13710 for (j=0; options[j] != (char *) NULL; j++)
13711 PUSHs(sv_2mortal(newSVpv(options[j],0)));
13712 options=DestroyStringList(options);
13713 }
13714 }
13715
13716 InheritPerlException(exception,perl_exception);
13717 exception=DestroyExceptionInfo(exception);
13718 SvREFCNT_dec(perl_exception);
13719 }
13720
13721#
13722###############################################################################
13723# #
13724# #
13725# #
13726# R e a d #
13727# #
13728# #
13729# #
13730###############################################################################
13731#
13732#
13733void
13734Read(ref,...)
13735 Image::Magick ref=NO_INIT
13736 ALIAS:
13737 ReadImage = 1
13738 read = 2
13739 readimage = 3
13740 PPCODE:
13741 {
13742 AV
13743 *av;
13744
13745 char
13746 **keep,
13747 **list;
13748
13749 ExceptionInfo
13750 *exception;
13751
13752 HV
13753 *hv;
13754
13755 Image
13756 *image;
13757
13758 int
13759 n;
13760
13761 MagickBooleanType
13762 status;
13763
13764 register char
13765 **p;
13766
13767 register ssize_t
13768 i;
13769
13770 ssize_t
13771 ac,
13772 number_images;
13773
13774 STRLEN
13775 *length;
13776
13777 struct PackageInfo
13778 *info,
13779 *package_info;
13780
13781 SV
13782 *perl_exception, /* Perl variable for storing messages */
13783 *reference,
13784 *rv,
13785 *sv;
13786
13787 PERL_UNUSED_VAR(ref);
13788 PERL_UNUSED_VAR(ix);
13789 exception=AcquireExceptionInfo();
13790 perl_exception=newSVpv("",0);
13791 sv=NULL;
13792 package_info=(struct PackageInfo *) NULL;
13793 number_images=0;
13794 ac=(items < 2) ? 1 : items-1;
13795 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13796 keep=list;
13797 length=(STRLEN *) NULL;
13798 if (list == (char **) NULL)
13799 {
13800 ThrowPerlException(exception,ResourceLimitError,
13801 "MemoryAllocationFailed",PackageName);
13802 goto PerlException;
13803 }
13804 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13805 if (length == (STRLEN *) NULL)
13806 {
13807 ThrowPerlException(exception,ResourceLimitError,
13808 "MemoryAllocationFailed",PackageName);
13809 goto PerlException;
13810 }
13811 if (sv_isobject(ST(0)) == 0)
13812 {
13813 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13814 PackageName);
13815 goto PerlException;
13816 }
13817 reference=SvRV(ST(0));
13818 hv=SvSTASH(reference);
13819 if (SvTYPE(reference) != SVt_PVAV)
13820 {
13821 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13822 PackageName);
13823 goto PerlException;
13824 }
13825 av=(AV *) reference;
13826 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13827 exception);
13828 package_info=ClonePackageInfo(info,exception);
13829 n=1;
13830 if (items <= 1)
13831 *list=(char *) (*package_info->image_info->filename ?
13832 package_info->image_info->filename : "XC:black");
13833 else
13834 for (n=0, i=0; i < ac; i++)
13835 {
13836 list[n]=(char *) SvPV(ST(i+1),length[n]);
13837 if ((items >= 3) && strEQcase(list[n],"blob"))
13838 {
13839 void
13840 *blob;
13841
13842 i++;
13843 blob=(void *) (SvPV(ST(i+1),length[n]));
13844 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13845 }
13846 if ((items >= 3) && strEQcase(list[n],"filename"))
13847 continue;
13848 if ((items >= 3) && strEQcase(list[n],"file"))
13849 {
13850 FILE
13851 *file;
13852
13853 PerlIO
13854 *io_info;
13855
13856 i++;
13857 io_info=IoIFP(sv_2io(ST(i+1)));
13858 if (io_info == (PerlIO *) NULL)
13859 {
13860 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13861 PackageName);
13862 continue;
13863 }
13864 file=PerlIO_findFILE(io_info);
13865 if (file == (FILE *) NULL)
13866 {
13867 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13868 PackageName);
13869 continue;
13870 }
13871 SetImageInfoFile(package_info->image_info,file);
13872 }
13873 if ((items >= 3) && strEQcase(list[n],"magick"))
13874 continue;
13875 n++;
13876 }
13877 list[n]=(char *) NULL;
13878 keep=list;
13879 status=ExpandFilenames(&n,&list);
13880 if (status == MagickFalse)
13881 {
13882 ThrowPerlException(exception,ResourceLimitError,
13883 "MemoryAllocationFailed",PackageName);
13884 goto PerlException;
13885 }
13886 number_images=0;
13887 for (i=0; i < n; i++)
13888 {
13889 if ((package_info->image_info->file == (FILE *) NULL) &&
13890 (package_info->image_info->blob == (void *) NULL))
13891 image=ReadImages(package_info->image_info,list[i],exception);
13892 else
13893 {
13894 image=ReadImages(package_info->image_info,
13895 package_info->image_info->filename,exception);
13896 if (image != (Image *) NULL)
13897 DisassociateImageStream(image);
13898 }
13899 if (image == (Image *) NULL)
13900 break;
13901 for ( ; image; image=image->next)
13902 {
13903 AddImageToRegistry(sv,image);
13904 rv=newRV(sv);
13905 av_push(av,sv_bless(rv,hv));
13906 SvREFCNT_dec(sv);
13907 number_images++;
13908 }
13909 }
13910 /*
13911 Free resources.
13912 */
13913 for (i=0; i < n; i++)
13914 if (list[i] != (char *) NULL)
13915 for (p=keep; list[i] != *p++; )
13916 if (*p == (char *) NULL)
13917 {
13918 list[i]=(char *) RelinquishMagickMemory(list[i]);
13919 break;
13920 }
13921
13922 PerlException:
13923 if (package_info != (struct PackageInfo *) NULL)
13924 DestroyPackageInfo(package_info);
13925 if (list && (list != keep))
13926 list=(char **) RelinquishMagickMemory(list);
13927 if (keep)
13928 keep=(char **) RelinquishMagickMemory(keep);
13929 if (length)
13930 length=(STRLEN *) RelinquishMagickMemory(length);
13931 InheritPerlException(exception,perl_exception);
13932 exception=DestroyExceptionInfo(exception);
13933 sv_setiv(perl_exception,(IV) number_images);
13934 SvPOK_on(perl_exception);
13935 ST(0)=sv_2mortal(perl_exception);
13936 XSRETURN(1);
13937 }
13938
13939#
13940###############################################################################
13941# #
13942# #
13943# #
13944# R e m o t e #
13945# #
13946# #
13947# #
13948###############################################################################
13949#
13950#
13951void
13952Remote(ref,...)
13953 Image::Magick ref=NO_INIT
13954 ALIAS:
13955 RemoteCommand = 1
13956 remote = 2
13957 remoteCommand = 3
13958 PPCODE:
13959 {
13960 AV
13961 *av;
13962
13963 ExceptionInfo
13964 *exception;
13965
13966 register ssize_t
13967 i;
13968
13969 SV
13970 *perl_exception,
13971 *reference;
13972
13973 struct PackageInfo
13974 *info;
13975
13976 PERL_UNUSED_VAR(ref);
13977 PERL_UNUSED_VAR(ix);
13978 exception=AcquireExceptionInfo();
13979 perl_exception=newSVpv("",0);
13980 reference=SvRV(ST(0));
13981 av=(AV *) reference;
13982 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13983 exception);
13984 for (i=1; i < items; i++)
13985 (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13986 SvPV(ST(i),na),exception);
13987 InheritPerlException(exception,perl_exception);
13988 exception=DestroyExceptionInfo(exception);
13989 SvREFCNT_dec(perl_exception); /* throw away all errors */
13990 }
13991
13992#
13993###############################################################################
13994# #
13995# #
13996# #
13997# S e t #
13998# #
13999# #
14000# #
14001###############################################################################
14002#
14003#
14004void
14005Set(ref,...)
14006 Image::Magick ref=NO_INIT
14007 ALIAS:
14008 SetAttributes = 1
14009 SetAttribute = 2
14010 set = 3
14011 setattributes = 4
14012 setattribute = 5
14013 PPCODE:
14014 {
14015 ExceptionInfo
14016 *exception;
14017
14018 Image
14019 *image;
14020
14021 register ssize_t
14022 i;
14023
14024 struct PackageInfo
14025 *info;
14026
14027 SV
14028 *perl_exception,
14029 *reference; /* reference is the SV* of ref=SvIV(reference) */
14030
14031 PERL_UNUSED_VAR(ref);
14032 PERL_UNUSED_VAR(ix);
14033 exception=AcquireExceptionInfo();
14034 perl_exception=newSVpv("",0);
14035 if (sv_isobject(ST(0)) == 0)
14036 {
14037 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14038 PackageName);
14039 goto PerlException;
14040 }
14041 reference=SvRV(ST(0));
14042 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14043 if (items == 2)
14044 SetAttribute(aTHX_ info,image,"size",ST(1),exception);
14045 else
14046 for (i=2; i < items; i+=2)
14047 SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
14048
14049 PerlException:
14050 InheritPerlException(exception,perl_exception);
14051 exception=DestroyExceptionInfo(exception);
14052 sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
14053 SvPOK_on(perl_exception);
14054 ST(0)=sv_2mortal(perl_exception);
14055 XSRETURN(1);
14056 }
14057
14058#
14059###############################################################################
14060# #
14061# #
14062# #
14063# S e t P i x e l #
14064# #
14065# #
14066# #
14067###############################################################################
14068#
14069#
14070void
14071SetPixel(ref,...)
14072 Image::Magick ref=NO_INIT
14073 ALIAS:
14074 setpixel = 1
14075 setPixel = 2
14076 PPCODE:
14077 {
14078 AV
14079 *av;
14080
14081 char
14082 *attribute;
14083
14084 ChannelType
14085 channel,
14086 channel_mask;
14087
14088 ExceptionInfo
14089 *exception;
14090
14091 Image
14092 *image;
14093
14094 MagickBooleanType
14095 normalize;
14096
14097 RectangleInfo
14098 region;
14099
14100 register ssize_t
14101 i;
14102
14103 register Quantum
14104 *q;
14105
14106 ssize_t
14107 option;
14108
14109 struct PackageInfo
14110 *info;
14111
14112 SV
14113 *perl_exception,
14114 *reference; /* reference is the SV* of ref=SvIV(reference) */
14115
14116 PERL_UNUSED_VAR(ref);
14117 PERL_UNUSED_VAR(ix);
14118 exception=AcquireExceptionInfo();
14119 perl_exception=newSVpv("",0);
14120 reference=SvRV(ST(0));
14121 av=(AV *) reference;
14122 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14123 exception);
14124 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14125 if (image == (Image *) NULL)
14126 {
14127 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14128 PackageName);
14129 goto PerlException;
14130 }
14131 av=(AV *) NULL;
14132 normalize=MagickTrue;
14133 region.x=0;
14134 region.y=0;
14135 region.width=image->columns;
14136 region.height=1;
14137 if (items == 1)
14138 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14139 channel=DefaultChannels;
14140 for (i=2; i < items; i+=2)
14141 {
14142 attribute=(char *) SvPV(ST(i-1),na);
14143 switch (*attribute)
14144 {
14145 case 'C':
14146 case 'c':
14147 {
14148 if (LocaleCompare(attribute,"channel") == 0)
14149 {
14150 ssize_t
14151 option;
14152
14153 option=ParseChannelOption(SvPV(ST(i),na));
14154 if (option < 0)
14155 {
14156 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14157 SvPV(ST(i),na));
14158 return;
14159 }
14160 channel=(ChannelType) option;
14161 break;
14162 }
14163 if (LocaleCompare(attribute,"color") == 0)
14164 {
14165 if (SvTYPE(ST(i)) != SVt_RV)
14166 {
14167 char
cristy151b66d2015-04-15 10:50:31 +000014168 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014169
cristy151b66d2015-04-15 10:50:31 +000014170 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +000014171 "invalid %.60s value",attribute);
14172 ThrowPerlException(exception,OptionError,message,
14173 SvPV(ST(i),na));
14174 }
14175 av=(AV *) SvRV(ST(i));
14176 break;
14177 }
14178 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14179 attribute);
14180 break;
14181 }
14182 case 'g':
14183 case 'G':
14184 {
14185 if (LocaleCompare(attribute,"geometry") == 0)
14186 {
14187 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14188 break;
14189 }
14190 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14191 attribute);
14192 break;
14193 }
14194 case 'N':
14195 case 'n':
14196 {
14197 if (LocaleCompare(attribute,"normalize") == 0)
14198 {
14199 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14200 SvPV(ST(i),na));
14201 if (option < 0)
14202 {
14203 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14204 SvPV(ST(i),na));
14205 break;
14206 }
14207 normalize=option != 0 ? MagickTrue : MagickFalse;
14208 break;
14209 }
14210 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14211 attribute);
14212 break;
14213 }
14214 case 'x':
14215 case 'X':
14216 {
14217 if (LocaleCompare(attribute,"x") == 0)
14218 {
14219 region.x=SvIV(ST(i));
14220 break;
14221 }
14222 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14223 attribute);
14224 break;
14225 }
14226 case 'y':
14227 case 'Y':
14228 {
14229 if (LocaleCompare(attribute,"y") == 0)
14230 {
14231 region.y=SvIV(ST(i));
14232 break;
14233 }
14234 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14235 attribute);
14236 break;
14237 }
14238 default:
14239 {
14240 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14241 attribute);
14242 break;
14243 }
14244 }
14245 }
14246 (void) SetImageStorageClass(image,DirectClass,exception);
14247 channel_mask=SetImageChannelMask(image,channel);
14248 q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14249 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14250 (SvTYPE(av) != SVt_PVAV))
14251 PUSHs(&sv_undef);
14252 else
14253 {
14254 double
14255 scale;
14256
14257 register ssize_t
14258 i;
14259
14260 i=0;
14261 scale=1.0;
14262 if (normalize != MagickFalse)
14263 scale=QuantumRange;
14264 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14265 (i <= av_len(av)))
14266 {
14267 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14268 av_fetch(av,i,0)))),q);
14269 i++;
14270 }
14271 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14272 (i <= av_len(av)))
14273 {
14274 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14275 av_fetch(av,i,0)))),q);
14276 i++;
14277 }
14278 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14279 (i <= av_len(av)))
14280 {
14281 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14282 av_fetch(av,i,0)))),q);
14283 i++;
14284 }
14285 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14286 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14287 {
14288 SetPixelBlack(image,ClampToQuantum(scale*
14289 SvNV(*(av_fetch(av,i,0)))),q);
14290 i++;
14291 }
14292 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14293 (i <= av_len(av)))
14294 {
14295 SetPixelAlpha(image,ClampToQuantum(scale*
14296 SvNV(*(av_fetch(av,i,0)))),q);
14297 i++;
14298 }
14299 (void) SyncAuthenticPixels(image,exception);
14300 }
14301 (void) SetImageChannelMask(image,channel_mask);
14302
14303 PerlException:
14304 InheritPerlException(exception,perl_exception);
14305 exception=DestroyExceptionInfo(exception);
14306 SvREFCNT_dec(perl_exception);
14307 }
14308
14309#
14310###############################################################################
14311# #
14312# #
14313# #
Cristybba545b2018-07-04 15:00:12 -040014314# S e t P i x e l s #
14315# #
14316# #
14317# #
14318###############################################################################
14319#
14320#
14321void
14322SetPixels(ref,...)
14323 Image::Magick ref=NO_INIT
14324 ALIAS:
14325 setpixels = 1
14326 setPixels = 2
14327 PPCODE:
14328 {
14329 AV
14330 *av;
14331
14332 char
14333 *attribute;
14334
14335 ChannelType
14336 channel,
14337 channel_mask;
14338
14339 ExceptionInfo
14340 *exception;
14341
14342 Image
14343 *image;
14344
14345 RectangleInfo
14346 region;
14347
14348 register ssize_t
14349 i;
14350
14351 register Quantum
14352 *q;
14353
14354 struct PackageInfo
14355 *info;
14356
14357 SV
14358 *perl_exception,
14359 *reference; /* reference is the SV* of ref=SvIV(reference) */
14360
14361 PERL_UNUSED_VAR(ref);
14362 PERL_UNUSED_VAR(ix);
14363 exception=AcquireExceptionInfo();
14364 perl_exception=newSVpv("",0);
14365 reference=SvRV(ST(0));
14366 av=(AV *) reference;
14367 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14368 exception);
14369 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14370 if (image == (Image *) NULL)
14371 {
14372 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14373 PackageName);
14374 goto PerlException;
14375 }
14376 av=(AV *) NULL;
14377 region.x=0;
14378 region.y=0;
14379 region.width=image->columns;
14380 region.height=1;
14381 if (items == 1)
14382 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14383 channel=DefaultChannels;
14384 for (i=2; i < items; i+=2)
14385 {
14386 attribute=(char *) SvPV(ST(i-1),na);
14387 switch (*attribute)
14388 {
14389 case 'C':
14390 case 'c':
14391 {
14392 if (LocaleCompare(attribute,"channel") == 0)
14393 {
14394 ssize_t
14395 option;
14396
14397 option=ParseChannelOption(SvPV(ST(i),na));
14398 if (option < 0)
14399 {
14400 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14401 SvPV(ST(i),na));
14402 return;
14403 }
14404 channel=(ChannelType) option;
14405 break;
14406 }
14407 if (LocaleCompare(attribute,"color") == 0)
14408 {
14409 if (SvTYPE(ST(i)) != SVt_RV)
14410 {
14411 char
14412 message[MagickPathExtent];
14413
14414 (void) FormatLocaleString(message,MagickPathExtent,
14415 "invalid %.60s value",attribute);
14416 ThrowPerlException(exception,OptionError,message,
14417 SvPV(ST(i),na));
14418 }
14419 av=(AV *) SvRV(ST(i));
14420 break;
14421 }
14422 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14423 attribute);
14424 break;
14425 }
14426 case 'g':
14427 case 'G':
14428 {
14429 if (LocaleCompare(attribute,"geometry") == 0)
14430 {
14431 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14432 break;
14433 }
14434 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14435 attribute);
14436 break;
14437 }
14438 case 'h':
14439 case 'H':
14440 {
14441 if (LocaleCompare(attribute,"height") == 0)
14442 {
14443 region.height=SvIV(ST(i));
14444 break;
14445 }
14446 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14447 attribute);
14448 break;
14449 }
14450 case 'w':
14451 case 'W':
14452 {
14453 if (LocaleCompare(attribute,"width") == 0)
14454 {
14455 region.width=SvIV(ST(i));
14456 break;
14457 }
14458 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14459 attribute);
14460 break;
14461 }
14462 case 'x':
14463 case 'X':
14464 {
14465 if (LocaleCompare(attribute,"x") == 0)
14466 {
14467 region.x=SvIV(ST(i));
14468 break;
14469 }
14470 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14471 attribute);
14472 break;
14473 }
14474 case 'y':
14475 case 'Y':
14476 {
14477 if (LocaleCompare(attribute,"y") == 0)
14478 {
14479 region.y=SvIV(ST(i));
14480 break;
14481 }
14482 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14483 attribute);
14484 break;
14485 }
14486 default:
14487 {
14488 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14489 attribute);
14490 break;
14491 }
14492 }
14493 }
14494 (void) SetImageStorageClass(image,DirectClass,exception);
14495 channel_mask=SetImageChannelMask(image,channel);
14496 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
14497 exception);
14498 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14499 (SvTYPE(av) != SVt_PVAV))
14500 PUSHs(&sv_undef);
14501 else
14502 {
14503 double
14504 scale;
14505
14506 register ssize_t
14507 i,
14508 n,
14509 number_pixels;
14510
14511 i=0;
14512 n=0;
14513 scale=(double) QuantumRange;
14514 number_pixels=region.width*region.height;
14515 while ((n < number_pixels) && (i < av_len(av)))
14516 {
14517 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14518 (i <= av_len(av)))
14519 {
14520 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14521 av_fetch(av,i,0)))),q);
14522 i++;
14523 }
14524 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14525 (i <= av_len(av)))
14526 {
14527 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14528 av_fetch(av,i,0)))),q);
14529 i++;
14530 }
14531 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14532 (i <= av_len(av)))
14533 {
14534 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14535 av_fetch(av,i,0)))),q);
14536 i++;
14537 }
14538 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14539 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14540 {
14541 SetPixelBlack(image,ClampToQuantum(scale*
14542 SvNV(*(av_fetch(av,i,0)))),q);
14543 i++;
14544 }
14545 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14546 (i <= av_len(av)))
14547 {
14548 SetPixelAlpha(image,ClampToQuantum(scale*
14549 SvNV(*(av_fetch(av,i,0)))),q);
14550 i++;
14551 }
14552 n++;
14553 q+=image->number_channels;
14554 }
14555 (void) SyncAuthenticPixels(image,exception);
14556 }
14557 (void) SetImageChannelMask(image,channel_mask);
14558
14559 PerlException:
14560 InheritPerlException(exception,perl_exception);
14561 exception=DestroyExceptionInfo(exception);
14562 SvREFCNT_dec(perl_exception);
14563 }
14564
14565#
14566###############################################################################
14567# #
14568# #
14569# #
cristy4a3ce0a2013-08-03 20:06:59 +000014570# S m u s h #
14571# #
14572# #
14573# #
14574###############################################################################
14575#
14576#
14577void
14578Smush(ref,...)
14579 Image::Magick ref=NO_INIT
14580 ALIAS:
14581 SmushImage = 1
14582 smush = 2
14583 smushimage = 3
14584 PPCODE:
14585 {
14586 AV
14587 *av;
14588
14589 char
14590 *attribute;
14591
14592 ExceptionInfo
14593 *exception;
14594
14595 HV
14596 *hv;
14597
14598 Image
14599 *image;
14600
14601 register ssize_t
14602 i;
14603
14604 ssize_t
14605 offset,
14606 stack;
14607
14608 struct PackageInfo
14609 *info;
14610
14611 SV
14612 *av_reference,
14613 *perl_exception,
14614 *reference,
14615 *rv,
14616 *sv;
14617
14618 PERL_UNUSED_VAR(ref);
14619 PERL_UNUSED_VAR(ix);
14620 exception=AcquireExceptionInfo();
14621 perl_exception=newSVpv("",0);
14622 sv=NULL;
14623 attribute=NULL;
14624 av=NULL;
14625 if (sv_isobject(ST(0)) == 0)
14626 {
14627 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14628 PackageName);
14629 goto PerlException;
14630 }
14631 reference=SvRV(ST(0));
14632 hv=SvSTASH(reference);
14633 av=newAV();
14634 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14635 SvREFCNT_dec(av);
14636 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14637 if (image == (Image *) NULL)
14638 {
14639 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14640 PackageName);
14641 goto PerlException;
14642 }
14643 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14644 /*
14645 Get options.
14646 */
14647 offset=0;
14648 stack=MagickTrue;
14649 for (i=2; i < items; i+=2)
14650 {
14651 attribute=(char *) SvPV(ST(i-1),na);
14652 switch (*attribute)
14653 {
14654 case 'O':
14655 case 'o':
14656 {
14657 if (LocaleCompare(attribute,"offset") == 0)
14658 {
14659 offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14660 break;
14661 }
14662 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14663 attribute);
14664 break;
14665 }
14666 case 'S':
14667 case 's':
14668 {
14669 if (LocaleCompare(attribute,"stack") == 0)
14670 {
14671 stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14672 SvPV(ST(i),na));
14673 if (stack < 0)
14674 {
14675 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14676 SvPV(ST(i),na));
14677 return;
14678 }
14679 break;
14680 }
14681 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14682 attribute);
14683 break;
14684 }
14685 default:
14686 {
14687 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14688 attribute);
14689 break;
14690 }
14691 }
14692 }
14693 image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14694 exception);
14695 if (image == (Image *) NULL)
14696 goto PerlException;
14697 for ( ; image; image=image->next)
14698 {
14699 AddImageToRegistry(sv,image);
14700 rv=newRV(sv);
14701 av_push(av,sv_bless(rv,hv));
14702 SvREFCNT_dec(sv);
14703 }
14704 exception=DestroyExceptionInfo(exception);
14705 ST(0)=av_reference;
14706 SvREFCNT_dec(perl_exception);
14707 XSRETURN(1);
14708
14709 PerlException:
14710 InheritPerlException(exception,perl_exception);
14711 exception=DestroyExceptionInfo(exception);
14712 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14713 SvPOK_on(perl_exception);
14714 ST(0)=sv_2mortal(perl_exception);
14715 XSRETURN(1);
14716 }
14717
14718#
14719###############################################################################
14720# #
14721# #
14722# #
14723# S t a t i s t i c s #
14724# #
14725# #
14726# #
14727###############################################################################
14728#
14729#
14730void
14731Statistics(ref,...)
14732 Image::Magick ref=NO_INIT
14733 ALIAS:
14734 StatisticsImage = 1
14735 statistics = 2
14736 statisticsimage = 3
14737 PPCODE:
14738 {
14739#define ChannelStatistics(channel) \
14740{ \
cristy151b66d2015-04-15 10:50:31 +000014741 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014742 (double) channel_statistics[channel].depth); \
14743 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014744 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014745 channel_statistics[channel].minima/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014746 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014747 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014748 channel_statistics[channel].maxima/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014749 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014750 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014751 channel_statistics[channel].mean/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014752 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014753 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014754 channel_statistics[channel].standard_deviation/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014755 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014756 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014757 channel_statistics[channel].kurtosis); \
14758 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014759 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014760 channel_statistics[channel].skewness); \
14761 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014762 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy275bdd92014-11-08 23:45:03 +000014763 channel_statistics[channel].entropy); \
14764 PUSHs(sv_2mortal(newSVpv(message,0))); \
cristy4a3ce0a2013-08-03 20:06:59 +000014765}
14766
14767 AV
14768 *av;
14769
14770 char
cristy151b66d2015-04-15 10:50:31 +000014771 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014772
14773 ChannelStatistics
14774 *channel_statistics;
14775
cristy4a3ce0a2013-08-03 20:06:59 +000014776 ExceptionInfo
14777 *exception;
14778
14779 Image
14780 *image;
14781
14782 ssize_t
14783 count;
14784
14785 struct PackageInfo
14786 *info;
14787
14788 SV
14789 *perl_exception,
14790 *reference;
14791
14792 PERL_UNUSED_VAR(ref);
14793 PERL_UNUSED_VAR(ix);
14794 exception=AcquireExceptionInfo();
14795 perl_exception=newSVpv("",0);
14796 av=NULL;
14797 if (sv_isobject(ST(0)) == 0)
14798 {
14799 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14800 PackageName);
14801 goto PerlException;
14802 }
14803 reference=SvRV(ST(0));
14804 av=newAV();
14805 SvREFCNT_dec(av);
14806 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14807 if (image == (Image *) NULL)
14808 {
14809 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14810 PackageName);
14811 goto PerlException;
14812 }
cristy4a3ce0a2013-08-03 20:06:59 +000014813 count=0;
14814 for ( ; image; image=image->next)
14815 {
Cristyb1710fe2017-02-11 13:51:48 -050014816 register size_t
14817 i;
14818
cristy4a3ce0a2013-08-03 20:06:59 +000014819 channel_statistics=GetImageStatistics(image,exception);
14820 if (channel_statistics == (ChannelStatistics *) NULL)
14821 continue;
14822 count++;
Cristyb1710fe2017-02-11 13:51:48 -050014823 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
14824 {
14825 PixelChannel channel=GetPixelChannelChannel(image,i);
14826 PixelTrait traits=GetPixelChannelTraits(image,channel);
Cristy5a854dc2017-02-11 15:43:46 -050014827 if (traits == UndefinedPixelTrait)
Cristyb1710fe2017-02-11 13:51:48 -050014828 continue;
Cristy5a854dc2017-02-11 15:43:46 -050014829 EXTEND(sp,8*(i+1)*count);
Cristyb1710fe2017-02-11 13:51:48 -050014830 ChannelStatistics(channel);
14831 }
Cristy25813902017-02-11 15:47:52 -050014832 EXTEND(sp,8*(i+1)*count);
14833 ChannelStatistics(CompositePixelChannel);
cristy4a3ce0a2013-08-03 20:06:59 +000014834 channel_statistics=(ChannelStatistics *)
14835 RelinquishMagickMemory(channel_statistics);
14836 }
14837
14838 PerlException:
14839 InheritPerlException(exception,perl_exception);
14840 exception=DestroyExceptionInfo(exception);
14841 SvREFCNT_dec(perl_exception);
14842 }
14843
14844#
14845###############################################################################
14846# #
14847# #
14848# #
14849# S y n c A u t h e n t i c P i x e l s #
14850# #
14851# #
14852# #
14853###############################################################################
14854#
14855#
14856void
14857SyncAuthenticPixels(ref,...)
14858 Image::Magick ref = NO_INIT
14859 ALIAS:
14860 Syncauthenticpixels = 1
14861 SyncImagePixels = 2
14862 syncimagepixels = 3
14863 CODE:
14864 {
14865 ExceptionInfo
14866 *exception;
14867
14868 Image
14869 *image;
14870
14871 MagickBooleanType
14872 status;
14873
14874 struct PackageInfo
14875 *info;
14876
14877 SV
14878 *perl_exception,
14879 *reference;
14880
14881 PERL_UNUSED_VAR(ref);
14882 PERL_UNUSED_VAR(ix);
14883 exception=AcquireExceptionInfo();
14884 perl_exception=newSVpv("",0);
14885 if (sv_isobject(ST(0)) == 0)
14886 {
14887 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14888 PackageName);
14889 goto PerlException;
14890 }
14891
14892 reference=SvRV(ST(0));
14893 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14894 if (image == (Image *) NULL)
14895 {
14896 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14897 PackageName);
14898 goto PerlException;
14899 }
14900
14901 status=SyncAuthenticPixels(image,exception);
14902 if (status != MagickFalse)
14903 return;
14904
14905 PerlException:
14906 InheritPerlException(exception,perl_exception);
14907 exception=DestroyExceptionInfo(exception);
14908 SvREFCNT_dec(perl_exception); /* throw away all errors */
14909 }
14910
14911#
14912###############################################################################
14913# #
14914# #
14915# #
cristy4a3ce0a2013-08-03 20:06:59 +000014916# W r i t e #
14917# #
14918# #
14919# #
14920###############################################################################
14921#
14922#
14923void
14924Write(ref,...)
14925 Image::Magick ref=NO_INIT
14926 ALIAS:
14927 WriteImage = 1
14928 write = 2
14929 writeimage = 3
14930 PPCODE:
14931 {
14932 char
cristy151b66d2015-04-15 10:50:31 +000014933 filename[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014934
14935 ExceptionInfo
14936 *exception;
14937
14938 Image
14939 *image,
14940 *next;
14941
14942 register ssize_t
14943 i;
14944
14945 ssize_t
14946 number_images,
14947 scene;
14948
14949 struct PackageInfo
14950 *info,
14951 *package_info;
14952
14953 SV
14954 *perl_exception,
14955 *reference;
14956
14957 PERL_UNUSED_VAR(ref);
14958 PERL_UNUSED_VAR(ix);
14959 exception=AcquireExceptionInfo();
14960 perl_exception=newSVpv("",0);
14961 number_images=0;
14962 package_info=(struct PackageInfo *) NULL;
14963 if (sv_isobject(ST(0)) == 0)
14964 {
14965 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14966 PackageName);
14967 goto PerlException;
14968 }
14969 reference=SvRV(ST(0));
14970 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14971 if (image == (Image *) NULL)
14972 {
14973 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14974 PackageName);
14975 goto PerlException;
14976 }
Cristyb4ee45c2017-09-27 17:58:55 -040014977 scene=0;
14978 for (next=image; next; next=next->next)
14979 next->scene=scene++;
cristy4a3ce0a2013-08-03 20:06:59 +000014980 package_info=ClonePackageInfo(info,exception);
14981 if (items == 2)
14982 SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14983 else
14984 if (items > 2)
14985 for (i=2; i < items; i+=2)
14986 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14987 exception);
14988 (void) CopyMagickString(filename,package_info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +000014989 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000014990 for (next=image; next; next=next->next)
cristy151b66d2015-04-15 10:50:31 +000014991 (void) CopyMagickString(next->filename,filename,MagickPathExtent);
cristy68bd79a2015-02-25 12:23:36 +000014992 *package_info->image_info->magick='\0';
cristy4a3ce0a2013-08-03 20:06:59 +000014993 SetImageInfo(package_info->image_info,(unsigned int)
14994 GetImageListLength(image),exception);
14995 for (next=image; next; next=next->next)
14996 {
14997 (void) WriteImage(package_info->image_info,next,exception);
14998 number_images++;
14999 if (package_info->image_info->adjoin)
15000 break;
15001 }
15002
15003 PerlException:
15004 if (package_info != (struct PackageInfo *) NULL)
15005 DestroyPackageInfo(package_info);
15006 InheritPerlException(exception,perl_exception);
15007 exception=DestroyExceptionInfo(exception);
15008 sv_setiv(perl_exception,(IV) number_images);
15009 SvPOK_on(perl_exception);
15010 ST(0)=sv_2mortal(perl_exception);
15011 XSRETURN(1);
15012 }