blob: 7013528725ec69be0c889a0c6b64cfa256fb3485 [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},
443 {"unique", MagickBooleanOptions} } },
444 { "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} } },
cristy4a3ce0a2013-08-03 20:06:59 +0000578 };
579
580static SplayTreeInfo
581 *magick_registry = (SplayTreeInfo *) NULL;
582
583/*
584 Forward declarations.
585*/
586static Image
587 *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
588
589static ssize_t
590 strEQcase(const char *,const char *);
591
592/*
593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594% %
595% %
596% %
597% C l o n e P a c k a g e I n f o %
598% %
599% %
600% %
601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602%
603% ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
604% a new one.
605%
606% The format of the ClonePackageInfo routine is:
607%
608% struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
609% exception)
610%
611% A description of each parameter follows:
612%
613% o info: a structure of type info.
614%
615% o exception: Return any errors or warnings in this structure.
616%
617*/
618static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
619 ExceptionInfo *exception)
620{
621 struct PackageInfo
622 *clone_info;
623
624 clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
625 if (clone_info == (struct PackageInfo *) NULL)
626 {
627 ThrowPerlException(exception,ResourceLimitError,
628 "UnableToClonePackageInfo",PackageName);
629 return((struct PackageInfo *) NULL);
630 }
631 if (info == (struct PackageInfo *) NULL)
632 {
633 clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
634 return(clone_info);
635 }
636 *clone_info=(*info);
637 clone_info->image_info=CloneImageInfo(info->image_info);
638 return(clone_info);
639}
640
641/*
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643% %
644% %
645% %
646% c o n s t a n t %
647% %
648% %
649% %
650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651%
652% constant() returns a double value for the specified name.
653%
654% The format of the constant routine is:
655%
656% double constant(char *name,ssize_t sans)
657%
658% A description of each parameter follows:
659%
660% o value: Method constant returns a double value for the specified name.
661%
662% o name: The name of the constant.
663%
664% o sans: This integer value is not used.
665%
666*/
667static double constant(char *name,ssize_t sans)
668{
669 (void) sans;
670 errno=0;
671 switch (*name)
672 {
673 case 'B':
674 {
675 if (strEQ(name,"BlobError"))
676 return(BlobError);
677 if (strEQ(name,"BlobWarning"))
678 return(BlobWarning);
679 break;
680 }
681 case 'C':
682 {
683 if (strEQ(name,"CacheError"))
684 return(CacheError);
685 if (strEQ(name,"CacheWarning"))
686 return(CacheWarning);
687 if (strEQ(name,"CoderError"))
688 return(CoderError);
689 if (strEQ(name,"CoderWarning"))
690 return(CoderWarning);
691 if (strEQ(name,"ConfigureError"))
692 return(ConfigureError);
693 if (strEQ(name,"ConfigureWarning"))
694 return(ConfigureWarning);
695 if (strEQ(name,"CorruptImageError"))
696 return(CorruptImageError);
697 if (strEQ(name,"CorruptImageWarning"))
698 return(CorruptImageWarning);
699 break;
700 }
701 case 'D':
702 {
703 if (strEQ(name,"DelegateError"))
704 return(DelegateError);
705 if (strEQ(name,"DelegateWarning"))
706 return(DelegateWarning);
707 if (strEQ(name,"DrawError"))
708 return(DrawError);
709 if (strEQ(name,"DrawWarning"))
710 return(DrawWarning);
711 break;
712 }
713 case 'E':
714 {
715 if (strEQ(name,"ErrorException"))
716 return(ErrorException);
717 if (strEQ(name,"ExceptionError"))
718 return(CoderError);
719 if (strEQ(name,"ExceptionWarning"))
720 return(CoderWarning);
721 break;
722 }
723 case 'F':
724 {
725 if (strEQ(name,"FatalErrorException"))
726 return(FatalErrorException);
727 if (strEQ(name,"FileOpenError"))
728 return(FileOpenError);
729 if (strEQ(name,"FileOpenWarning"))
730 return(FileOpenWarning);
731 break;
732 }
733 case 'I':
734 {
735 if (strEQ(name,"ImageError"))
736 return(ImageError);
737 if (strEQ(name,"ImageWarning"))
738 return(ImageWarning);
739 break;
740 }
741 case 'M':
742 {
743 if (strEQ(name,"MaxRGB"))
744 return(QuantumRange);
745 if (strEQ(name,"MissingDelegateError"))
746 return(MissingDelegateError);
747 if (strEQ(name,"MissingDelegateWarning"))
748 return(MissingDelegateWarning);
749 if (strEQ(name,"ModuleError"))
750 return(ModuleError);
751 if (strEQ(name,"ModuleWarning"))
752 return(ModuleWarning);
753 break;
754 }
755 case 'O':
756 {
757 if (strEQ(name,"Opaque"))
758 return(OpaqueAlpha);
759 if (strEQ(name,"OptionError"))
760 return(OptionError);
761 if (strEQ(name,"OptionWarning"))
762 return(OptionWarning);
763 break;
764 }
765 case 'Q':
766 {
767 if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
768 return(MAGICKCORE_QUANTUM_DEPTH);
769 if (strEQ(name,"QuantumDepth"))
770 return(MAGICKCORE_QUANTUM_DEPTH);
771 if (strEQ(name,"QuantumRange"))
772 return(QuantumRange);
773 break;
774 }
775 case 'R':
776 {
777 if (strEQ(name,"ResourceLimitError"))
778 return(ResourceLimitError);
779 if (strEQ(name,"ResourceLimitWarning"))
780 return(ResourceLimitWarning);
781 if (strEQ(name,"RegistryError"))
782 return(RegistryError);
783 if (strEQ(name,"RegistryWarning"))
784 return(RegistryWarning);
785 break;
786 }
787 case 'S':
788 {
789 if (strEQ(name,"StreamError"))
790 return(StreamError);
791 if (strEQ(name,"StreamWarning"))
792 return(StreamWarning);
793 if (strEQ(name,"Success"))
794 return(0);
795 break;
796 }
797 case 'T':
798 {
799 if (strEQ(name,"Transparent"))
800 return(TransparentAlpha);
801 if (strEQ(name,"TypeError"))
802 return(TypeError);
803 if (strEQ(name,"TypeWarning"))
804 return(TypeWarning);
805 break;
806 }
807 case 'W':
808 {
809 if (strEQ(name,"WarningException"))
810 return(WarningException);
811 break;
812 }
813 case 'X':
814 {
815 if (strEQ(name,"XServerError"))
816 return(XServerError);
817 if (strEQ(name,"XServerWarning"))
818 return(XServerWarning);
819 break;
820 }
821 }
822 errno=EINVAL;
823 return(0);
824}
825
826/*
827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828% %
829% %
830% %
831% D e s t r o y P a c k a g e I n f o %
832% %
833% %
834% %
835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
836%
837% Method DestroyPackageInfo frees a previously created info structure.
838%
839% The format of the DestroyPackageInfo routine is:
840%
841% DestroyPackageInfo(struct PackageInfo *info)
842%
843% A description of each parameter follows:
844%
845% o info: a structure of type info.
846%
847*/
848static void DestroyPackageInfo(struct PackageInfo *info)
849{
850 info->image_info=DestroyImageInfo(info->image_info);
851 info=(struct PackageInfo *) RelinquishMagickMemory(info);
852}
853
854/*
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856% %
857% %
858% %
859% G e t L i s t %
860% %
861% %
862% %
863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864%
865% Method GetList is recursively called by SetupList to traverse the
866% Image__Magick reference. If building an reference_vector (see SetupList),
867% *current is the current position in *reference_vector and *last is the final
868% entry in *reference_vector.
869%
870% The format of the GetList routine is:
871%
872% GetList(info)
873%
874% A description of each parameter follows:
875%
876% o info: a structure of type info.
877%
878*/
879static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
880 ssize_t *current,ssize_t *last,ExceptionInfo *exception)
881{
882 Image
883 *image;
884
885 if (reference == (SV *) NULL)
886 return(NULL);
887 switch (SvTYPE(reference))
888 {
889 case SVt_PVAV:
890 {
891 AV
892 *av;
893
894 Image
895 *head,
896 *previous;
897
898 register ssize_t
899 i;
900
901 ssize_t
902 n;
903
904 /*
905 Array of images.
906 */
907 previous=(Image *) NULL;
908 head=(Image *) NULL;
909 av=(AV *) reference;
910 n=av_len(av);
911 for (i=0; i <= n; i++)
912 {
913 SV
914 **rv;
915
916 rv=av_fetch(av,i,0);
917 if (rv && *rv && sv_isobject(*rv))
918 {
919 image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
920 exception);
921 if (image == (Image *) NULL)
922 continue;
923 if (image == previous)
924 {
925 image=CloneImage(image,0,0,MagickTrue,exception);
926 if (image == (Image *) NULL)
927 return(NULL);
928 }
929 image->previous=previous;
930 *(previous ? &previous->next : &head)=image;
931 for (previous=image; previous->next; previous=previous->next) ;
932 }
933 }
934 return(head);
935 }
936 case SVt_PVMG:
937 {
938 /*
939 Blessed scalar, one image.
940 */
941 image=INT2PTR(Image *,SvIV(reference));
942 if (image == (Image *) NULL)
943 return(NULL);
944 image->previous=(Image *) NULL;
945 image->next=(Image *) NULL;
946 if (reference_vector)
947 {
948 if (*current == *last)
949 {
950 *last+=256;
951 if (*reference_vector == (SV **) NULL)
952 *reference_vector=(SV **) AcquireQuantumMemory(*last,
953 sizeof(*reference_vector));
954 else
955 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
956 *last,sizeof(*reference_vector));
957 }
958 if (*reference_vector == (SV **) NULL)
959 {
960 ThrowPerlException(exception,ResourceLimitError,
961 "MemoryAllocationFailed",PackageName);
962 return((Image *) NULL);
963 }
964 (*reference_vector)[*current]=reference;
965 (*reference_vector)[++(*current)]=NULL;
966 }
967 return(image);
968 }
969 default:
970 break;
971 }
972 (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
973 (double) SvTYPE(reference));
974 return((Image *) NULL);
975}
976
977/*
978%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979% %
980% %
981% %
982% G e t P a c k a g e I n f o %
983% %
984% %
985% %
986%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
987%
988% Method GetPackageInfo looks up or creates an info structure for the given
989% Image__Magick reference. If it does create a new one, the information in
990% package_info is used to initialize it.
991%
992% The format of the GetPackageInfo routine is:
993%
994% struct PackageInfo *GetPackageInfo(void *reference,
995% struct PackageInfo *package_info,ExceptionInfo *exception)
996%
997% A description of each parameter follows:
998%
999% o info: a structure of type info.
1000%
1001% o exception: Return any errors or warnings in this structure.
1002%
1003*/
1004static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
1005 struct PackageInfo *package_info,ExceptionInfo *exception)
1006{
1007 char
cristy151b66d2015-04-15 10:50:31 +00001008 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00001009
1010 struct PackageInfo
1011 *clone_info;
1012
1013 SV
1014 *sv;
1015
cristy151b66d2015-04-15 10:50:31 +00001016 (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
cristy4a3ce0a2013-08-03 20:06:59 +00001017 PackageName,XS_VERSION,reference);
1018 sv=perl_get_sv(message,(TRUE | 0x02));
1019 if (sv == (SV *) NULL)
1020 {
1021 ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1022 message);
1023 return(package_info);
1024 }
1025 if (SvREFCNT(sv) == 0)
1026 (void) SvREFCNT_inc(sv);
1027 if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1028 return(clone_info);
1029 clone_info=ClonePackageInfo(package_info,exception);
1030 sv_setiv(sv,PTR2IV(clone_info));
1031 return(clone_info);
1032}
1033
1034/*
1035%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1036% %
1037% %
1038% %
1039% S e t A t t r i b u t e %
1040% %
1041% %
1042% %
1043%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1044%
1045% SetAttribute() sets the attribute to the value in sval. This can change
1046% either or both of image or info.
1047%
1048% The format of the SetAttribute routine is:
1049%
1050% SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1051% SV *sval,ExceptionInfo *exception)
1052%
1053% A description of each parameter follows:
1054%
1055% o list: a list of strings.
1056%
1057% o string: a character string.
1058%
1059*/
1060
1061static double SiPrefixToDoubleInterval(const char *string,const double interval)
1062{
1063 char
1064 *q;
1065
1066 double
1067 value;
1068
1069 value=InterpretSiPrefixValue(string,&q);
1070 if (*q == '%')
1071 value*=interval/100.0;
1072 return(value);
1073}
1074
1075static inline double StringToDouble(const char *string,char **sentinal)
1076{
1077 return(InterpretLocaleValue(string,sentinal));
1078}
1079
1080static double StringToDoubleInterval(const char *string,const double interval)
1081{
1082 char
1083 *q;
1084
1085 double
1086 value;
1087
1088 value=InterpretLocaleValue(string,&q);
1089 if (*q == '%')
1090 value*=interval/100.0;
1091 return(value);
1092}
1093
1094static inline ssize_t StringToLong(const char *value)
1095{
1096 return(strtol(value,(char **) NULL,10));
1097}
1098
1099static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1100 const char *attribute,SV *sval,ExceptionInfo *exception)
1101{
1102 GeometryInfo
1103 geometry_info;
1104
1105 long
1106 x,
1107 y;
1108
1109 PixelInfo
1110 pixel;
1111
1112 MagickStatusType
1113 flags;
1114
1115 PixelInfo
1116 *color,
1117 target_color;
1118
1119 ssize_t
1120 sp;
1121
1122 switch (*attribute)
1123 {
1124 case 'A':
1125 case 'a':
1126 {
1127 if (LocaleCompare(attribute,"adjoin") == 0)
1128 {
1129 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1130 SvPV(sval,na)) : SvIV(sval);
1131 if (sp < 0)
1132 {
1133 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1134 SvPV(sval,na));
1135 break;
1136 }
1137 if (info)
1138 info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1139 break;
1140 }
1141 if (LocaleCompare(attribute,"alpha") == 0)
1142 {
1143 sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1144 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1145 if (sp < 0)
1146 {
1147 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1148 SvPV(sval,na));
1149 break;
1150 }
1151 for ( ; image; image=image->next)
1152 (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1153 exception);
1154 break;
1155 }
1156 if (LocaleCompare(attribute,"antialias") == 0)
1157 {
1158 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1159 SvPV(sval,na)) : SvIV(sval);
1160 if (sp < 0)
1161 {
1162 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1163 SvPV(sval,na));
1164 break;
1165 }
1166 if (info)
1167 info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1168 break;
1169 }
1170 if (LocaleCompare(attribute,"area-limit") == 0)
1171 {
1172 MagickSizeType
1173 limit;
1174
1175 limit=MagickResourceInfinity;
1176 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1177 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1178 100.0);
1179 (void) SetMagickResourceLimit(AreaResource,limit);
1180 break;
1181 }
1182 if (LocaleCompare(attribute,"attenuate") == 0)
1183 {
1184 if (info)
1185 (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1186 break;
1187 }
1188 if (LocaleCompare(attribute,"authenticate") == 0)
1189 {
1190 if (info)
1191 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1192 break;
1193 }
1194 if (info)
1195 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1196 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001197 {
1198 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstra337c9bc2017-04-03 16:04:21 +02001199 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001200 }
cristy4a3ce0a2013-08-03 20:06:59 +00001201 break;
1202 }
1203 case 'B':
1204 case 'b':
1205 {
1206 if (LocaleCompare(attribute,"background") == 0)
1207 {
1208 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1209 exception);
1210 if (info)
1211 info->image_info->background_color=target_color;
1212 for ( ; image; image=image->next)
1213 image->background_color=target_color;
1214 break;
1215 }
1216 if (LocaleCompare(attribute,"blue-primary") == 0)
1217 {
1218 for ( ; image; image=image->next)
1219 {
1220 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1221 image->chromaticity.blue_primary.x=geometry_info.rho;
1222 image->chromaticity.blue_primary.y=geometry_info.sigma;
1223 if ((flags & SigmaValue) == 0)
1224 image->chromaticity.blue_primary.y=
1225 image->chromaticity.blue_primary.x;
1226 }
1227 break;
1228 }
1229 if (LocaleCompare(attribute,"bordercolor") == 0)
1230 {
1231 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1232 exception);
1233 if (info)
1234 info->image_info->border_color=target_color;
1235 for ( ; image; image=image->next)
1236 image->border_color=target_color;
1237 break;
1238 }
1239 if (info)
1240 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1241 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001242 {
1243 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001244 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001245 }
cristy4a3ce0a2013-08-03 20:06:59 +00001246 break;
1247 }
1248 case 'C':
1249 case 'c':
1250 {
1251 if (LocaleCompare(attribute,"cache-threshold") == 0)
1252 {
1253 (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1254 SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1255 (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1256 (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1257 break;
1258 }
1259 if (LocaleCompare(attribute,"clip-mask") == 0)
1260 {
1261 Image
1262 *clip_mask;
1263
1264 clip_mask=(Image *) NULL;
1265 if (SvPOK(sval))
1266 clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1267 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001268 SetImageMask(image,ReadPixelMask,clip_mask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001269 break;
1270 }
1271 if (LocaleNCompare(attribute,"colormap",8) == 0)
1272 {
1273 for ( ; image; image=image->next)
1274 {
1275 int
1276 items;
1277
1278 long
1279 i;
1280
1281 if (image->storage_class == DirectClass)
1282 continue;
1283 i=0;
1284 items=sscanf(attribute,"%*[^[][%ld",&i);
1285 (void) items;
1286 if (i > (ssize_t) image->colors)
1287 i%=image->colors;
1288 if ((strchr(SvPV(sval,na),',') == 0) ||
1289 (strchr(SvPV(sval,na),')') != 0))
1290 QueryColorCompliance(SvPV(sval,na),AllCompliance,
1291 image->colormap+i,exception);
1292 else
1293 {
1294 color=image->colormap+i;
1295 pixel.red=color->red;
1296 pixel.green=color->green;
1297 pixel.blue=color->blue;
1298 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1299 pixel.red=geometry_info.rho;
1300 pixel.green=geometry_info.sigma;
1301 pixel.blue=geometry_info.xi;
1302 color->red=ClampToQuantum(pixel.red);
1303 color->green=ClampToQuantum(pixel.green);
1304 color->blue=ClampToQuantum(pixel.blue);
1305 }
1306 }
1307 break;
1308 }
1309 if (LocaleCompare(attribute,"colorspace") == 0)
1310 {
1311 sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1312 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1313 if (sp < 0)
1314 {
1315 ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1316 SvPV(sval,na));
1317 break;
1318 }
1319 for ( ; image; image=image->next)
Cristy59262d92016-12-05 15:21:50 -05001320 (void) SetImageColorspace(image,(ColorspaceType) sp,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001321 break;
1322 }
1323 if (LocaleCompare(attribute,"comment") == 0)
1324 {
1325 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001326 (void) SetImageProperty(image,"Comment",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00001327 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04001328 SvPV(sval,na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001329 break;
1330 }
1331 if (LocaleCompare(attribute,"compression") == 0)
1332 {
1333 sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1334 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1335 if (sp < 0)
1336 {
1337 ThrowPerlException(exception,OptionError,
1338 "UnrecognizedImageCompression",SvPV(sval,na));
1339 break;
1340 }
1341 if (info)
1342 info->image_info->compression=(CompressionType) sp;
1343 for ( ; image; image=image->next)
1344 image->compression=(CompressionType) sp;
1345 break;
1346 }
1347 if (info)
1348 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1349 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001350 {
1351 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001352 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001353 }
cristy4a3ce0a2013-08-03 20:06:59 +00001354 break;
1355 }
1356 case 'D':
1357 case 'd':
1358 {
1359 if (LocaleCompare(attribute,"debug") == 0)
1360 {
1361 SetLogEventMask(SvPV(sval,na));
1362 break;
1363 }
1364 if (LocaleCompare(attribute,"delay") == 0)
1365 {
1366 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1367 for ( ; image; image=image->next)
1368 {
1369 image->delay=(size_t) floor(geometry_info.rho+0.5);
1370 if ((flags & SigmaValue) != 0)
1371 image->ticks_per_second=(ssize_t)
1372 floor(geometry_info.sigma+0.5);
1373 }
1374 break;
1375 }
1376 if (LocaleCompare(attribute,"disk-limit") == 0)
1377 {
1378 MagickSizeType
1379 limit;
1380
1381 limit=MagickResourceInfinity;
1382 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1383 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1384 100.0);
1385 (void) SetMagickResourceLimit(DiskResource,limit);
1386 break;
1387 }
1388 if (LocaleCompare(attribute,"density") == 0)
1389 {
1390 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1391 {
1392 ThrowPerlException(exception,OptionError,"MissingGeometry",
1393 SvPV(sval,na));
1394 break;
1395 }
1396 if (info)
1397 (void) CloneString(&info->image_info->density,SvPV(sval,na));
1398 for ( ; image; image=image->next)
1399 {
1400 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1401 image->resolution.x=geometry_info.rho;
1402 image->resolution.y=geometry_info.sigma;
1403 if ((flags & SigmaValue) == 0)
1404 image->resolution.y=image->resolution.x;
1405 }
1406 break;
1407 }
1408 if (LocaleCompare(attribute,"depth") == 0)
1409 {
1410 if (info)
1411 info->image_info->depth=SvIV(sval);
1412 for ( ; image; image=image->next)
1413 (void) SetImageDepth(image,SvIV(sval),exception);
1414 break;
1415 }
1416 if (LocaleCompare(attribute,"dispose") == 0)
1417 {
1418 sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1419 SvPV(sval,na)) : SvIV(sval);
1420 if (sp < 0)
1421 {
1422 ThrowPerlException(exception,OptionError,
1423 "UnrecognizedDisposeMethod",SvPV(sval,na));
1424 break;
1425 }
1426 for ( ; image; image=image->next)
1427 image->dispose=(DisposeType) sp;
1428 break;
1429 }
1430 if (LocaleCompare(attribute,"dither") == 0)
1431 {
1432 if (info)
1433 {
1434 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1435 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1436 if (sp < 0)
1437 {
1438 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1439 SvPV(sval,na));
1440 break;
1441 }
1442 info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1443 }
1444 break;
1445 }
1446 if (LocaleCompare(attribute,"display") == 0)
1447 {
1448 display:
1449 if (info)
1450 (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1451 break;
1452 }
1453 if (info)
1454 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1455 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001456 {
1457 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001458 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001459 }
cristy4a3ce0a2013-08-03 20:06:59 +00001460 break;
1461 }
1462 case 'E':
1463 case 'e':
1464 {
1465 if (LocaleCompare(attribute,"endian") == 0)
1466 {
1467 sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1468 SvPV(sval,na)) : SvIV(sval);
1469 if (sp < 0)
1470 {
1471 ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1472 SvPV(sval,na));
1473 break;
1474 }
1475 if (info)
1476 info->image_info->endian=(EndianType) sp;
1477 for ( ; image; image=image->next)
1478 image->endian=(EndianType) sp;
1479 break;
1480 }
1481 if (LocaleCompare(attribute,"extract") == 0)
1482 {
1483 /*
1484 Set image extract geometry.
1485 */
1486 (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1487 break;
1488 }
1489 if (info)
1490 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1491 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001492 {
1493 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001494 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001495 }
cristy4a3ce0a2013-08-03 20:06:59 +00001496 break;
1497 }
1498 case 'F':
1499 case 'f':
1500 {
1501 if (LocaleCompare(attribute,"filename") == 0)
1502 {
1503 if (info)
1504 (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
cristy151b66d2015-04-15 10:50:31 +00001505 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001506 for ( ; image; image=image->next)
1507 (void) CopyMagickString(image->filename,SvPV(sval,na),
cristy151b66d2015-04-15 10:50:31 +00001508 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001509 break;
1510 }
1511 if (LocaleCompare(attribute,"file") == 0)
1512 {
1513 FILE
1514 *file;
1515
1516 PerlIO
1517 *io_info;
1518
1519 if (info == (struct PackageInfo *) NULL)
1520 break;
1521 io_info=IoIFP(sv_2io(sval));
1522 if (io_info == (PerlIO *) NULL)
1523 {
1524 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1525 PackageName);
1526 break;
1527 }
1528 file=PerlIO_findFILE(io_info);
1529 if (file == (FILE *) NULL)
1530 {
1531 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1532 PackageName);
1533 break;
1534 }
1535 SetImageInfoFile(info->image_info,file);
1536 break;
1537 }
1538 if (LocaleCompare(attribute,"fill") == 0)
1539 {
1540 if (info)
1541 (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1542 break;
1543 }
1544 if (LocaleCompare(attribute,"font") == 0)
1545 {
1546 if (info)
1547 (void) CloneString(&info->image_info->font,SvPV(sval,na));
1548 break;
1549 }
1550 if (LocaleCompare(attribute,"foreground") == 0)
1551 break;
1552 if (LocaleCompare(attribute,"fuzz") == 0)
1553 {
1554 if (info)
1555 info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1556 QuantumRange+1.0);
1557 for ( ; image; image=image->next)
1558 image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1559 QuantumRange+1.0);
1560 break;
1561 }
1562 if (info)
1563 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1564 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001565 {
1566 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001567 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001568 }
cristy4a3ce0a2013-08-03 20:06:59 +00001569 break;
1570 }
1571 case 'G':
1572 case 'g':
1573 {
1574 if (LocaleCompare(attribute,"gamma") == 0)
1575 {
1576 for ( ; image; image=image->next)
1577 image->gamma=SvNV(sval);
1578 break;
1579 }
1580 if (LocaleCompare(attribute,"gravity") == 0)
1581 {
1582 sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1583 SvPV(sval,na)) : SvIV(sval);
1584 if (sp < 0)
1585 {
1586 ThrowPerlException(exception,OptionError,
1587 "UnrecognizedGravityType",SvPV(sval,na));
1588 break;
1589 }
1590 if (info)
1591 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1592 for ( ; image; image=image->next)
1593 image->gravity=(GravityType) sp;
1594 break;
1595 }
1596 if (LocaleCompare(attribute,"green-primary") == 0)
1597 {
1598 for ( ; image; image=image->next)
1599 {
1600 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1601 image->chromaticity.green_primary.x=geometry_info.rho;
1602 image->chromaticity.green_primary.y=geometry_info.sigma;
1603 if ((flags & SigmaValue) == 0)
1604 image->chromaticity.green_primary.y=
1605 image->chromaticity.green_primary.x;
1606 }
1607 break;
1608 }
1609 if (info)
1610 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1611 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001612 {
1613 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001614 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001615 }
cristy4a3ce0a2013-08-03 20:06:59 +00001616 break;
1617 }
1618 case 'I':
1619 case 'i':
1620 {
1621 if (LocaleNCompare(attribute,"index",5) == 0)
1622 {
1623 int
1624 items;
1625
1626 long
1627 index;
1628
1629 register Quantum
1630 *q;
1631
1632 CacheView
1633 *image_view;
1634
1635 for ( ; image; image=image->next)
1636 {
1637 if (image->storage_class != PseudoClass)
1638 continue;
1639 x=0;
1640 y=0;
1641 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1642 (void) items;
1643 image_view=AcquireAuthenticCacheView(image,exception);
1644 q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1645 if (q != (Quantum *) NULL)
1646 {
1647 items=sscanf(SvPV(sval,na),"%ld",&index);
1648 if ((index >= 0) && (index < (ssize_t) image->colors))
1649 SetPixelIndex(image,index,q);
1650 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1651 }
1652 image_view=DestroyCacheView(image_view);
1653 }
1654 break;
1655 }
1656 if (LocaleCompare(attribute,"iterations") == 0)
1657 {
1658 iterations:
1659 for ( ; image; image=image->next)
1660 image->iterations=SvIV(sval);
1661 break;
1662 }
1663 if (LocaleCompare(attribute,"interlace") == 0)
1664 {
1665 sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1666 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1667 if (sp < 0)
1668 {
1669 ThrowPerlException(exception,OptionError,
1670 "UnrecognizedInterlaceType",SvPV(sval,na));
1671 break;
1672 }
1673 if (info)
1674 info->image_info->interlace=(InterlaceType) sp;
1675 for ( ; image; image=image->next)
1676 image->interlace=(InterlaceType) sp;
1677 break;
1678 }
1679 if (info)
1680 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1681 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001682 {
1683 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001684 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001685 }
cristy4a3ce0a2013-08-03 20:06:59 +00001686 break;
1687 }
1688 case 'L':
1689 case 'l':
1690 {
1691 if (LocaleCompare(attribute,"label") == 0)
1692 {
1693 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001694 (void) SetImageProperty(image,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00001695 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04001696 SvPV(sval,na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001697 break;
1698 }
1699 if (LocaleCompare(attribute,"loop") == 0)
1700 goto iterations;
1701 if (info)
1702 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1703 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001704 {
1705 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001706 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001707 }
cristy4a3ce0a2013-08-03 20:06:59 +00001708 break;
1709 }
1710 case 'M':
1711 case 'm':
1712 {
1713 if (LocaleCompare(attribute,"magick") == 0)
1714 {
1715 if (info)
Cristyb5b1f5d2017-03-31 16:42:35 -04001716 (void) FormatLocaleString(info->image_info->filename,
1717 MagickPathExtent,"%s:",SvPV(sval,na));
cristy4a3ce0a2013-08-03 20:06:59 +00001718 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001719 (void) CopyMagickString(image->magick,SvPV(sval,na),
1720 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00001721 break;
1722 }
1723 if (LocaleCompare(attribute,"map-limit") == 0)
1724 {
1725 MagickSizeType
1726 limit;
1727
1728 limit=MagickResourceInfinity;
1729 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1730 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1731 100.0);
1732 (void) SetMagickResourceLimit(MapResource,limit);
1733 break;
1734 }
1735 if (LocaleCompare(attribute,"mask") == 0)
1736 {
1737 Image
1738 *mask;
1739
1740 mask=(Image *) NULL;
1741 if (SvPOK(sval))
1742 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1743 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001744 SetImageMask(image,ReadPixelMask,mask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00001745 break;
1746 }
1747 if (LocaleCompare(attribute,"mattecolor") == 0)
1748 {
1749 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1750 exception);
1751 if (info)
Cristy8645e042016-02-03 16:35:29 -05001752 info->image_info->alpha_color=target_color;
cristy4a3ce0a2013-08-03 20:06:59 +00001753 for ( ; image; image=image->next)
Cristy8645e042016-02-03 16:35:29 -05001754 image->alpha_color=target_color;
cristy4a3ce0a2013-08-03 20:06:59 +00001755 break;
1756 }
1757 if (LocaleCompare(attribute,"matte") == 0)
1758 {
1759 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1760 SvPV(sval,na)) : SvIV(sval);
1761 if (sp < 0)
1762 {
1763 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1764 SvPV(sval,na));
1765 break;
1766 }
1767 for ( ; image; image=image->next)
1768 image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1769 break;
1770 }
1771 if (LocaleCompare(attribute,"memory-limit") == 0)
1772 {
1773 MagickSizeType
1774 limit;
1775
1776 limit=MagickResourceInfinity;
1777 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1778 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1779 100.0);
1780 (void) SetMagickResourceLimit(MemoryResource,limit);
1781 break;
1782 }
1783 if (LocaleCompare(attribute,"monochrome") == 0)
1784 {
1785 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1786 SvPV(sval,na)) : SvIV(sval);
1787 if (sp < 0)
1788 {
1789 ThrowPerlException(exception,OptionError,"UnrecognizedType",
1790 SvPV(sval,na));
1791 break;
1792 }
1793 if (info)
1794 info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1795 for ( ; image; image=image->next)
1796 (void) SetImageType(image,BilevelType,exception);
1797 break;
1798 }
1799 if (info)
1800 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1801 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001802 {
1803 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001804 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001805 }
cristy4a3ce0a2013-08-03 20:06:59 +00001806 break;
1807 }
1808 case 'O':
1809 case 'o':
1810 {
1811 if (LocaleCompare(attribute,"option") == 0)
1812 {
1813 if (info)
1814 DefineImageOption(info->image_info,SvPV(sval,na));
1815 break;
1816 }
1817 if (LocaleCompare(attribute,"orientation") == 0)
1818 {
1819 sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1820 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1821 if (sp < 0)
1822 {
1823 ThrowPerlException(exception,OptionError,
1824 "UnrecognizedOrientationType",SvPV(sval,na));
1825 break;
1826 }
1827 if (info)
1828 info->image_info->orientation=(OrientationType) sp;
1829 for ( ; image; image=image->next)
1830 image->orientation=(OrientationType) sp;
1831 break;
1832 }
1833 if (info)
1834 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1835 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001836 {
1837 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001838 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001839 }
cristy4a3ce0a2013-08-03 20:06:59 +00001840 break;
1841 }
1842 case 'P':
1843 case 'p':
1844 {
1845 if (LocaleCompare(attribute,"page") == 0)
1846 {
1847 char
1848 *geometry;
1849
1850 geometry=GetPageGeometry(SvPV(sval,na));
1851 if (info)
1852 (void) CloneString(&info->image_info->page,geometry);
1853 for ( ; image; image=image->next)
1854 (void) ParsePageGeometry(image,geometry,&image->page,exception);
1855 geometry=(char *) RelinquishMagickMemory(geometry);
1856 break;
1857 }
1858 if (LocaleNCompare(attribute,"pixel",5) == 0)
1859 {
1860 int
1861 items;
1862
1863 PixelInfo
1864 pixel;
1865
1866 register Quantum
1867 *q;
1868
1869 CacheView
1870 *image_view;
1871
1872 for ( ; image; image=image->next)
1873 {
1874 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1875 break;
1876 x=0;
1877 y=0;
1878 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1879 (void) items;
1880 image_view=AcquireVirtualCacheView(image,exception);
1881 q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1882 if (q != (Quantum *) NULL)
1883 {
1884 if ((strchr(SvPV(sval,na),',') == 0) ||
1885 (strchr(SvPV(sval,na),')') != 0))
1886 QueryColorCompliance(SvPV(sval,na),AllCompliance,
1887 &pixel,exception);
1888 else
1889 {
1890 GetPixelInfo(image,&pixel);
1891 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1892 pixel.red=geometry_info.rho;
1893 if ((flags & SigmaValue) != 0)
1894 pixel.green=geometry_info.sigma;
1895 if ((flags & XiValue) != 0)
1896 pixel.blue=geometry_info.xi;
1897 if ((flags & PsiValue) != 0)
1898 pixel.alpha=geometry_info.psi;
1899 if ((flags & ChiValue) != 0)
1900 pixel.black=geometry_info.chi;
1901 }
1902 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1903 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1904 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1905 if (image->colorspace == CMYKColorspace)
1906 SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1907 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1908 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1909 }
1910 image_view=DestroyCacheView(image_view);
1911 }
1912 break;
1913 }
1914 if (LocaleCompare(attribute,"pointsize") == 0)
1915 {
1916 if (info)
1917 {
1918 (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1919 info->image_info->pointsize=geometry_info.rho;
1920 }
1921 break;
1922 }
cristy4a3ce0a2013-08-03 20:06:59 +00001923 if (info)
1924 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1925 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001926 {
1927 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001928 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001929 }
cristy4a3ce0a2013-08-03 20:06:59 +00001930 break;
1931 }
1932 case 'Q':
1933 case 'q':
1934 {
1935 if (LocaleCompare(attribute,"quality") == 0)
1936 {
1937 if (info)
1938 info->image_info->quality=SvIV(sval);
1939 for ( ; image; image=image->next)
1940 image->quality=SvIV(sval);
1941 break;
1942 }
1943 if (info)
1944 SetImageOption(info->image_info,attribute,SvPV(sval,na));
1945 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04001946 {
1947 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02001948 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04001949 }
cristy4a3ce0a2013-08-03 20:06:59 +00001950 break;
1951 }
1952 case 'R':
1953 case 'r':
1954 {
cristyc0fe4752015-07-27 18:02:39 +00001955 if (LocaleCompare(attribute,"read-mask") == 0)
1956 {
1957 Image
1958 *mask;
1959
1960 mask=(Image *) NULL;
1961 if (SvPOK(sval))
1962 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1963 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00001964 SetImageMask(image,ReadPixelMask,mask,exception);
cristyc0fe4752015-07-27 18:02:39 +00001965 break;
1966 }
cristy4a3ce0a2013-08-03 20:06:59 +00001967 if (LocaleCompare(attribute,"red-primary") == 0)
1968 {
1969 for ( ; image; image=image->next)
1970 {
1971 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1972 image->chromaticity.red_primary.x=geometry_info.rho;
1973 image->chromaticity.red_primary.y=geometry_info.sigma;
1974 if ((flags & SigmaValue) == 0)
1975 image->chromaticity.red_primary.y=
1976 image->chromaticity.red_primary.x;
1977 }
1978 break;
1979 }
1980 if (LocaleCompare(attribute,"render") == 0)
1981 {
1982 sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1983 SvPV(sval,na)) : SvIV(sval);
1984 if (sp < 0)
1985 {
1986 ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1987 SvPV(sval,na));
1988 break;
1989 }
1990 for ( ; image; image=image->next)
1991 image->rendering_intent=(RenderingIntent) sp;
1992 break;
1993 }
1994 if (LocaleCompare(attribute,"repage") == 0)
1995 {
1996 RectangleInfo
1997 geometry;
1998
1999 for ( ; image; image=image->next)
2000 {
2001 flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
2002 if ((flags & WidthValue) != 0)
2003 {
2004 if ((flags & HeightValue) == 0)
2005 geometry.height=geometry.width;
2006 image->page.width=geometry.width;
2007 image->page.height=geometry.height;
2008 }
2009 if ((flags & AspectValue) != 0)
2010 {
2011 if ((flags & XValue) != 0)
2012 image->page.x+=geometry.x;
2013 if ((flags & YValue) != 0)
2014 image->page.y+=geometry.y;
2015 }
2016 else
2017 {
2018 if ((flags & XValue) != 0)
2019 {
2020 image->page.x=geometry.x;
2021 if (((flags & WidthValue) != 0) && (geometry.x > 0))
2022 image->page.width=image->columns+geometry.x;
2023 }
2024 if ((flags & YValue) != 0)
2025 {
2026 image->page.y=geometry.y;
2027 if (((flags & HeightValue) != 0) && (geometry.y > 0))
2028 image->page.height=image->rows+geometry.y;
2029 }
2030 }
2031 }
2032 break;
2033 }
2034 if (info)
2035 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2036 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002037 {
2038 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002039 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002040 }
cristy4a3ce0a2013-08-03 20:06:59 +00002041 break;
2042 }
2043 case 'S':
2044 case 's':
2045 {
2046 if (LocaleCompare(attribute,"sampling-factor") == 0)
2047 {
2048 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2049 {
2050 ThrowPerlException(exception,OptionError,"MissingGeometry",
2051 SvPV(sval,na));
2052 break;
2053 }
2054 if (info)
2055 (void) CloneString(&info->image_info->sampling_factor,
2056 SvPV(sval,na));
2057 break;
2058 }
2059 if (LocaleCompare(attribute,"scene") == 0)
2060 {
2061 for ( ; image; image=image->next)
2062 image->scene=SvIV(sval);
2063 break;
2064 }
2065 if (LocaleCompare(attribute,"server") == 0)
2066 goto display;
2067 if (LocaleCompare(attribute,"size") == 0)
2068 {
2069 if (info)
2070 {
2071 if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2072 {
2073 ThrowPerlException(exception,OptionError,"MissingGeometry",
2074 SvPV(sval,na));
2075 break;
2076 }
2077 (void) CloneString(&info->image_info->size,SvPV(sval,na));
2078 }
2079 break;
2080 }
2081 if (LocaleCompare(attribute,"stroke") == 0)
2082 {
2083 if (info)
2084 (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2085 break;
2086 }
2087 if (info)
2088 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2089 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002090 {
2091 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002092 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002093 }
cristy4a3ce0a2013-08-03 20:06:59 +00002094 break;
2095 }
2096 case 'T':
2097 case 't':
2098 {
2099 if (LocaleCompare(attribute,"texture") == 0)
2100 {
2101 if (info)
2102 (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2103 break;
2104 }
2105 if (LocaleCompare(attribute,"thread-limit") == 0)
2106 {
2107 MagickSizeType
2108 limit;
2109
2110 limit=MagickResourceInfinity;
2111 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2112 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2113 100.0);
2114 (void) SetMagickResourceLimit(ThreadResource,limit);
2115 break;
2116 }
2117 if (LocaleCompare(attribute,"tile-offset") == 0)
2118 {
2119 char
2120 *geometry;
2121
2122 geometry=GetPageGeometry(SvPV(sval,na));
2123 if (info)
2124 (void) CloneString(&info->image_info->page,geometry);
2125 for ( ; image; image=image->next)
2126 (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2127 exception);
2128 geometry=(char *) RelinquishMagickMemory(geometry);
2129 break;
2130 }
2131 if (LocaleCompare(attribute,"time-limit") == 0)
2132 {
2133 MagickSizeType
2134 limit;
2135
2136 limit=MagickResourceInfinity;
2137 if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2138 limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2139 100.0);
2140 (void) SetMagickResourceLimit(TimeResource,limit);
2141 break;
2142 }
2143 if (LocaleCompare(attribute,"transparent-color") == 0)
2144 {
2145 (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2146 exception);
2147 if (info)
2148 info->image_info->transparent_color=target_color;
2149 for ( ; image; image=image->next)
2150 image->transparent_color=target_color;
2151 break;
2152 }
2153 if (LocaleCompare(attribute,"type") == 0)
2154 {
2155 sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2156 SvPV(sval,na)) : SvIV(sval);
2157 if (sp < 0)
2158 {
2159 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2160 SvPV(sval,na));
2161 break;
2162 }
2163 if (info)
2164 info->image_info->type=(ImageType) sp;
2165 for ( ; image; image=image->next)
2166 SetImageType(image,(ImageType) sp,exception);
2167 break;
2168 }
2169 if (info)
2170 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2171 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002172 {
2173 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002174 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002175 }
cristy4a3ce0a2013-08-03 20:06:59 +00002176 break;
2177 }
2178 case 'U':
2179 case 'u':
2180 {
2181 if (LocaleCompare(attribute,"units") == 0)
2182 {
2183 sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2184 MagickFalse,SvPV(sval,na)) : SvIV(sval);
2185 if (sp < 0)
2186 {
2187 ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2188 SvPV(sval,na));
2189 break;
2190 }
2191 if (info)
2192 info->image_info->units=(ResolutionType) sp;
2193 for ( ; image; image=image->next)
2194 {
2195 ResolutionType
2196 units;
2197
2198 units=(ResolutionType) sp;
2199 if (image->units != units)
2200 switch (image->units)
2201 {
2202 case UndefinedResolution:
2203 case PixelsPerInchResolution:
2204 {
2205 if (units == PixelsPerCentimeterResolution)
2206 {
2207 image->resolution.x*=2.54;
2208 image->resolution.y*=2.54;
2209 }
2210 break;
2211 }
2212 case PixelsPerCentimeterResolution:
2213 {
2214 if (units == PixelsPerInchResolution)
2215 {
2216 image->resolution.x/=2.54;
2217 image->resolution.y/=2.54;
2218 }
2219 break;
2220 }
2221 }
2222 image->units=units;
2223 }
2224 break;
2225 }
2226 if (info)
2227 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2228 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002229 {
2230 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002231 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002232 }
cristy4a3ce0a2013-08-03 20:06:59 +00002233 break;
2234 }
2235 case 'V':
2236 case 'v':
2237 {
2238 if (LocaleCompare(attribute,"verbose") == 0)
2239 {
2240 sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2241 SvPV(sval,na)) : SvIV(sval);
2242 if (sp < 0)
2243 {
2244 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2245 SvPV(sval,na));
2246 break;
2247 }
2248 if (info)
2249 info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2250 break;
2251 }
cristy4a3ce0a2013-08-03 20:06:59 +00002252 if (LocaleCompare(attribute,"virtual-pixel") == 0)
2253 {
2254 sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2255 MagickFalse,SvPV(sval,na)) : SvIV(sval);
2256 if (sp < 0)
2257 {
2258 ThrowPerlException(exception,OptionError,
2259 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2260 break;
2261 }
2262 for ( ; image; image=image->next)
2263 SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2264 break;
2265 }
2266 if (info)
2267 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2268 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002269 {
2270 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002271 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002272 }
cristy4a3ce0a2013-08-03 20:06:59 +00002273 break;
2274 }
2275 case 'W':
2276 case 'w':
2277 {
2278 if (LocaleCompare(attribute,"white-point") == 0)
2279 {
2280 for ( ; image; image=image->next)
2281 {
2282 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2283 image->chromaticity.white_point.x=geometry_info.rho;
2284 image->chromaticity.white_point.y=geometry_info.sigma;
2285 if ((flags & SigmaValue) == 0)
2286 image->chromaticity.white_point.y=
2287 image->chromaticity.white_point.x;
2288 }
2289 break;
2290 }
cristyc0fe4752015-07-27 18:02:39 +00002291 if (LocaleCompare(attribute,"write-mask") == 0)
2292 {
2293 Image
2294 *mask;
2295
2296 mask=(Image *) NULL;
2297 if (SvPOK(sval))
2298 mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2299 for ( ; image; image=image->next)
cristy1f7ffb72015-07-29 11:07:03 +00002300 SetImageMask(image,WritePixelMask,mask,exception);
cristyc0fe4752015-07-27 18:02:39 +00002301 break;
2302 }
cristy4a3ce0a2013-08-03 20:06:59 +00002303 if (info)
2304 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2305 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002306 {
2307 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002308 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002309 }
cristy4a3ce0a2013-08-03 20:06:59 +00002310 break;
2311 }
2312 default:
2313 {
2314 if (info)
2315 SetImageOption(info->image_info,attribute,SvPV(sval,na));
2316 for ( ; image; image=image->next)
Cristy935a4052017-03-31 17:45:37 -04002317 {
2318 (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
Dirk Lemstraf42b7fc2017-04-03 16:21:09 +02002319 (void) SetImageArtifact(image,attribute,SvPV(sval,na));
Cristy935a4052017-03-31 17:45:37 -04002320 }
cristy4a3ce0a2013-08-03 20:06:59 +00002321 break;
2322 }
2323 }
2324}
2325
2326/*
2327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2328% %
2329% %
2330% %
2331% S e t u p L i s t %
2332% %
2333% %
2334% %
2335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2336%
2337% Method SetupList returns the list of all the images linked by their
2338% image->next and image->previous link lists for use with ImageMagick. If
2339% info is non-NULL, an info structure is returned in *info. If
2340% reference_vector is non-NULL,an array of SV* are returned in
2341% *reference_vector. Reference_vector is used when the images are going to be
2342% replaced with new Image*'s.
2343%
2344% The format of the SetupList routine is:
2345%
2346% Image *SetupList(SV *reference,struct PackageInfo **info,
2347% SV ***reference_vector,ExceptionInfo *exception)
2348%
2349% A description of each parameter follows:
2350%
2351% o list: a list of strings.
2352%
2353% o string: a character string.
2354%
2355% o exception: Return any errors or warnings in this structure.
2356%
2357*/
2358static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2359 SV ***reference_vector,ExceptionInfo *exception)
2360{
2361 Image
2362 *image;
2363
2364 ssize_t
2365 current,
2366 last;
2367
2368 if (reference_vector)
2369 *reference_vector=NULL;
2370 if (info)
2371 *info=NULL;
2372 current=0;
2373 last=0;
2374 image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2375 if (info && (SvTYPE(reference) == SVt_PVAV))
2376 *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2377 exception);
2378 return(image);
2379}
2380
2381/*
2382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2383% %
2384% %
2385% %
2386% s t r E Q c a s e %
2387% %
2388% %
2389% %
2390%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2391%
2392% strEQcase() compares two strings and returns 0 if they are the
2393% same or if the second string runs out first. The comparison is case
2394% insensitive.
2395%
2396% The format of the strEQcase routine is:
2397%
2398% ssize_t strEQcase(const char *p,const char *q)
2399%
2400% A description of each parameter follows:
2401%
2402% o p: a character string.
2403%
2404% o q: a character string.
2405%
2406%
2407*/
2408static ssize_t strEQcase(const char *p,const char *q)
2409{
2410 char
2411 c;
2412
2413 register ssize_t
2414 i;
2415
2416 for (i=0 ; (c=(*q)) != 0; i++)
2417 {
2418 if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2419 (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2420 return(0);
2421 p++;
2422 q++;
2423 }
2424 return(((*q == 0) && (*p == 0)) ? i : 0);
2425}
2426
2427/*
2428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2429% %
2430% %
2431% %
2432% I m a g e : : M a g i c k %
2433% %
2434% %
2435% %
2436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2437%
2438%
2439*/
2440MODULE = Image::Magick PACKAGE = Image::Magick
2441
2442PROTOTYPES: ENABLE
2443
2444BOOT:
2445 MagickCoreGenesis("PerlMagick",MagickFalse);
2446 SetWarningHandler(NULL);
2447 SetErrorHandler(NULL);
2448 magick_registry=NewSplayTree((int (*)(const void *,const void *))
2449 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2450
2451void
2452UNLOAD()
2453 PPCODE:
2454 {
2455 if (magick_registry != (SplayTreeInfo *) NULL)
2456 magick_registry=DestroySplayTree(magick_registry);
2457 MagickCoreTerminus();
2458 }
2459
2460double
2461constant(name,argument)
2462 char *name
2463 ssize_t argument
2464
2465#
2466###############################################################################
2467# #
2468# #
2469# #
2470# A n i m a t e #
2471# #
2472# #
2473# #
2474###############################################################################
2475#
2476#
2477void
2478Animate(ref,...)
2479 Image::Magick ref=NO_INIT
2480 ALIAS:
2481 AnimateImage = 1
2482 animate = 2
2483 animateimage = 3
2484 PPCODE:
2485 {
2486 ExceptionInfo
2487 *exception;
2488
2489 Image
2490 *image;
2491
2492 register ssize_t
2493 i;
2494
2495 struct PackageInfo
2496 *info,
2497 *package_info;
2498
2499 SV
2500 *perl_exception,
2501 *reference;
2502
2503 PERL_UNUSED_VAR(ref);
2504 PERL_UNUSED_VAR(ix);
2505 exception=AcquireExceptionInfo();
2506 perl_exception=newSVpv("",0);
2507 package_info=(struct PackageInfo *) NULL;
2508 if (sv_isobject(ST(0)) == 0)
2509 {
2510 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2511 PackageName);
2512 goto PerlException;
2513 }
2514 reference=SvRV(ST(0));
2515 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2516 if (image == (Image *) NULL)
2517 {
2518 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2519 PackageName);
2520 goto PerlException;
2521 }
2522 package_info=ClonePackageInfo(info,exception);
2523 if (items == 2)
2524 SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2525 else
2526 if (items > 2)
2527 for (i=2; i < items; i+=2)
2528 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2529 exception);
2530 (void) AnimateImages(package_info->image_info,image,exception);
2531 (void) CatchImageException(image);
2532
2533 PerlException:
2534 if (package_info != (struct PackageInfo *) NULL)
2535 DestroyPackageInfo(package_info);
2536 InheritPerlException(exception,perl_exception);
2537 exception=DestroyExceptionInfo(exception);
2538 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2539 SvPOK_on(perl_exception);
2540 ST(0)=sv_2mortal(perl_exception);
2541 XSRETURN(1);
2542 }
2543
2544#
2545###############################################################################
2546# #
2547# #
2548# #
2549# A p p e n d #
2550# #
2551# #
2552# #
2553###############################################################################
2554#
2555#
2556void
2557Append(ref,...)
2558 Image::Magick ref=NO_INIT
2559 ALIAS:
2560 AppendImage = 1
2561 append = 2
2562 appendimage = 3
2563 PPCODE:
2564 {
2565 AV
2566 *av;
2567
2568 char
2569 *attribute;
2570
2571 ExceptionInfo
2572 *exception;
2573
2574 HV
2575 *hv;
2576
2577 Image
2578 *image;
2579
2580 register ssize_t
2581 i;
2582
2583 ssize_t
2584 stack;
2585
2586 struct PackageInfo
2587 *info;
2588
2589 SV
2590 *av_reference,
2591 *perl_exception,
2592 *reference,
2593 *rv,
2594 *sv;
2595
2596 PERL_UNUSED_VAR(ref);
2597 PERL_UNUSED_VAR(ix);
2598 exception=AcquireExceptionInfo();
2599 perl_exception=newSVpv("",0);
2600 sv=NULL;
2601 attribute=NULL;
2602 av=NULL;
2603 if (sv_isobject(ST(0)) == 0)
2604 {
2605 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2606 PackageName);
2607 goto PerlException;
2608 }
2609 reference=SvRV(ST(0));
2610 hv=SvSTASH(reference);
2611 av=newAV();
2612 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2613 SvREFCNT_dec(av);
2614 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2615 if (image == (Image *) NULL)
2616 {
2617 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2618 PackageName);
2619 goto PerlException;
2620 }
2621 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2622 /*
2623 Get options.
2624 */
2625 stack=MagickTrue;
2626 for (i=2; i < items; i+=2)
2627 {
2628 attribute=(char *) SvPV(ST(i-1),na);
2629 switch (*attribute)
2630 {
2631 case 'S':
2632 case 's':
2633 {
2634 if (LocaleCompare(attribute,"stack") == 0)
2635 {
2636 stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2637 SvPV(ST(i),na));
2638 if (stack < 0)
2639 {
2640 ThrowPerlException(exception,OptionError,"UnrecognizedType",
2641 SvPV(ST(i),na));
2642 return;
2643 }
2644 break;
2645 }
2646 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2647 attribute);
2648 break;
2649 }
2650 default:
2651 {
2652 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2653 attribute);
2654 break;
2655 }
2656 }
2657 }
2658 image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2659 if (image == (Image *) NULL)
2660 goto PerlException;
2661 for ( ; image; image=image->next)
2662 {
2663 AddImageToRegistry(sv,image);
2664 rv=newRV(sv);
2665 av_push(av,sv_bless(rv,hv));
2666 SvREFCNT_dec(sv);
2667 }
2668 exception=DestroyExceptionInfo(exception);
2669 ST(0)=av_reference;
2670 SvREFCNT_dec(perl_exception);
2671 XSRETURN(1);
2672
2673 PerlException:
2674 InheritPerlException(exception,perl_exception);
2675 exception=DestroyExceptionInfo(exception);
2676 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2677 SvPOK_on(perl_exception);
2678 ST(0)=sv_2mortal(perl_exception);
2679 XSRETURN(1);
2680 }
2681
2682#
2683###############################################################################
2684# #
2685# #
2686# #
2687# A v e r a g e #
2688# #
2689# #
2690# #
2691###############################################################################
2692#
2693#
2694void
2695Average(ref)
2696 Image::Magick ref=NO_INIT
2697 ALIAS:
2698 AverageImage = 1
2699 average = 2
2700 averageimage = 3
2701 PPCODE:
2702 {
2703 AV
2704 *av;
2705
2706 char
2707 *p;
2708
2709 ExceptionInfo
2710 *exception;
2711
2712 HV
2713 *hv;
2714
2715 Image
2716 *image;
2717
2718 struct PackageInfo
2719 *info;
2720
2721 SV
2722 *perl_exception,
2723 *reference,
2724 *rv,
2725 *sv;
2726
2727 PERL_UNUSED_VAR(ref);
2728 PERL_UNUSED_VAR(ix);
2729 exception=AcquireExceptionInfo();
2730 perl_exception=newSVpv("",0);
2731 sv=NULL;
2732 if (sv_isobject(ST(0)) == 0)
2733 {
2734 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2735 PackageName);
2736 goto PerlException;
2737 }
2738 reference=SvRV(ST(0));
2739 hv=SvSTASH(reference);
2740 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2741 if (image == (Image *) NULL)
2742 {
2743 ThrowPerlException(exception,OptionError,"NoImagesDefined",
2744 PackageName);
2745 goto PerlException;
2746 }
2747 image=EvaluateImages(image,MeanEvaluateOperator,exception);
2748 if (image == (Image *) NULL)
2749 goto PerlException;
2750 /*
2751 Create blessed Perl array for the returned image.
2752 */
2753 av=newAV();
2754 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2755 SvREFCNT_dec(av);
2756 AddImageToRegistry(sv,image);
2757 rv=newRV(sv);
2758 av_push(av,sv_bless(rv,hv));
2759 SvREFCNT_dec(sv);
2760 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00002761 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2762 "average-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00002763 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2764 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00002765 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00002766 SetImageInfo(info->image_info,0,exception);
2767 exception=DestroyExceptionInfo(exception);
2768 SvREFCNT_dec(perl_exception);
2769 XSRETURN(1);
2770
2771 PerlException:
2772 InheritPerlException(exception,perl_exception);
2773 exception=DestroyExceptionInfo(exception);
2774 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2775 SvPOK_on(perl_exception);
2776 ST(0)=sv_2mortal(perl_exception);
2777 XSRETURN(1);
2778 }
2779
2780#
2781###############################################################################
2782# #
2783# #
2784# #
2785# B l o b T o I m a g e #
2786# #
2787# #
2788# #
2789###############################################################################
2790#
2791#
2792void
2793BlobToImage(ref,...)
2794 Image::Magick ref=NO_INIT
2795 ALIAS:
2796 BlobToImage = 1
2797 blobtoimage = 2
2798 blobto = 3
2799 PPCODE:
2800 {
2801 AV
2802 *av;
2803
2804 char
2805 **keep,
2806 **list;
2807
2808 ExceptionInfo
2809 *exception;
2810
2811 HV
2812 *hv;
2813
2814 Image
2815 *image;
2816
2817 register char
2818 **p;
2819
2820 register ssize_t
2821 i;
2822
2823 ssize_t
2824 ac,
2825 n,
2826 number_images;
2827
2828 STRLEN
2829 *length;
2830
2831 struct PackageInfo
2832 *info;
2833
2834 SV
2835 *perl_exception,
2836 *reference,
2837 *rv,
2838 *sv;
2839
2840 PERL_UNUSED_VAR(ref);
2841 PERL_UNUSED_VAR(ix);
2842 exception=AcquireExceptionInfo();
2843 perl_exception=newSVpv("",0);
2844 sv=NULL;
2845 number_images=0;
2846 ac=(items < 2) ? 1 : items-1;
2847 length=(STRLEN *) NULL;
2848 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2849 if (list == (char **) NULL)
2850 {
2851 ThrowPerlException(exception,ResourceLimitError,
2852 "MemoryAllocationFailed",PackageName);
2853 goto PerlException;
2854 }
2855 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2856 if (length == (STRLEN *) NULL)
2857 {
2858 ThrowPerlException(exception,ResourceLimitError,
2859 "MemoryAllocationFailed",PackageName);
2860 goto PerlException;
2861 }
2862 if (sv_isobject(ST(0)) == 0)
2863 {
2864 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2865 PackageName);
2866 goto PerlException;
2867 }
2868 reference=SvRV(ST(0));
2869 hv=SvSTASH(reference);
2870 if (SvTYPE(reference) != SVt_PVAV)
2871 {
2872 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2873 PackageName);
2874 goto PerlException;
2875 }
2876 av=(AV *) reference;
2877 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2878 exception);
2879 n=1;
2880 if (items <= 1)
2881 {
2882 ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2883 goto PerlException;
2884 }
2885 for (n=0, i=0; i < ac; i++)
2886 {
2887 list[n]=(char *) (SvPV(ST(i+1),length[n]));
2888 if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2889 {
2890 list[n]=(char *) (SvPV(ST(i+2),length[n]));
2891 continue;
2892 }
2893 n++;
2894 }
2895 list[n]=(char *) NULL;
2896 keep=list;
2897 for (i=number_images=0; i < n; i++)
2898 {
2899 image=BlobToImage(info->image_info,list[i],length[i],exception);
2900 if (image == (Image *) NULL)
2901 break;
2902 for ( ; image; image=image->next)
2903 {
2904 AddImageToRegistry(sv,image);
2905 rv=newRV(sv);
2906 av_push(av,sv_bless(rv,hv));
2907 SvREFCNT_dec(sv);
2908 number_images++;
2909 }
2910 }
2911 /*
2912 Free resources.
2913 */
2914 for (i=0; i < n; i++)
2915 if (list[i] != (char *) NULL)
2916 for (p=keep; list[i] != *p++; )
2917 if (*p == (char *) NULL)
2918 {
2919 list[i]=(char *) RelinquishMagickMemory(list[i]);
2920 break;
2921 }
2922
2923 PerlException:
2924 if (list)
2925 list=(char **) RelinquishMagickMemory(list);
2926 if (length)
2927 length=(STRLEN *) RelinquishMagickMemory(length);
2928 InheritPerlException(exception,perl_exception);
2929 exception=DestroyExceptionInfo(exception);
2930 sv_setiv(perl_exception,(IV) number_images);
2931 SvPOK_on(perl_exception);
2932 ST(0)=sv_2mortal(perl_exception);
2933 XSRETURN(1);
2934 }
2935
2936#
2937###############################################################################
2938# #
2939# #
2940# #
2941# C h a n n e l F x #
2942# #
2943# #
2944# #
2945###############################################################################
2946#
2947#
2948void
2949ChannelFx(ref,...)
2950 Image::Magick ref=NO_INIT
2951 ALIAS:
2952 ChannelFxImage = 1
2953 channelfx = 2
2954 channelfximage = 3
2955 PPCODE:
2956 {
2957 AV
2958 *av;
2959
2960 char
2961 *attribute,
cristy151b66d2015-04-15 10:50:31 +00002962 expression[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00002963
2964 ChannelType
2965 channel,
2966 channel_mask;
2967
2968 ExceptionInfo
2969 *exception;
2970
2971 HV
2972 *hv;
2973
2974 Image
2975 *image;
2976
2977 register ssize_t
2978 i;
2979
2980 struct PackageInfo
2981 *info;
2982
2983 SV
2984 *av_reference,
2985 *perl_exception,
2986 *reference,
2987 *rv,
2988 *sv;
2989
2990 PERL_UNUSED_VAR(ref);
2991 PERL_UNUSED_VAR(ix);
2992 exception=AcquireExceptionInfo();
2993 perl_exception=newSVpv("",0);
2994 sv=NULL;
2995 attribute=NULL;
2996 av=NULL;
2997 if (sv_isobject(ST(0)) == 0)
2998 {
2999 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3000 PackageName);
3001 goto PerlException;
3002 }
3003 reference=SvRV(ST(0));
3004 hv=SvSTASH(reference);
3005 av=newAV();
3006 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3007 SvREFCNT_dec(av);
3008 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3009 if (image == (Image *) NULL)
3010 {
3011 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3012 PackageName);
3013 goto PerlException;
3014 }
3015 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3016 /*
3017 Get options.
3018 */
3019 channel=DefaultChannels;
cristy151b66d2015-04-15 10:50:31 +00003020 (void) CopyMagickString(expression,"u",MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003021 if (items == 2)
cristy151b66d2015-04-15 10:50:31 +00003022 (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003023 else
3024 for (i=2; i < items; i+=2)
3025 {
3026 attribute=(char *) SvPV(ST(i-1),na);
3027 switch (*attribute)
3028 {
3029 case 'C':
3030 case 'c':
3031 {
3032 if (LocaleCompare(attribute,"channel") == 0)
3033 {
3034 ssize_t
3035 option;
3036
3037 option=ParseChannelOption(SvPV(ST(i),na));
3038 if (option < 0)
3039 {
3040 ThrowPerlException(exception,OptionError,
3041 "UnrecognizedType",SvPV(ST(i),na));
3042 return;
3043 }
3044 channel=(ChannelType) option;
3045 break;
3046 }
3047 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3048 attribute);
3049 break;
3050 }
3051 case 'E':
3052 case 'e':
3053 {
3054 if (LocaleCompare(attribute,"expression") == 0)
3055 {
3056 (void) CopyMagickString(expression,SvPV(ST(i),na),
cristy151b66d2015-04-15 10:50:31 +00003057 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00003058 break;
3059 }
3060 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3061 attribute);
3062 break;
3063 }
3064 default:
3065 {
3066 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3067 attribute);
3068 break;
3069 }
3070 }
3071 }
3072 channel_mask=SetImageChannelMask(image,channel);
3073 image=ChannelFxImage(image,expression,exception);
3074 if (image != (Image *) NULL)
3075 (void) SetImageChannelMask(image,channel_mask);
3076 if (image == (Image *) NULL)
3077 goto PerlException;
3078 for ( ; image; image=image->next)
3079 {
3080 AddImageToRegistry(sv,image);
3081 rv=newRV(sv);
3082 av_push(av,sv_bless(rv,hv));
3083 SvREFCNT_dec(sv);
3084 }
3085 exception=DestroyExceptionInfo(exception);
3086 ST(0)=av_reference;
3087 SvREFCNT_dec(perl_exception); /* can't return warning messages */
3088 XSRETURN(1);
3089
3090 PerlException:
3091 InheritPerlException(exception,perl_exception);
3092 exception=DestroyExceptionInfo(exception);
3093 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3094 SvPOK_on(perl_exception);
3095 ST(0)=sv_2mortal(perl_exception);
3096 XSRETURN(1);
3097 }
3098
3099#
3100###############################################################################
3101# #
3102# #
3103# #
3104# C l o n e #
3105# #
3106# #
3107# #
3108###############################################################################
3109#
3110#
3111void
3112Clone(ref)
3113 Image::Magick ref=NO_INIT
3114 ALIAS:
3115 CopyImage = 1
3116 copy = 2
3117 copyimage = 3
3118 CloneImage = 4
3119 clone = 5
3120 cloneimage = 6
3121 Clone = 7
3122 PPCODE:
3123 {
3124 AV
3125 *av;
3126
3127 ExceptionInfo
3128 *exception;
3129
3130 HV
3131 *hv;
3132
3133 Image
3134 *clone,
3135 *image;
3136
3137 struct PackageInfo
3138 *info;
3139
3140 SV
3141 *perl_exception,
3142 *reference,
3143 *rv,
3144 *sv;
3145
3146 PERL_UNUSED_VAR(ref);
3147 PERL_UNUSED_VAR(ix);
3148 exception=AcquireExceptionInfo();
3149 perl_exception=newSVpv("",0);
3150 sv=NULL;
3151 if (sv_isobject(ST(0)) == 0)
3152 {
3153 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3154 PackageName);
3155 goto PerlException;
3156 }
3157 reference=SvRV(ST(0));
3158 hv=SvSTASH(reference);
3159 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3160 if (image == (Image *) NULL)
3161 {
3162 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3163 PackageName);
3164 goto PerlException;
3165 }
3166 /*
3167 Create blessed Perl array for the returned image.
3168 */
3169 av=newAV();
3170 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3171 SvREFCNT_dec(av);
3172 for ( ; image; image=image->next)
3173 {
3174 clone=CloneImage(image,0,0,MagickTrue,exception);
3175 if (clone == (Image *) NULL)
3176 break;
3177 AddImageToRegistry(sv,clone);
3178 rv=newRV(sv);
3179 av_push(av,sv_bless(rv,hv));
3180 SvREFCNT_dec(sv);
3181 }
3182 exception=DestroyExceptionInfo(exception);
3183 SvREFCNT_dec(perl_exception);
3184 XSRETURN(1);
3185
3186 PerlException:
3187 InheritPerlException(exception,perl_exception);
3188 exception=DestroyExceptionInfo(exception);
3189 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3190 SvPOK_on(perl_exception);
3191 ST(0)=sv_2mortal(perl_exception);
3192 XSRETURN(1);
3193 }
3194
3195#
3196###############################################################################
3197# #
3198# #
3199# #
3200# C L O N E #
3201# #
3202# #
3203# #
3204###############################################################################
3205#
3206#
3207void
3208CLONE(ref,...)
3209 SV *ref;
3210 CODE:
3211 {
3212 PERL_UNUSED_VAR(ref);
3213 if (magick_registry != (SplayTreeInfo *) NULL)
3214 {
3215 register Image
3216 *p;
3217
3218 ResetSplayTreeIterator(magick_registry);
3219 p=(Image *) GetNextKeyInSplayTree(magick_registry);
3220 while (p != (Image *) NULL)
3221 {
3222 ReferenceImage(p);
3223 p=(Image *) GetNextKeyInSplayTree(magick_registry);
3224 }
3225 }
3226 }
3227
3228#
3229###############################################################################
3230# #
3231# #
3232# #
3233# C o a l e s c e #
3234# #
3235# #
3236# #
3237###############################################################################
3238#
3239#
3240void
3241Coalesce(ref)
3242 Image::Magick ref=NO_INIT
3243 ALIAS:
3244 CoalesceImage = 1
3245 coalesce = 2
3246 coalesceimage = 3
3247 PPCODE:
3248 {
3249 AV
3250 *av;
3251
3252 ExceptionInfo
3253 *exception;
3254
3255 HV
3256 *hv;
3257
3258 Image
3259 *image;
3260
3261 struct PackageInfo
3262 *info;
3263
3264 SV
3265 *av_reference,
3266 *perl_exception,
3267 *reference,
3268 *rv,
3269 *sv;
3270
3271 PERL_UNUSED_VAR(ref);
3272 PERL_UNUSED_VAR(ix);
3273 exception=AcquireExceptionInfo();
3274 perl_exception=newSVpv("",0);
3275 sv=NULL;
3276 if (sv_isobject(ST(0)) == 0)
3277 {
3278 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3279 PackageName);
3280 goto PerlException;
3281 }
3282 reference=SvRV(ST(0));
3283 hv=SvSTASH(reference);
3284 av=newAV();
3285 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3286 SvREFCNT_dec(av);
3287 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3288 if (image == (Image *) NULL)
3289 {
3290 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3291 PackageName);
3292 goto PerlException;
3293 }
3294 image=CoalesceImages(image,exception);
3295 if (image == (Image *) NULL)
3296 goto PerlException;
3297 for ( ; image; image=image->next)
3298 {
3299 AddImageToRegistry(sv,image);
3300 rv=newRV(sv);
3301 av_push(av,sv_bless(rv,hv));
3302 SvREFCNT_dec(sv);
3303 }
3304 exception=DestroyExceptionInfo(exception);
3305 ST(0)=av_reference;
3306 SvREFCNT_dec(perl_exception);
3307 XSRETURN(1);
3308
3309 PerlException:
3310 InheritPerlException(exception,perl_exception);
3311 exception=DestroyExceptionInfo(exception);
3312 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3313 SvPOK_on(perl_exception);
3314 ST(0)=sv_2mortal(perl_exception);
3315 XSRETURN(1);
3316 }
3317
3318#
3319###############################################################################
3320# #
3321# #
3322# #
3323# C o m p a r e #
3324# #
3325# #
3326# #
3327###############################################################################
3328#
3329#
3330void
3331Compare(ref,...)
3332 Image::Magick ref=NO_INIT
3333 ALIAS:
3334 CompareImages = 1
3335 compare = 2
3336 compareimage = 3
3337 PPCODE:
3338 {
3339 AV
3340 *av;
3341
3342 char
3343 *attribute;
3344
3345 double
3346 distortion;
3347
3348 ExceptionInfo
3349 *exception;
3350
3351 HV
3352 *hv;
3353
3354 Image
3355 *difference_image,
3356 *image,
3357 *reconstruct_image;
3358
3359 MetricType
3360 metric;
3361
3362 register ssize_t
3363 i;
3364
3365 ssize_t
3366 option;
3367
3368 struct PackageInfo
3369 *info;
3370
3371 SV
3372 *av_reference,
3373 *perl_exception,
3374 *reference,
3375 *rv,
3376 *sv;
3377
3378 PERL_UNUSED_VAR(ref);
3379 PERL_UNUSED_VAR(ix);
3380 exception=AcquireExceptionInfo();
3381 perl_exception=newSVpv("",0);
3382 sv=NULL;
3383 av=NULL;
3384 attribute=NULL;
3385 if (sv_isobject(ST(0)) == 0)
3386 {
3387 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3388 PackageName);
3389 goto PerlException;
3390 }
3391 reference=SvRV(ST(0));
3392 hv=SvSTASH(reference);
3393 av=newAV();
3394 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3395 SvREFCNT_dec(av);
3396 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3397 if (image == (Image *) NULL)
3398 {
3399 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3400 PackageName);
3401 goto PerlException;
3402 }
3403 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3404 /*
3405 Get attribute.
3406 */
3407 reconstruct_image=image;
3408 metric=RootMeanSquaredErrorMetric;
3409 for (i=2; i < items; i+=2)
3410 {
3411 attribute=(char *) SvPV(ST(i-1),na);
3412 switch (*attribute)
3413 {
3414 case 'C':
3415 case 'c':
3416 {
3417 if (LocaleCompare(attribute,"channel") == 0)
3418 {
3419 ssize_t
3420 option;
3421
3422 option=ParseChannelOption(SvPV(ST(i),na));
3423 if (option < 0)
3424 {
3425 ThrowPerlException(exception,OptionError,
3426 "UnrecognizedType",SvPV(ST(i),na));
3427 return;
3428 }
cristybcd59342015-06-07 14:07:19 +00003429 (void) SetPixelChannelMask(image,(ChannelType) option);
cristy4a3ce0a2013-08-03 20:06:59 +00003430 break;
3431 }
3432 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3433 attribute);
3434 break;
3435 }
3436 case 'F':
3437 case 'f':
3438 {
3439 if (LocaleCompare(attribute,"fuzz") == 0)
3440 {
3441 image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3442 break;
3443 }
3444 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3445 attribute);
3446 break;
3447 }
3448 case 'I':
3449 case 'i':
3450 {
3451 if (LocaleCompare(attribute,"image") == 0)
3452 {
3453 reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3454 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3455 break;
3456 }
3457 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3458 attribute);
3459 break;
3460 }
3461 case 'M':
3462 case 'm':
3463 {
3464 if (LocaleCompare(attribute,"metric") == 0)
3465 {
3466 option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3467 SvPV(ST(i),na));
3468 if (option < 0)
3469 {
3470 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3471 SvPV(ST(i),na));
3472 break;
3473 }
3474 metric=(MetricType) option;
3475 break;
3476 }
3477 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3478 attribute);
3479 break;
3480 }
3481 default:
3482 {
3483 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3484 attribute);
3485 break;
3486 }
3487 }
3488 }
3489 difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3490 exception);
3491 if (difference_image != (Image *) NULL)
3492 {
3493 difference_image->error.mean_error_per_pixel=distortion;
3494 AddImageToRegistry(sv,difference_image);
3495 rv=newRV(sv);
3496 av_push(av,sv_bless(rv,hv));
3497 SvREFCNT_dec(sv);
3498 }
3499 exception=DestroyExceptionInfo(exception);
3500 ST(0)=av_reference;
3501 SvREFCNT_dec(perl_exception); /* can't return warning messages */
3502 XSRETURN(1);
3503
3504 PerlException:
3505 InheritPerlException(exception,perl_exception);
3506 exception=DestroyExceptionInfo(exception);
3507 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3508 SvPOK_on(perl_exception);
3509 ST(0)=sv_2mortal(perl_exception);
3510 XSRETURN(1);
3511 }
3512
3513#
3514###############################################################################
3515# #
3516# #
3517# #
cristy15655332013-10-06 00:27:33 +00003518# C o m p l e x I m a g e s #
3519# #
3520# #
3521# #
3522###############################################################################
3523#
3524#
3525void
3526ComplexImages(ref)
3527 Image::Magick ref=NO_INIT
3528 ALIAS:
3529 ComplexImages = 1
3530 compleximages = 2
3531 PPCODE:
3532 {
3533 AV
3534 *av;
3535
3536 char
3537 *attribute,
3538 *p;
3539
cristyfa21e9e2013-10-07 10:37:38 +00003540 ComplexOperator
3541 op;
3542
cristy15655332013-10-06 00:27:33 +00003543 ExceptionInfo
3544 *exception;
3545
3546 HV
3547 *hv;
3548
3549 Image
3550 *image;
3551
cristy15655332013-10-06 00:27:33 +00003552 register ssize_t
3553 i;
3554
3555 struct PackageInfo
3556 *info;
3557
3558 SV
3559 *perl_exception,
3560 *reference,
3561 *rv,
3562 *sv;
3563
3564 PERL_UNUSED_VAR(ref);
3565 PERL_UNUSED_VAR(ix);
3566 exception=AcquireExceptionInfo();
3567 perl_exception=newSVpv("",0);
3568 sv=NULL;
3569 if (sv_isobject(ST(0)) == 0)
3570 {
3571 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3572 PackageName);
3573 goto PerlException;
3574 }
3575 reference=SvRV(ST(0));
3576 hv=SvSTASH(reference);
3577 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3578 if (image == (Image *) NULL)
3579 {
3580 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3581 PackageName);
3582 goto PerlException;
3583 }
cristyfd168722013-10-07 15:59:31 +00003584 op=UndefinedComplexOperator;
cristy15655332013-10-06 00:27:33 +00003585 if (items == 2)
3586 {
3587 ssize_t
3588 in;
3589
3590 in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3591 SvPV(ST(1),na));
3592 if (in < 0)
3593 {
3594 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3595 SvPV(ST(1),na));
3596 return;
3597 }
cristyfa21e9e2013-10-07 10:37:38 +00003598 op=(ComplexOperator) in;
cristy15655332013-10-06 00:27:33 +00003599 }
3600 else
3601 for (i=2; i < items; i+=2)
3602 {
3603 attribute=(char *) SvPV(ST(i-1),na);
3604 switch (*attribute)
3605 {
3606 case 'O':
3607 case 'o':
3608 {
3609 if (LocaleCompare(attribute,"operator") == 0)
3610 {
3611 ssize_t
3612 in;
3613
3614 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3615 MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3616 if (in < 0)
3617 {
3618 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3619 SvPV(ST(i),na));
3620 return;
3621 }
cristyfa21e9e2013-10-07 10:37:38 +00003622 op=(ComplexOperator) in;
cristy15655332013-10-06 00:27:33 +00003623 break;
3624 }
3625 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3626 attribute);
3627 break;
3628 }
3629 default:
3630 {
3631 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3632 attribute);
3633 break;
3634 }
3635 }
3636 }
3637 image=ComplexImages(image,op,exception);
3638 if (image == (Image *) NULL)
3639 goto PerlException;
3640 /*
3641 Create blessed Perl array for the returned image.
3642 */
3643 av=newAV();
3644 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3645 SvREFCNT_dec(av);
3646 AddImageToRegistry(sv,image);
3647 rv=newRV(sv);
3648 av_push(av,sv_bless(rv,hv));
3649 SvREFCNT_dec(sv);
3650 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00003651 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3652 "complex-%.*s",(int) (MagickPathExtent-9),
cristy15655332013-10-06 00:27:33 +00003653 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3654 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00003655 MagickPathExtent);
cristy15655332013-10-06 00:27:33 +00003656 SetImageInfo(info->image_info,0,exception);
3657 exception=DestroyExceptionInfo(exception);
3658 SvREFCNT_dec(perl_exception);
3659 XSRETURN(1);
3660
3661 PerlException:
3662 InheritPerlException(exception,perl_exception);
3663 exception=DestroyExceptionInfo(exception);
3664 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3665 SvPOK_on(perl_exception);
3666 ST(0)=sv_2mortal(perl_exception);
3667 XSRETURN(1);
3668 }
3669
3670#
3671###############################################################################
3672# #
3673# #
3674# #
cristy4a3ce0a2013-08-03 20:06:59 +00003675# C o m p a r e L a y e r s #
3676# #
3677# #
3678# #
3679###############################################################################
3680#
3681#
3682void
3683CompareLayers(ref)
3684 Image::Magick ref=NO_INIT
3685 ALIAS:
3686 CompareImagesLayers = 1
3687 comparelayers = 2
3688 compareimagelayers = 3
3689 PPCODE:
3690 {
3691 AV
3692 *av;
3693
3694 char
3695 *attribute;
3696
3697 ExceptionInfo
3698 *exception;
3699
3700 HV
3701 *hv;
3702
3703 Image
3704 *image;
3705
3706 LayerMethod
3707 method;
3708
3709 register ssize_t
3710 i;
3711
3712 ssize_t
3713 option;
3714
3715 struct PackageInfo
3716 *info;
3717
3718 SV
3719 *av_reference,
3720 *perl_exception,
3721 *reference,
3722 *rv,
3723 *sv;
3724
3725 PERL_UNUSED_VAR(ref);
3726 PERL_UNUSED_VAR(ix);
3727 exception=AcquireExceptionInfo();
3728 perl_exception=newSVpv("",0);
3729 sv=NULL;
3730 if (sv_isobject(ST(0)) == 0)
3731 {
3732 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3733 PackageName);
3734 goto PerlException;
3735 }
3736 reference=SvRV(ST(0));
3737 hv=SvSTASH(reference);
3738 av=newAV();
3739 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3740 SvREFCNT_dec(av);
3741 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3742 if (image == (Image *) NULL)
3743 {
3744 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3745 PackageName);
3746 goto PerlException;
3747 }
3748 method=CompareAnyLayer;
3749 for (i=2; i < items; i+=2)
3750 {
3751 attribute=(char *) SvPV(ST(i-1),na);
3752 switch (*attribute)
3753 {
3754 case 'M':
3755 case 'm':
3756 {
3757 if (LocaleCompare(attribute,"method") == 0)
3758 {
3759 option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3760 SvPV(ST(i),na));
3761 if (option < 0)
3762 {
3763 ThrowPerlException(exception,OptionError,"UnrecognizedType",
3764 SvPV(ST(i),na));
3765 break;
3766 }
3767 method=(LayerMethod) option;
3768 break;
3769 }
3770 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3771 attribute);
3772 break;
3773 }
3774 default:
3775 {
3776 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3777 attribute);
3778 break;
3779 }
3780 }
3781 }
3782 image=CompareImagesLayers(image,method,exception);
3783 if (image == (Image *) NULL)
3784 goto PerlException;
3785 for ( ; image; image=image->next)
3786 {
3787 AddImageToRegistry(sv,image);
3788 rv=newRV(sv);
3789 av_push(av,sv_bless(rv,hv));
3790 SvREFCNT_dec(sv);
3791 }
3792 exception=DestroyExceptionInfo(exception);
3793 ST(0)=av_reference;
3794 SvREFCNT_dec(perl_exception);
3795 XSRETURN(1);
3796
3797 PerlException:
3798 InheritPerlException(exception,perl_exception);
3799 exception=DestroyExceptionInfo(exception);
3800 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3801 SvPOK_on(perl_exception);
3802 ST(0)=sv_2mortal(perl_exception);
3803 XSRETURN(1);
3804 }
3805
3806#
3807###############################################################################
3808# #
3809# #
3810# #
3811# D e s t r o y #
3812# #
3813# #
3814# #
3815###############################################################################
3816#
3817#
3818void
3819DESTROY(ref)
3820 Image::Magick ref=NO_INIT
3821 PPCODE:
3822 {
3823 SV
3824 *reference;
3825
3826 PERL_UNUSED_VAR(ref);
3827 if (sv_isobject(ST(0)) == 0)
3828 croak("ReferenceIsNotMyType");
3829 reference=SvRV(ST(0));
3830 switch (SvTYPE(reference))
3831 {
3832 case SVt_PVAV:
3833 {
3834 char
cristy151b66d2015-04-15 10:50:31 +00003835 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00003836
3837 const SV
3838 *key;
3839
3840 HV
3841 *hv;
3842
3843 GV
3844 **gvp;
3845
3846 struct PackageInfo
3847 *info;
3848
3849 SV
3850 *sv;
3851
3852 /*
3853 Array (AV *) reference
3854 */
cristy151b66d2015-04-15 10:50:31 +00003855 (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
cristy4a3ce0a2013-08-03 20:06:59 +00003856 XS_VERSION,reference);
3857 hv=gv_stashpv(PackageName, FALSE);
3858 if (!hv)
3859 break;
3860 gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3861 if (!gvp)
3862 break;
3863 sv=GvSV(*gvp);
3864 if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3865 {
3866 info=INT2PTR(struct PackageInfo *,SvIV(sv));
3867 DestroyPackageInfo(info);
3868 }
3869 key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3870 (void) key;
3871 break;
3872 }
3873 case SVt_PVMG:
3874 {
3875 Image
3876 *image;
3877
3878 /*
3879 Blessed scalar = (Image *) SvIV(reference)
3880 */
3881 image=INT2PTR(Image *,SvIV(reference));
3882 if (image != (Image *) NULL)
3883 DeleteImageFromRegistry(reference,image);
3884 break;
3885 }
3886 default:
3887 break;
3888 }
3889 }
3890
3891#
3892###############################################################################
3893# #
3894# #
3895# #
3896# D i s p l a y #
3897# #
3898# #
3899# #
3900###############################################################################
3901#
3902#
3903void
3904Display(ref,...)
3905 Image::Magick ref=NO_INIT
3906 ALIAS:
3907 DisplayImage = 1
3908 display = 2
3909 displayimage = 3
3910 PPCODE:
3911 {
3912 ExceptionInfo
3913 *exception;
3914
3915 Image
3916 *image;
3917
3918 register ssize_t
3919 i;
3920
3921 struct PackageInfo
3922 *info,
3923 *package_info;
3924
3925 SV
3926 *perl_exception,
3927 *reference;
3928
3929 PERL_UNUSED_VAR(ref);
3930 PERL_UNUSED_VAR(ix);
3931 exception=AcquireExceptionInfo();
3932 perl_exception=newSVpv("",0);
3933 package_info=(struct PackageInfo *) NULL;
3934 if (sv_isobject(ST(0)) == 0)
3935 {
3936 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3937 PackageName);
3938 goto PerlException;
3939 }
3940 reference=SvRV(ST(0));
3941 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3942 if (image == (Image *) NULL)
3943 {
3944 ThrowPerlException(exception,OptionError,"NoImagesDefined",
3945 PackageName);
3946 goto PerlException;
3947 }
3948 package_info=ClonePackageInfo(info,exception);
3949 if (items == 2)
3950 SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3951 else
3952 if (items > 2)
3953 for (i=2; i < items; i+=2)
3954 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3955 exception);
3956 (void) DisplayImages(package_info->image_info,image,exception);
3957 (void) CatchImageException(image);
3958
3959 PerlException:
3960 if (package_info != (struct PackageInfo *) NULL)
3961 DestroyPackageInfo(package_info);
3962 InheritPerlException(exception,perl_exception);
3963 exception=DestroyExceptionInfo(exception);
3964 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3965 SvPOK_on(perl_exception);
3966 ST(0)=sv_2mortal(perl_exception);
3967 XSRETURN(1);
3968 }
3969
3970#
3971###############################################################################
3972# #
3973# #
3974# #
3975# E v a l u a t e I m a g e s #
3976# #
3977# #
3978# #
3979###############################################################################
3980#
3981#
3982void
3983EvaluateImages(ref)
3984 Image::Magick ref=NO_INIT
3985 ALIAS:
3986 EvaluateImages = 1
3987 evaluateimages = 2
3988 PPCODE:
3989 {
3990 AV
3991 *av;
3992
3993 char
3994 *attribute,
3995 *p;
3996
3997 ExceptionInfo
3998 *exception;
3999
4000 HV
4001 *hv;
4002
4003 Image
4004 *image;
4005
4006 MagickEvaluateOperator
4007 op;
4008
4009 register ssize_t
4010 i;
4011
4012 struct PackageInfo
4013 *info;
4014
4015 SV
4016 *perl_exception,
4017 *reference,
4018 *rv,
4019 *sv;
4020
4021 PERL_UNUSED_VAR(ref);
4022 PERL_UNUSED_VAR(ix);
4023 exception=AcquireExceptionInfo();
4024 perl_exception=newSVpv("",0);
4025 sv=NULL;
4026 if (sv_isobject(ST(0)) == 0)
4027 {
4028 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4029 PackageName);
4030 goto PerlException;
4031 }
4032 reference=SvRV(ST(0));
4033 hv=SvSTASH(reference);
4034 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4035 if (image == (Image *) NULL)
4036 {
4037 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4038 PackageName);
4039 goto PerlException;
4040 }
4041 op=MeanEvaluateOperator;
4042 if (items == 2)
4043 {
4044 ssize_t
4045 in;
4046
4047 in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
4048 SvPV(ST(1),na));
4049 if (in < 0)
4050 {
4051 ThrowPerlException(exception,OptionError,"UnrecognizedType",
4052 SvPV(ST(1),na));
4053 return;
4054 }
4055 op=(MagickEvaluateOperator) in;
4056 }
4057 else
4058 for (i=2; i < items; i+=2)
4059 {
4060 attribute=(char *) SvPV(ST(i-1),na);
4061 switch (*attribute)
4062 {
4063 case 'O':
4064 case 'o':
4065 {
4066 if (LocaleCompare(attribute,"operator") == 0)
4067 {
4068 ssize_t
4069 in;
4070
4071 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4072 MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4073 if (in < 0)
4074 {
4075 ThrowPerlException(exception,OptionError,"UnrecognizedType",
4076 SvPV(ST(i),na));
4077 return;
4078 }
4079 op=(MagickEvaluateOperator) in;
4080 break;
4081 }
4082 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4083 attribute);
4084 break;
4085 }
4086 default:
4087 {
4088 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4089 attribute);
4090 break;
4091 }
4092 }
4093 }
4094 image=EvaluateImages(image,op,exception);
4095 if (image == (Image *) NULL)
4096 goto PerlException;
4097 /*
4098 Create blessed Perl array for the returned image.
4099 */
4100 av=newAV();
4101 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4102 SvREFCNT_dec(av);
4103 AddImageToRegistry(sv,image);
4104 rv=newRV(sv);
4105 av_push(av,sv_bless(rv,hv));
4106 SvREFCNT_dec(sv);
4107 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00004108 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4109 "evaluate-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00004110 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4111 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00004112 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004113 SetImageInfo(info->image_info,0,exception);
4114 exception=DestroyExceptionInfo(exception);
4115 SvREFCNT_dec(perl_exception);
4116 XSRETURN(1);
4117
4118 PerlException:
4119 InheritPerlException(exception,perl_exception);
4120 exception=DestroyExceptionInfo(exception);
4121 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4122 SvPOK_on(perl_exception);
4123 ST(0)=sv_2mortal(perl_exception);
4124 XSRETURN(1);
4125 }
4126
4127#
4128###############################################################################
4129# #
4130# #
4131# #
4132# F e a t u r e s #
4133# #
4134# #
4135# #
4136###############################################################################
4137#
4138#
4139void
4140Features(ref,...)
4141 Image::Magick ref=NO_INIT
4142 ALIAS:
4143 FeaturesImage = 1
4144 features = 2
4145 featuresimage = 3
4146 PPCODE:
4147 {
4148#define ChannelFeatures(channel,direction) \
4149{ \
Cristyb1710fe2017-02-11 13:51:48 -05004150 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004151 channel_features[channel].angular_second_moment[direction]); \
4152 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004153 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004154 channel_features[channel].contrast[direction]); \
4155 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004156 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004157 channel_features[channel].contrast[direction]); \
4158 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004159 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004160 channel_features[channel].variance_sum_of_squares[direction]); \
4161 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004162 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004163 channel_features[channel].inverse_difference_moment[direction]); \
4164 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004165 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004166 channel_features[channel].sum_average[direction]); \
4167 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004168 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004169 channel_features[channel].sum_variance[direction]); \
4170 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004171 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004172 channel_features[channel].sum_entropy[direction]); \
4173 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004174 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004175 channel_features[channel].entropy[direction]); \
4176 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004177 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004178 channel_features[channel].difference_variance[direction]); \
4179 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004180 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004181 channel_features[channel].difference_entropy[direction]); \
4182 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004183 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004184 channel_features[channel].measure_of_correlation_1[direction]); \
4185 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004186 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004187 channel_features[channel].measure_of_correlation_2[direction]); \
4188 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -05004189 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +00004190 channel_features[channel].maximum_correlation_coefficient[direction]); \
4191 PUSHs(sv_2mortal(newSVpv(message,0))); \
4192}
4193
4194 AV
4195 *av;
4196
4197 char
4198 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004199 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004200
4201 ChannelFeatures
4202 *channel_features;
4203
4204 double
4205 distance;
4206
4207 ExceptionInfo
4208 *exception;
4209
4210 Image
4211 *image;
4212
4213 register ssize_t
4214 i;
4215
4216 ssize_t
4217 count;
4218
4219 struct PackageInfo
4220 *info;
4221
4222 SV
4223 *perl_exception,
4224 *reference;
4225
4226 PERL_UNUSED_VAR(ref);
4227 PERL_UNUSED_VAR(ix);
4228 exception=AcquireExceptionInfo();
4229 perl_exception=newSVpv("",0);
4230 av=NULL;
4231 if (sv_isobject(ST(0)) == 0)
4232 {
4233 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4234 PackageName);
4235 goto PerlException;
4236 }
4237 reference=SvRV(ST(0));
4238 av=newAV();
4239 SvREFCNT_dec(av);
4240 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4241 if (image == (Image *) NULL)
4242 {
4243 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4244 PackageName);
4245 goto PerlException;
4246 }
cristy7dbd9262014-07-02 17:53:42 +00004247 distance=1.0;
cristy4a3ce0a2013-08-03 20:06:59 +00004248 for (i=2; i < items; i+=2)
4249 {
4250 attribute=(char *) SvPV(ST(i-1),na);
4251 switch (*attribute)
4252 {
4253 case 'D':
4254 case 'd':
4255 {
4256 if (LocaleCompare(attribute,"distance") == 0)
4257 {
4258 distance=StringToLong((char *) SvPV(ST(1),na));
4259 break;
4260 }
4261 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4262 attribute);
4263 break;
4264 }
4265 default:
4266 {
4267 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4268 attribute);
4269 break;
4270 }
4271 }
4272 }
4273 count=0;
4274 for ( ; image; image=image->next)
4275 {
Cristy5a854dc2017-02-11 15:43:46 -05004276 register ssize_t
4277 j;
4278
cristy4a3ce0a2013-08-03 20:06:59 +00004279 channel_features=GetImageFeatures(image,distance,exception);
4280 if (channel_features == (ChannelFeatures *) NULL)
4281 continue;
4282 count++;
Cristy5a854dc2017-02-11 15:43:46 -05004283 for (j=0; j < 4; j++)
cristy4a3ce0a2013-08-03 20:06:59 +00004284 {
Cristy5a854dc2017-02-11 15:43:46 -05004285 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
4286 {
4287 PixelChannel channel=GetPixelChannelChannel(image,i);
4288 PixelTrait traits=GetPixelChannelTraits(image,channel);
4289 if (traits == UndefinedPixelTrait)
4290 continue;
4291 EXTEND(sp,14*(i+1)*count);
4292 ChannelFeatures(channel,j);
4293 }
cristy4a3ce0a2013-08-03 20:06:59 +00004294 }
4295 channel_features=(ChannelFeatures *)
4296 RelinquishMagickMemory(channel_features);
4297 }
4298
4299 PerlException:
4300 InheritPerlException(exception,perl_exception);
4301 exception=DestroyExceptionInfo(exception);
4302 SvREFCNT_dec(perl_exception);
4303 }
4304
4305#
4306###############################################################################
4307# #
4308# #
4309# #
4310# F l a t t e n #
4311# #
4312# #
4313# #
4314###############################################################################
4315#
4316#
4317void
4318Flatten(ref)
4319 Image::Magick ref=NO_INIT
4320 ALIAS:
4321 FlattenImage = 1
4322 flatten = 2
4323 flattenimage = 3
4324 PPCODE:
4325 {
4326 AV
4327 *av;
4328
4329 char
4330 *attribute,
4331 *p;
4332
4333 ExceptionInfo
4334 *exception;
4335
4336 HV
4337 *hv;
4338
4339 Image
4340 *image;
4341
4342 PixelInfo
4343 background_color;
4344
4345 register ssize_t
4346 i;
4347
4348 struct PackageInfo
4349 *info;
4350
4351 SV
4352 *perl_exception,
4353 *reference,
4354 *rv,
4355 *sv;
4356
4357 PERL_UNUSED_VAR(ref);
4358 PERL_UNUSED_VAR(ix);
4359 exception=AcquireExceptionInfo();
4360 perl_exception=newSVpv("",0);
4361 sv=NULL;
4362 if (sv_isobject(ST(0)) == 0)
4363 {
4364 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4365 PackageName);
4366 goto PerlException;
4367 }
4368 reference=SvRV(ST(0));
4369 hv=SvSTASH(reference);
4370 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4371 if (image == (Image *) NULL)
4372 {
4373 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4374 PackageName);
4375 goto PerlException;
4376 }
4377 background_color=image->background_color;
4378 if (items == 2)
4379 (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4380 &background_color,exception);
4381 else
4382 for (i=2; i < items; i+=2)
4383 {
4384 attribute=(char *) SvPV(ST(i-1),na);
4385 switch (*attribute)
4386 {
4387 case 'B':
4388 case 'b':
4389 {
4390 if (LocaleCompare(attribute,"background") == 0)
4391 {
4392 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4393 AllCompliance,&background_color,exception);
4394 break;
4395 }
4396 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4397 attribute);
4398 break;
4399 }
4400 default:
4401 {
4402 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4403 attribute);
4404 break;
4405 }
4406 }
4407 }
4408 image->background_color=background_color;
4409 image=MergeImageLayers(image,FlattenLayer,exception);
4410 if (image == (Image *) NULL)
4411 goto PerlException;
4412 /*
4413 Create blessed Perl array for the returned image.
4414 */
4415 av=newAV();
4416 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4417 SvREFCNT_dec(av);
4418 AddImageToRegistry(sv,image);
4419 rv=newRV(sv);
4420 av_push(av,sv_bless(rv,hv));
4421 SvREFCNT_dec(sv);
4422 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
cristy151b66d2015-04-15 10:50:31 +00004423 (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4424 "flatten-%.*s",(int) (MagickPathExtent-9),
cristy4a3ce0a2013-08-03 20:06:59 +00004425 ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4426 (void) CopyMagickString(image->filename,info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00004427 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004428 SetImageInfo(info->image_info,0,exception);
4429 exception=DestroyExceptionInfo(exception);
4430 SvREFCNT_dec(perl_exception);
4431 XSRETURN(1);
4432
4433 PerlException:
4434 InheritPerlException(exception,perl_exception);
4435 exception=DestroyExceptionInfo(exception);
4436 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4437 SvPOK_on(perl_exception); /* return messages in string context */
4438 ST(0)=sv_2mortal(perl_exception);
4439 XSRETURN(1);
4440 }
4441
4442#
4443###############################################################################
4444# #
4445# #
4446# #
4447# F x #
4448# #
4449# #
4450# #
4451###############################################################################
4452#
4453#
4454void
4455Fx(ref,...)
4456 Image::Magick ref=NO_INIT
4457 ALIAS:
4458 FxImage = 1
4459 fx = 2
4460 fximage = 3
4461 PPCODE:
4462 {
4463 AV
4464 *av;
4465
4466 char
4467 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004468 expression[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004469
4470 ChannelType
4471 channel,
4472 channel_mask;
4473
4474 ExceptionInfo
4475 *exception;
4476
4477 HV
4478 *hv;
4479
4480 Image
4481 *image;
4482
4483 register ssize_t
4484 i;
4485
4486 struct PackageInfo
4487 *info;
4488
4489 SV
4490 *av_reference,
4491 *perl_exception,
4492 *reference,
4493 *rv,
4494 *sv;
4495
4496 PERL_UNUSED_VAR(ref);
4497 PERL_UNUSED_VAR(ix);
4498 exception=AcquireExceptionInfo();
4499 perl_exception=newSVpv("",0);
4500 sv=NULL;
4501 attribute=NULL;
4502 av=NULL;
4503 if (sv_isobject(ST(0)) == 0)
4504 {
4505 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4506 PackageName);
4507 goto PerlException;
4508 }
4509 reference=SvRV(ST(0));
4510 hv=SvSTASH(reference);
4511 av=newAV();
4512 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4513 SvREFCNT_dec(av);
4514 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4515 if (image == (Image *) NULL)
4516 {
4517 ThrowPerlException(exception,OptionError,"NoImagesDefined",
4518 PackageName);
4519 goto PerlException;
4520 }
4521 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4522 /*
4523 Get options.
4524 */
4525 channel=DefaultChannels;
cristy151b66d2015-04-15 10:50:31 +00004526 (void) CopyMagickString(expression,"u",MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004527 if (items == 2)
cristy151b66d2015-04-15 10:50:31 +00004528 (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004529 else
4530 for (i=2; i < items; i+=2)
4531 {
4532 attribute=(char *) SvPV(ST(i-1),na);
4533 switch (*attribute)
4534 {
4535 case 'C':
4536 case 'c':
4537 {
4538 if (LocaleCompare(attribute,"channel") == 0)
4539 {
4540 ssize_t
4541 option;
4542
4543 option=ParseChannelOption(SvPV(ST(i),na));
4544 if (option < 0)
4545 {
4546 ThrowPerlException(exception,OptionError,
4547 "UnrecognizedType",SvPV(ST(i),na));
4548 return;
4549 }
4550 channel=(ChannelType) option;
4551 break;
4552 }
4553 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4554 attribute);
4555 break;
4556 }
4557 case 'E':
4558 case 'e':
4559 {
4560 if (LocaleCompare(attribute,"expression") == 0)
4561 {
4562 (void) CopyMagickString(expression,SvPV(ST(i),na),
cristy151b66d2015-04-15 10:50:31 +00004563 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00004564 break;
4565 }
4566 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4567 attribute);
4568 break;
4569 }
4570 default:
4571 {
4572 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4573 attribute);
4574 break;
4575 }
4576 }
4577 }
4578 channel_mask=SetImageChannelMask(image,channel);
4579 image=FxImage(image,expression,exception);
4580 if (image != (Image *) NULL)
4581 (void) SetImageChannelMask(image,channel_mask);
4582 if (image == (Image *) NULL)
4583 goto PerlException;
4584 for ( ; image; image=image->next)
4585 {
4586 AddImageToRegistry(sv,image);
4587 rv=newRV(sv);
4588 av_push(av,sv_bless(rv,hv));
4589 SvREFCNT_dec(sv);
4590 }
4591 exception=DestroyExceptionInfo(exception);
4592 ST(0)=av_reference;
4593 SvREFCNT_dec(perl_exception); /* can't return warning messages */
4594 XSRETURN(1);
4595
4596 PerlException:
4597 InheritPerlException(exception,perl_exception);
4598 exception=DestroyExceptionInfo(exception);
4599 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4600 SvPOK_on(perl_exception);
4601 ST(0)=sv_2mortal(perl_exception);
4602 XSRETURN(1);
4603 }
4604
4605#
4606###############################################################################
4607# #
4608# #
4609# #
4610# G e t #
4611# #
4612# #
4613# #
4614###############################################################################
4615#
4616#
4617void
4618Get(ref,...)
4619 Image::Magick ref=NO_INIT
4620 ALIAS:
4621 GetAttributes = 1
4622 GetAttribute = 2
4623 get = 3
4624 getattributes = 4
4625 getattribute = 5
4626 PPCODE:
4627 {
4628 char
4629 *attribute,
cristy151b66d2015-04-15 10:50:31 +00004630 color[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004631
4632 const char
4633 *value;
4634
4635 ExceptionInfo
4636 *exception;
4637
4638 Image
4639 *image;
4640
4641 long
4642 j;
4643
4644 register ssize_t
4645 i;
4646
4647 struct PackageInfo
4648 *info;
4649
4650 SV
4651 *perl_exception,
4652 *reference,
4653 *s;
4654
4655 PERL_UNUSED_VAR(ref);
4656 PERL_UNUSED_VAR(ix);
4657 exception=AcquireExceptionInfo();
4658 perl_exception=newSVpv("",0);
4659 if (sv_isobject(ST(0)) == 0)
4660 {
4661 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4662 PackageName);
4663 XSRETURN_EMPTY;
4664 }
4665 reference=SvRV(ST(0));
4666 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4667 if (image == (Image *) NULL && !info)
4668 XSRETURN_EMPTY;
4669 EXTEND(sp,items);
4670 for (i=1; i < items; i++)
4671 {
4672 attribute=(char *) SvPV(ST(i),na);
4673 s=NULL;
4674 switch (*attribute)
4675 {
4676 case 'A':
4677 case 'a':
4678 {
4679 if (LocaleCompare(attribute,"adjoin") == 0)
4680 {
4681 if (info)
4682 s=newSViv((ssize_t) info->image_info->adjoin);
4683 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4684 continue;
4685 }
4686 if (LocaleCompare(attribute,"antialias") == 0)
4687 {
4688 if (info)
4689 s=newSViv((ssize_t) info->image_info->antialias);
4690 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4691 continue;
4692 }
4693 if (LocaleCompare(attribute,"area") == 0)
4694 {
4695 s=newSViv(GetMagickResource(AreaResource));
4696 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4697 continue;
4698 }
4699 if (LocaleCompare(attribute,"attenuate") == 0)
4700 {
4701 const char
4702 *value;
4703
4704 value=GetImageProperty(image,attribute,exception);
4705 if (value != (const char *) NULL)
4706 s=newSVpv(value,0);
4707 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4708 continue;
4709 }
4710 if (LocaleCompare(attribute,"authenticate") == 0)
4711 {
4712 if (info)
4713 {
4714 const char
4715 *option;
4716
4717 option=GetImageOption(info->image_info,attribute);
4718 if (option != (const char *) NULL)
4719 s=newSVpv(option,0);
4720 }
4721 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4722 continue;
4723 }
4724 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4725 attribute);
4726 break;
4727 }
4728 case 'B':
4729 case 'b':
4730 {
4731 if (LocaleCompare(attribute,"background") == 0)
4732 {
4733 if (image == (Image *) NULL)
4734 break;
cristy151b66d2015-04-15 10:50:31 +00004735 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004736 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4737 (double) image->background_color.green,
4738 (double) image->background_color.blue,
4739 (double) image->background_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004740 s=newSVpv(color,0);
4741 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4742 continue;
4743 }
4744 if (LocaleCompare(attribute,"base-columns") == 0)
4745 {
4746 if (image != (Image *) NULL)
4747 s=newSViv((ssize_t) image->magick_columns);
4748 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4749 continue;
4750 }
4751 if (LocaleCompare(attribute,"base-filename") == 0)
4752 {
4753 if (image != (Image *) NULL)
4754 s=newSVpv(image->magick_filename,0);
4755 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4756 continue;
4757 }
4758 if (LocaleCompare(attribute,"base-height") == 0)
4759 {
4760 if (image != (Image *) NULL)
4761 s=newSViv((ssize_t) image->magick_rows);
4762 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4763 continue;
4764 }
4765 if (LocaleCompare(attribute,"base-rows") == 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-width") == 0)
4773 {
4774 if (image != (Image *) NULL)
4775 s=newSViv((ssize_t) image->magick_columns);
4776 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4777 continue;
4778 }
4779 if (LocaleCompare(attribute,"blue-primary") == 0)
4780 {
4781 if (image == (Image *) NULL)
4782 break;
Cristyb1710fe2017-02-11 13:51:48 -05004783 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00004784 image->chromaticity.blue_primary.x,
4785 image->chromaticity.blue_primary.y);
4786 s=newSVpv(color,0);
4787 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4788 continue;
4789 }
4790 if (LocaleCompare(attribute,"bordercolor") == 0)
4791 {
4792 if (image == (Image *) NULL)
4793 break;
cristy151b66d2015-04-15 10:50:31 +00004794 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004795 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4796 (double) image->border_color.green,
4797 (double) image->border_color.blue,
4798 (double) image->border_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004799 s=newSVpv(color,0);
4800 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4801 continue;
4802 }
4803 if (LocaleCompare(attribute,"bounding-box") == 0)
4804 {
4805 char
cristy151b66d2015-04-15 10:50:31 +00004806 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004807
4808 RectangleInfo
4809 page;
4810
4811 if (image == (Image *) NULL)
4812 break;
4813 page=GetImageBoundingBox(image,exception);
cristy151b66d2015-04-15 10:50:31 +00004814 (void) FormatLocaleString(geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00004815 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4816 page.height,(double) page.x,(double) page.y);
4817 s=newSVpv(geometry,0);
4818 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4819 continue;
4820 }
4821 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4822 attribute);
4823 break;
4824 }
4825 case 'C':
4826 case 'c':
4827 {
4828 if (LocaleCompare(attribute,"class") == 0)
4829 {
4830 if (image == (Image *) NULL)
4831 break;
4832 s=newSViv(image->storage_class);
4833 (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4834 image->storage_class));
4835 SvIOK_on(s);
4836 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4837 continue;
4838 }
4839 if (LocaleCompare(attribute,"clip-mask") == 0)
4840 {
4841 if (image != (Image *) NULL)
4842 {
4843 Image
4844 *mask_image;
4845
4846 SV
4847 *sv;
4848
4849 sv=NULL;
4850 if (image->read_mask == MagickFalse)
4851 ClipImage(image,exception);
Cristyda6b91a2016-01-11 16:05:27 -05004852 mask_image=GetImageMask(image,ReadPixelMask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004853 if (mask_image != (Image *) NULL)
4854 {
4855 AddImageToRegistry(sv,mask_image);
4856 s=sv_bless(newRV(sv),SvSTASH(reference));
4857 }
4858 }
4859 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4860 continue;
4861 }
4862 if (LocaleCompare(attribute,"clip-path") == 0)
4863 {
4864 if (image != (Image *) NULL)
4865 {
4866 Image
4867 *mask_image;
4868
4869 SV
4870 *sv;
4871
4872 sv=NULL;
4873 if (image->read_mask != MagickFalse)
4874 ClipImage(image,exception);
Cristyda6b91a2016-01-11 16:05:27 -05004875 mask_image=GetImageMask(image,ReadPixelMask,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004876 if (mask_image != (Image *) NULL)
4877 {
4878 AddImageToRegistry(sv,mask_image);
4879 s=sv_bless(newRV(sv),SvSTASH(reference));
4880 }
4881 }
4882 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4883 continue;
4884 }
4885 if (LocaleCompare(attribute,"compression") == 0)
4886 {
4887 j=info ? info->image_info->compression : image ?
4888 image->compression : UndefinedCompression;
4889 if (info)
4890 if (info->image_info->compression == UndefinedCompression)
4891 j=image->compression;
4892 s=newSViv(j);
4893 (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4894 j));
4895 SvIOK_on(s);
4896 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4897 continue;
4898 }
4899 if (LocaleCompare(attribute,"colorspace") == 0)
4900 {
4901 j=image ? image->colorspace : RGBColorspace;
4902 s=newSViv(j);
4903 (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4904 j));
4905 SvIOK_on(s);
4906 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4907 continue;
4908 }
4909 if (LocaleCompare(attribute,"colors") == 0)
4910 {
4911 if (image != (Image *) NULL)
4912 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4913 exception));
4914 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4915 continue;
4916 }
4917 if (LocaleNCompare(attribute,"colormap",8) == 0)
4918 {
4919 int
4920 items;
4921
4922 if (image == (Image *) NULL || !image->colormap)
4923 break;
4924 j=0;
4925 items=sscanf(attribute,"%*[^[][%ld",&j);
4926 (void) items;
4927 if (j > (ssize_t) image->colors)
4928 j%=image->colors;
cristy151b66d2015-04-15 10:50:31 +00004929 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00004930 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4931 (double) image->colormap[j].green,
4932 (double) image->colormap[j].blue,
4933 (double) image->colormap[j].alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00004934 s=newSVpv(color,0);
4935 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4936 continue;
4937 }
4938 if (LocaleCompare(attribute,"columns") == 0)
4939 {
4940 if (image != (Image *) NULL)
4941 s=newSViv((ssize_t) image->columns);
4942 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4943 continue;
4944 }
4945 if (LocaleCompare(attribute,"comment") == 0)
4946 {
4947 const char
4948 *value;
4949
Cristy935a4052017-03-31 17:45:37 -04004950 value=GetImageProperty(image,attribute,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00004951 if (value != (const char *) NULL)
4952 s=newSVpv(value,0);
4953 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4954 continue;
4955 }
4956 if (LocaleCompare(attribute,"copyright") == 0)
4957 {
4958 s=newSVpv(GetMagickCopyright(),0);
4959 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4960 continue;
4961 }
4962 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4963 attribute);
4964 break;
4965 }
4966 case 'D':
4967 case 'd':
4968 {
4969 if (LocaleCompare(attribute,"density") == 0)
4970 {
4971 char
cristy151b66d2015-04-15 10:50:31 +00004972 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00004973
4974 if (image == (Image *) NULL)
4975 break;
Cristyb1710fe2017-02-11 13:51:48 -05004976 (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00004977 image->resolution.x,image->resolution.y);
4978 s=newSVpv(geometry,0);
4979 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4980 continue;
4981 }
4982 if (LocaleCompare(attribute,"delay") == 0)
4983 {
4984 if (image != (Image *) NULL)
4985 s=newSViv((ssize_t) image->delay);
4986 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4987 continue;
4988 }
4989 if (LocaleCompare(attribute,"depth") == 0)
4990 {
4991 s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4992 if (image != (Image *) NULL)
4993 s=newSViv((ssize_t) GetImageDepth(image,exception));
4994 PUSHs(s ? sv_2mortal(s) : &sv_undef);
4995 continue;
4996 }
4997 if (LocaleCompare(attribute,"directory") == 0)
4998 {
4999 if (image && image->directory)
5000 s=newSVpv(image->directory,0);
5001 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5002 continue;
5003 }
5004 if (LocaleCompare(attribute,"dispose") == 0)
5005 {
5006 if (image == (Image *) NULL)
5007 break;
5008
5009 s=newSViv(image->dispose);
5010 (void) sv_setpv(s,
5011 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
5012 SvIOK_on(s);
5013 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5014 continue;
5015 }
5016 if (LocaleCompare(attribute,"disk") == 0)
5017 {
5018 s=newSViv(GetMagickResource(DiskResource));
5019 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5020 continue;
5021 }
5022 if (LocaleCompare(attribute,"dither") == 0)
5023 {
5024 if (info)
5025 s=newSViv((ssize_t) info->image_info->dither);
5026 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5027 continue;
5028 }
5029 if (LocaleCompare(attribute,"display") == 0) /* same as server */
5030 {
5031 if (info && info->image_info->server_name)
5032 s=newSVpv(info->image_info->server_name,0);
5033 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5034 continue;
5035 }
5036 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5037 attribute);
5038 break;
5039 }
5040 case 'E':
5041 case 'e':
5042 {
5043 if (LocaleCompare(attribute,"elapsed-time") == 0)
5044 {
5045 if (image != (Image *) NULL)
5046 s=newSVnv(GetElapsedTime(&image->timer));
5047 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5048 continue;
5049 }
5050 if (LocaleCompare(attribute,"endian") == 0)
5051 {
5052 j=info ? info->image_info->endian : image ? image->endian :
5053 UndefinedEndian;
5054 s=newSViv(j);
5055 (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
5056 SvIOK_on(s);
5057 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5058 continue;
5059 }
5060 if (LocaleCompare(attribute,"error") == 0)
5061 {
5062 if (image != (Image *) NULL)
5063 s=newSVnv(image->error.mean_error_per_pixel);
5064 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5065 continue;
5066 }
5067 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5068 attribute);
5069 break;
5070 }
5071 case 'F':
5072 case 'f':
5073 {
5074 if (LocaleCompare(attribute,"filesize") == 0)
5075 {
5076 if (image != (Image *) NULL)
5077 s=newSViv((ssize_t) GetBlobSize(image));
5078 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5079 continue;
5080 }
5081 if (LocaleCompare(attribute,"filename") == 0)
5082 {
Cristy2273d6a2017-07-14 19:19:55 -04005083 if (info && *info->image_info->filename)
cristy4a3ce0a2013-08-03 20:06:59 +00005084 s=newSVpv(info->image_info->filename,0);
5085 if (image != (Image *) NULL)
5086 s=newSVpv(image->filename,0);
5087 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5088 continue;
5089 }
5090 if (LocaleCompare(attribute,"filter") == 0)
5091 {
5092 s=image ? newSViv(image->filter) : newSViv(0);
5093 (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5094 image->filter));
5095 SvIOK_on(s);
5096 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5097 continue;
5098 }
5099 if (LocaleCompare(attribute,"font") == 0)
5100 {
5101 if (info && info->image_info->font)
5102 s=newSVpv(info->image_info->font,0);
5103 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5104 continue;
5105 }
5106 if (LocaleCompare(attribute,"foreground") == 0)
5107 continue;
5108 if (LocaleCompare(attribute,"format") == 0)
5109 {
5110 const MagickInfo
5111 *magick_info;
5112
5113 magick_info=(const MagickInfo *) NULL;
5114 if (info && (*info->image_info->magick != '\0'))
5115 magick_info=GetMagickInfo(info->image_info->magick,exception);
5116 if (image != (Image *) NULL)
5117 magick_info=GetMagickInfo(image->magick,exception);
5118 if ((magick_info != (const MagickInfo *) NULL) &&
5119 (*magick_info->description != '\0'))
5120 s=newSVpv((char *) magick_info->description,0);
5121 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5122 continue;
5123 }
5124 if (LocaleCompare(attribute,"fuzz") == 0)
5125 {
5126 if (info)
5127 s=newSVnv(info->image_info->fuzz);
5128 if (image != (Image *) NULL)
5129 s=newSVnv(image->fuzz);
5130 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5131 continue;
5132 }
5133 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5134 attribute);
5135 break;
5136 }
5137 case 'G':
5138 case 'g':
5139 {
5140 if (LocaleCompare(attribute,"gamma") == 0)
5141 {
5142 if (image != (Image *) NULL)
5143 s=newSVnv(image->gamma);
5144 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5145 continue;
5146 }
5147 if (LocaleCompare(attribute,"geometry") == 0)
5148 {
5149 if (image && image->geometry)
5150 s=newSVpv(image->geometry,0);
5151 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5152 continue;
5153 }
5154 if (LocaleCompare(attribute,"gravity") == 0)
5155 {
5156 s=image ? newSViv(image->gravity) : newSViv(0);
5157 (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5158 image->gravity));
5159 SvIOK_on(s);
5160 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5161 continue;
5162 }
5163 if (LocaleCompare(attribute,"green-primary") == 0)
5164 {
5165 if (image == (Image *) NULL)
5166 break;
Cristyb1710fe2017-02-11 13:51:48 -05005167 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005168 image->chromaticity.green_primary.x,
5169 image->chromaticity.green_primary.y);
5170 s=newSVpv(color,0);
5171 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5172 continue;
5173 }
5174 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5175 attribute);
5176 break;
5177 }
5178 case 'H':
5179 case 'h':
5180 {
5181 if (LocaleCompare(attribute,"height") == 0)
5182 {
5183 if (image != (Image *) NULL)
5184 s=newSViv((ssize_t) image->rows);
5185 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5186 continue;
5187 }
5188 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5189 attribute);
5190 break;
5191 }
5192 case 'I':
5193 case 'i':
5194 {
5195 if (LocaleCompare(attribute,"icc") == 0)
5196 {
5197 if (image != (Image *) NULL)
5198 {
5199 const StringInfo
5200 *profile;
5201
5202 profile=GetImageProfile(image,"icc");
5203 if (profile != (StringInfo *) NULL)
5204 s=newSVpv((const char *) GetStringInfoDatum(profile),
5205 GetStringInfoLength(profile));
5206 }
5207 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5208 continue;
5209 }
5210 if (LocaleCompare(attribute,"icm") == 0)
5211 {
5212 if (image != (Image *) NULL)
5213 {
5214 const StringInfo
5215 *profile;
5216
5217 profile=GetImageProfile(image,"icm");
5218 if (profile != (const StringInfo *) NULL)
5219 s=newSVpv((const char *) GetStringInfoDatum(profile),
5220 GetStringInfoLength(profile));
5221 }
5222 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5223 continue;
5224 }
5225 if (LocaleCompare(attribute,"id") == 0)
5226 {
5227 if (image != (Image *) NULL)
5228 {
5229 char
cristy151b66d2015-04-15 10:50:31 +00005230 key[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005231
5232 MagickBooleanType
5233 status;
5234
5235 static ssize_t
5236 id = 0;
5237
cristy151b66d2015-04-15 10:50:31 +00005238 (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
cristy4a3ce0a2013-08-03 20:06:59 +00005239 id);
5240 status=SetImageRegistry(ImageRegistryType,key,image,
5241 exception);
5242 (void) status;
5243 s=newSViv(id++);
5244 }
5245 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5246 continue;
5247 }
5248 if (LocaleNCompare(attribute,"index",5) == 0)
5249 {
5250 char
cristy151b66d2015-04-15 10:50:31 +00005251 name[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005252
5253 int
5254 items;
5255
5256 long
5257 x,
5258 y;
5259
5260 register const Quantum
5261 *p;
5262
5263 CacheView
5264 *image_view;
5265
5266 if (image == (Image *) NULL)
5267 break;
5268 if (image->storage_class != PseudoClass)
5269 break;
5270 x=0;
5271 y=0;
5272 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5273 (void) items;
5274 image_view=AcquireVirtualCacheView(image,exception);
5275 p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5276 if (p != (const Quantum *) NULL)
5277 {
cristy151b66d2015-04-15 10:50:31 +00005278 (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
cristy4a3ce0a2013-08-03 20:06:59 +00005279 GetPixelIndex(image,p));
5280 s=newSVpv(name,0);
5281 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5282 }
5283 image_view=DestroyCacheView(image_view);
5284 continue;
5285 }
5286 if (LocaleCompare(attribute,"iptc") == 0)
5287 {
5288 if (image != (Image *) NULL)
5289 {
5290 const StringInfo
5291 *profile;
5292
5293 profile=GetImageProfile(image,"iptc");
5294 if (profile != (const StringInfo *) NULL)
5295 s=newSVpv((const char *) GetStringInfoDatum(profile),
5296 GetStringInfoLength(profile));
5297 }
5298 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5299 continue;
5300 }
5301 if (LocaleCompare(attribute,"iterations") == 0) /* same as loop */
5302 {
5303 if (image != (Image *) NULL)
5304 s=newSViv((ssize_t) image->iterations);
5305 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5306 continue;
5307 }
5308 if (LocaleCompare(attribute,"interlace") == 0)
5309 {
5310 j=info ? info->image_info->interlace : image ? image->interlace :
5311 UndefinedInterlace;
5312 s=newSViv(j);
5313 (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5314 j));
5315 SvIOK_on(s);
5316 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5317 continue;
5318 }
5319 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5320 attribute);
5321 break;
5322 }
5323 case 'L':
5324 case 'l':
5325 {
5326 if (LocaleCompare(attribute,"label") == 0)
5327 {
5328 const char
5329 *value;
5330
5331 if (image == (Image *) NULL)
5332 break;
Cristy935a4052017-03-31 17:45:37 -04005333 value=GetImageProperty(image,"Label",exception);
cristy4a3ce0a2013-08-03 20:06:59 +00005334 if (value != (const char *) NULL)
5335 s=newSVpv(value,0);
5336 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5337 continue;
5338 }
5339 if (LocaleCompare(attribute,"loop") == 0) /* same as iterations */
5340 {
5341 if (image != (Image *) NULL)
5342 s=newSViv((ssize_t) image->iterations);
5343 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5344 continue;
5345 }
5346 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5347 attribute);
5348 break;
5349 }
5350 case 'M':
5351 case 'm':
5352 {
5353 if (LocaleCompare(attribute,"magick") == 0)
5354 {
5355 if (info && *info->image_info->magick)
5356 s=newSVpv(info->image_info->magick,0);
5357 if (image != (Image *) NULL)
5358 s=newSVpv(image->magick,0);
5359 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5360 continue;
5361 }
5362 if (LocaleCompare(attribute,"map") == 0)
5363 {
5364 s=newSViv(GetMagickResource(MapResource));
5365 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5366 continue;
5367 }
5368 if (LocaleCompare(attribute,"maximum-error") == 0)
5369 {
5370 if (image != (Image *) NULL)
5371 s=newSVnv(image->error.normalized_maximum_error);
5372 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5373 continue;
5374 }
5375 if (LocaleCompare(attribute,"memory") == 0)
5376 {
5377 s=newSViv(GetMagickResource(MemoryResource));
5378 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5379 continue;
5380 }
5381 if (LocaleCompare(attribute,"mean-error") == 0)
5382 {
5383 if (image != (Image *) NULL)
5384 s=newSVnv(image->error.normalized_mean_error);
5385 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5386 continue;
5387 }
5388 if (LocaleCompare(attribute,"mime") == 0)
5389 {
5390 if (info && *info->image_info->magick)
5391 s=newSVpv(MagickToMime(info->image_info->magick),0);
5392 if (image != (Image *) NULL)
5393 s=newSVpv(MagickToMime(image->magick),0);
5394 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5395 continue;
5396 }
5397 if (LocaleCompare(attribute,"mattecolor") == 0)
5398 {
5399 if (image == (Image *) NULL)
5400 break;
cristy151b66d2015-04-15 10:50:31 +00005401 (void) FormatLocaleString(color,MagickPathExtent,
Cristy8645e042016-02-03 16:35:29 -05005402 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5403 (double) image->alpha_color.green,
5404 (double) image->alpha_color.blue,
5405 (double) image->alpha_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00005406 s=newSVpv(color,0);
5407 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5408 continue;
5409 }
5410 if (LocaleCompare(attribute,"matte") == 0)
5411 {
5412 if (image != (Image *) NULL)
cristy17f11b02014-12-20 19:37:04 +00005413 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
cristy4a3ce0a2013-08-03 20:06:59 +00005414 1 : 0);
5415 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5416 continue;
5417 }
5418 if (LocaleCompare(attribute,"mime") == 0)
5419 {
5420 const char
5421 *magick;
5422
5423 magick=NULL;
5424 if (info && *info->image_info->magick)
5425 magick=info->image_info->magick;
5426 if (image != (Image *) NULL)
5427 magick=image->magick;
5428 if (magick)
5429 {
5430 char
5431 *mime;
5432
5433 mime=MagickToMime(magick);
5434 s=newSVpv(mime,0);
5435 mime=(char *) RelinquishMagickMemory(mime);
5436 }
5437 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5438 continue;
5439 }
5440 if (LocaleCompare(attribute,"monochrome") == 0)
5441 {
5442 if (image == (Image *) NULL)
5443 continue;
5444 j=info ? info->image_info->monochrome :
cristy932cb072015-04-13 20:06:25 +00005445 SetImageMonochrome(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00005446 s=newSViv(j);
5447 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5448 continue;
5449 }
5450 if (LocaleCompare(attribute,"montage") == 0)
5451 {
5452 if (image && image->montage)
5453 s=newSVpv(image->montage,0);
5454 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5455 continue;
5456 }
5457 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5458 attribute);
5459 break;
5460 }
5461 case 'O':
5462 case 'o':
5463 {
5464 if (LocaleCompare(attribute,"orientation") == 0)
5465 {
5466 j=info ? info->image_info->orientation : image ?
5467 image->orientation : UndefinedOrientation;
5468 s=newSViv(j);
5469 (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5470 j));
5471 SvIOK_on(s);
5472 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5473 continue;
5474 }
5475 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5476 attribute);
5477 break;
5478 }
5479 case 'P':
5480 case 'p':
5481 {
5482 if (LocaleCompare(attribute,"page") == 0)
5483 {
5484 if (info && info->image_info->page)
5485 s=newSVpv(info->image_info->page,0);
5486 if (image != (Image *) NULL)
5487 {
5488 char
cristy151b66d2015-04-15 10:50:31 +00005489 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005490
cristy151b66d2015-04-15 10:50:31 +00005491 (void) FormatLocaleString(geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00005492 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5493 (double) image->page.height,(double) image->page.x,(double)
5494 image->page.y);
5495 s=newSVpv(geometry,0);
5496 }
5497 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5498 continue;
5499 }
5500 if (LocaleCompare(attribute,"page.x") == 0)
5501 {
5502 if (image != (Image *) NULL)
5503 s=newSViv((ssize_t) image->page.x);
5504 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5505 continue;
5506 }
5507 if (LocaleCompare(attribute,"page.y") == 0)
5508 {
5509 if (image != (Image *) NULL)
5510 s=newSViv((ssize_t) image->page.y);
5511 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5512 continue;
5513 }
5514 if (LocaleNCompare(attribute,"pixel",5) == 0)
5515 {
5516 char
cristy151b66d2015-04-15 10:50:31 +00005517 tuple[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00005518
5519 int
5520 items;
5521
5522 long
5523 x,
5524 y;
5525
5526 register const Quantum
5527 *p;
5528
5529 if (image == (Image *) NULL)
5530 break;
5531 x=0;
5532 y=0;
5533 items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5534 (void) items;
5535 p=GetVirtualPixels(image,x,y,1,1,exception);
5536 if (image->colorspace != CMYKColorspace)
cristy151b66d2015-04-15 10:50:31 +00005537 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
cristy4a3ce0a2013-08-03 20:06:59 +00005538 QuantumFormat "," QuantumFormat "," QuantumFormat,
5539 GetPixelRed(image,p),GetPixelGreen(image,p),
5540 GetPixelBlue(image,p),GetPixelAlpha(image,p));
5541 else
cristy151b66d2015-04-15 10:50:31 +00005542 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
cristy4a3ce0a2013-08-03 20:06:59 +00005543 QuantumFormat "," QuantumFormat "," QuantumFormat ","
5544 QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5545 GetPixelBlue(image,p),GetPixelBlack(image,p),
5546 GetPixelAlpha(image,p));
5547 s=newSVpv(tuple,0);
5548 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5549 continue;
5550 }
5551 if (LocaleCompare(attribute,"pointsize") == 0)
5552 {
5553 if (info)
5554 s=newSViv((ssize_t) info->image_info->pointsize);
5555 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5556 continue;
5557 }
cristy4a3ce0a2013-08-03 20:06:59 +00005558 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5559 attribute);
5560 break;
5561 }
5562 case 'Q':
5563 case 'q':
5564 {
5565 if (LocaleCompare(attribute,"quality") == 0)
5566 {
5567 if (info)
5568 s=newSViv((ssize_t) info->image_info->quality);
5569 if (image != (Image *) NULL)
5570 s=newSViv((ssize_t) image->quality);
5571 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5572 continue;
5573 }
5574 if (LocaleCompare(attribute,"quantum") == 0)
5575 {
5576 if (info)
5577 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5578 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5579 continue;
5580 }
5581 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5582 attribute);
5583 break;
5584 }
5585 case 'R':
5586 case 'r':
5587 {
5588 if (LocaleCompare(attribute,"rendering-intent") == 0)
5589 {
5590 s=newSViv(image->rendering_intent);
5591 (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5592 image->rendering_intent));
5593 SvIOK_on(s);
5594 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5595 continue;
5596 }
5597 if (LocaleCompare(attribute,"red-primary") == 0)
5598 {
5599 if (image == (Image *) NULL)
5600 break;
Cristyb1710fe2017-02-11 13:51:48 -05005601 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005602 image->chromaticity.red_primary.x,
5603 image->chromaticity.red_primary.y);
5604 s=newSVpv(color,0);
5605 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5606 continue;
5607 }
5608 if (LocaleCompare(attribute,"rows") == 0)
5609 {
5610 if (image != (Image *) NULL)
5611 s=newSViv((ssize_t) image->rows);
5612 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5613 continue;
5614 }
5615 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5616 attribute);
5617 break;
5618 }
5619 case 'S':
5620 case 's':
5621 {
5622 if (LocaleCompare(attribute,"sampling-factor") == 0)
5623 {
5624 if (info && info->image_info->sampling_factor)
5625 s=newSVpv(info->image_info->sampling_factor,0);
5626 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5627 continue;
5628 }
5629 if (LocaleCompare(attribute,"server") == 0) /* same as display */
5630 {
5631 if (info && info->image_info->server_name)
5632 s=newSVpv(info->image_info->server_name,0);
5633 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5634 continue;
5635 }
5636 if (LocaleCompare(attribute,"size") == 0)
5637 {
5638 if (info && info->image_info->size)
5639 s=newSVpv(info->image_info->size,0);
5640 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5641 continue;
5642 }
5643 if (LocaleCompare(attribute,"scene") == 0)
5644 {
5645 if (image != (Image *) NULL)
5646 s=newSViv((ssize_t) image->scene);
5647 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5648 continue;
5649 }
5650 if (LocaleCompare(attribute,"scenes") == 0)
5651 {
5652 if (image != (Image *) NULL)
5653 s=newSViv((ssize_t) info->image_info->number_scenes);
5654 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5655 continue;
5656 }
5657 if (LocaleCompare(attribute,"signature") == 0)
5658 {
5659 const char
5660 *value;
5661
5662 if (image == (Image *) NULL)
5663 break;
5664 (void) SignatureImage(image,exception);
5665 value=GetImageProperty(image,"Signature",exception);
5666 if (value != (const char *) NULL)
5667 s=newSVpv(value,0);
5668 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5669 continue;
5670 }
5671 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5672 attribute);
5673 break;
5674 }
5675 case 'T':
5676 case 't':
5677 {
5678 if (LocaleCompare(attribute,"taint") == 0)
5679 {
5680 if (image != (Image *) NULL)
5681 s=newSViv((ssize_t) IsTaintImage(image));
5682 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5683 continue;
5684 }
5685 if (LocaleCompare(attribute,"texture") == 0)
5686 {
5687 if (info && info->image_info->texture)
5688 s=newSVpv(info->image_info->texture,0);
5689 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5690 continue;
5691 }
5692 if (LocaleCompare(attribute,"total-ink-density") == 0)
5693 {
5694 s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5695 if (image != (Image *) NULL)
5696 s=newSVnv(GetImageTotalInkDensity(image,exception));
5697 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5698 continue;
5699 }
5700 if (LocaleCompare(attribute,"transparent-color") == 0)
5701 {
5702 if (image == (Image *) NULL)
5703 break;
cristy151b66d2015-04-15 10:50:31 +00005704 (void) FormatLocaleString(color,MagickPathExtent,
cristyaa659162014-08-26 11:35:47 +00005705 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5706 (double) image->transparent_color.green,
5707 (double) image->transparent_color.blue,
5708 (double) image->transparent_color.alpha);
cristy4a3ce0a2013-08-03 20:06:59 +00005709 s=newSVpv(color,0);
5710 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5711 continue;
5712 }
5713 if (LocaleCompare(attribute,"type") == 0)
5714 {
5715 if (image == (Image *) NULL)
5716 break;
cristya26f54c2015-07-29 12:26:12 +00005717 j=(ssize_t) GetImageType(image);
cristy4a3ce0a2013-08-03 20:06:59 +00005718 s=newSViv(j);
5719 (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5720 SvIOK_on(s);
5721 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5722 continue;
5723 }
5724 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5725 attribute);
5726 break;
5727 }
5728 case 'U':
5729 case 'u':
5730 {
5731 if (LocaleCompare(attribute,"units") == 0)
5732 {
5733 j=info ? info->image_info->units : image ? image->units :
5734 UndefinedResolution;
5735 if (info && (info->image_info->units == UndefinedResolution))
5736 if (image)
5737 j=image->units;
5738 if (j == UndefinedResolution)
5739 s=newSVpv("undefined units",0);
5740 else
5741 if (j == PixelsPerInchResolution)
5742 s=newSVpv("pixels / inch",0);
5743 else
5744 s=newSVpv("pixels / centimeter",0);
5745 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5746 continue;
5747 }
5748 if (LocaleCompare(attribute,"user-time") == 0)
5749 {
5750 if (image != (Image *) NULL)
5751 s=newSVnv(GetUserTime(&image->timer));
5752 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5753 continue;
5754 }
5755 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5756 attribute);
5757 break;
5758 }
5759 case 'V':
5760 case 'v':
5761 {
5762 if (LocaleCompare(attribute,"verbose") == 0)
5763 {
5764 if (info)
5765 s=newSViv((ssize_t) info->image_info->verbose);
5766 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5767 continue;
5768 }
5769 if (LocaleCompare(attribute,"version") == 0)
5770 {
5771 s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5772 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5773 continue;
5774 }
cristy4a3ce0a2013-08-03 20:06:59 +00005775 if (LocaleCompare(attribute,"virtual-pixel") == 0)
5776 {
5777 if (image == (Image *) NULL)
5778 break;
5779 j=(ssize_t) GetImageVirtualPixelMethod(image);
5780 s=newSViv(j);
5781 (void) sv_setpv(s,CommandOptionToMnemonic(
5782 MagickVirtualPixelOptions,j));
5783 SvIOK_on(s);
5784 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5785 continue;
5786 }
5787 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5788 attribute);
5789 break;
5790 }
5791 case 'W':
5792 case 'w':
5793 {
5794 if (LocaleCompare(attribute,"white-point") == 0)
5795 {
5796 if (image == (Image *) NULL)
5797 break;
Cristyb1710fe2017-02-11 13:51:48 -05005798 (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00005799 image->chromaticity.white_point.x,
5800 image->chromaticity.white_point.y);
5801 s=newSVpv(color,0);
5802 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5803 continue;
5804 }
5805 if (LocaleCompare(attribute,"width") == 0)
5806 {
5807 if (image != (Image *) NULL)
5808 s=newSViv((ssize_t) image->columns);
5809 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5810 continue;
5811 }
5812 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5813 attribute);
5814 break;
5815 }
5816 case 'X':
5817 case 'x':
5818 {
Cristyc1f9f9f2016-01-05 08:19:28 -05005819 if (LocaleCompare(attribute,"xmp") == 0)
5820 {
5821 if (image != (Image *) NULL)
5822 {
5823 const StringInfo
5824 *profile;
5825
5826 profile=GetImageProfile(image,"xmp");
5827 if (profile != (StringInfo *) NULL)
5828 s=newSVpv((const char *) GetStringInfoDatum(profile),
5829 GetStringInfoLength(profile));
5830 }
5831 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5832 continue;
5833 }
cristy4a3ce0a2013-08-03 20:06:59 +00005834 if (LocaleCompare(attribute,"x-resolution") == 0)
5835 {
5836 if (image != (Image *) NULL)
5837 s=newSVnv(image->resolution.x);
5838 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5839 continue;
5840 }
5841 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5842 attribute);
5843 break;
5844 }
5845 case 'Y':
5846 case 'y':
5847 {
5848 if (LocaleCompare(attribute,"y-resolution") == 0)
5849 {
5850 if (image != (Image *) NULL)
5851 s=newSVnv(image->resolution.y);
5852 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5853 continue;
5854 }
5855 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5856 attribute);
5857 break;
5858 }
5859 default:
5860 break;
5861 }
5862 if (image == (Image *) NULL)
5863 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5864 attribute)
5865 else
5866 {
5867 value=GetImageProperty(image,attribute,exception);
5868 if (value != (const char *) NULL)
5869 {
5870 s=newSVpv(value,0);
5871 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5872 }
5873 else
5874 if (*attribute != '%')
5875 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5876 attribute)
5877 else
5878 {
5879 char
5880 *meta;
5881
5882 meta=InterpretImageProperties(info ? info->image_info :
5883 (ImageInfo *) NULL,image,attribute,exception);
5884 s=newSVpv(meta,0);
5885 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5886 meta=(char *) RelinquishMagickMemory(meta);
5887 }
5888 }
5889 }
5890 exception=DestroyExceptionInfo(exception);
5891 SvREFCNT_dec(perl_exception); /* can't return warning messages */
5892 }
5893
5894#
5895###############################################################################
5896# #
5897# #
5898# #
5899# G e t A u t h e n t i c P i x e l s #
5900# #
5901# #
5902# #
5903###############################################################################
5904#
5905#
5906void *
5907GetAuthenticPixels(ref,...)
5908 Image::Magick ref = NO_INIT
5909 ALIAS:
5910 getauthenticpixels = 1
5911 GetImagePixels = 2
5912 getimagepixels = 3
5913 CODE:
5914 {
5915 char
5916 *attribute;
5917
5918 ExceptionInfo
5919 *exception;
5920
5921 Image
5922 *image;
5923
5924 RectangleInfo
5925 region;
5926
5927 ssize_t
5928 i;
5929
5930 struct PackageInfo
5931 *info;
5932
5933 SV
5934 *perl_exception,
5935 *reference;
5936
5937 void
5938 *blob = NULL;
5939
5940 PERL_UNUSED_VAR(ref);
5941 PERL_UNUSED_VAR(ix);
5942 exception=AcquireExceptionInfo();
5943 perl_exception=newSVpv("",0);
5944 if (sv_isobject(ST(0)) == 0)
5945 {
5946 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5947 PackageName);
5948 goto PerlException;
5949 }
5950 reference=SvRV(ST(0));
5951
5952 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5953 if (image == (Image *) NULL)
5954 {
5955 ThrowPerlException(exception,OptionError,"NoImagesDefined",
5956 PackageName);
5957 goto PerlException;
5958 }
5959
5960 region.x=0;
5961 region.y=0;
5962 region.width=image->columns;
5963 region.height=1;
5964 if (items == 1)
5965 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5966 for (i=2; i < items; i+=2)
5967 {
5968 attribute=(char *) SvPV(ST(i-1),na);
5969 switch (*attribute)
5970 {
5971 case 'g':
5972 case 'G':
5973 {
5974 if (LocaleCompare(attribute,"geometry") == 0)
5975 {
5976 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5977 break;
5978 }
5979 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5980 attribute);
5981 break;
5982 }
5983 case 'H':
5984 case 'h':
5985 {
5986 if (LocaleCompare(attribute,"height") == 0)
5987 {
5988 region.height=SvIV(ST(i));
5989 continue;
5990 }
5991 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5992 attribute);
5993 break;
5994 }
5995 case 'X':
5996 case 'x':
5997 {
5998 if (LocaleCompare(attribute,"x") == 0)
5999 {
6000 region.x=SvIV(ST(i));
6001 continue;
6002 }
6003 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6004 attribute);
6005 break;
6006 }
6007 case 'Y':
6008 case 'y':
6009 {
6010 if (LocaleCompare(attribute,"y") == 0)
6011 {
6012 region.y=SvIV(ST(i));
6013 continue;
6014 }
6015 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6016 attribute);
6017 break;
6018 }
6019 case 'W':
6020 case 'w':
6021 {
6022 if (LocaleCompare(attribute,"width") == 0)
6023 {
6024 region.width=SvIV(ST(i));
6025 continue;
6026 }
6027 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6028 attribute);
6029 break;
6030 }
6031 }
6032 }
6033 blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
6034 region.height,exception);
6035 if (blob != (void *) NULL)
6036 goto PerlEnd;
6037
6038 PerlException:
6039 InheritPerlException(exception,perl_exception);
6040 exception=DestroyExceptionInfo(exception);
6041 SvREFCNT_dec(perl_exception); /* throw away all errors */
6042
6043 PerlEnd:
6044 RETVAL = blob;
6045 }
6046 OUTPUT:
6047 RETVAL
6048
6049#
6050###############################################################################
6051# #
6052# #
6053# #
6054# G e t V i r t u a l P i x e l s #
6055# #
6056# #
6057# #
6058###############################################################################
6059#
6060#
6061void *
6062GetVirtualPixels(ref,...)
6063 Image::Magick ref = NO_INIT
6064 ALIAS:
6065 getvirtualpixels = 1
6066 AcquireImagePixels = 2
6067 acquireimagepixels = 3
6068 CODE:
6069 {
6070 char
6071 *attribute;
6072
6073 const void
6074 *blob = NULL;
6075
6076 ExceptionInfo
6077 *exception;
6078
6079 Image
6080 *image;
6081
6082 RectangleInfo
6083 region;
6084
6085 ssize_t
6086 i;
6087
6088 struct PackageInfo
6089 *info;
6090
6091 SV
6092 *perl_exception,
6093 *reference;
6094
6095 PERL_UNUSED_VAR(ref);
6096 PERL_UNUSED_VAR(ix);
6097 exception=AcquireExceptionInfo();
6098 perl_exception=newSVpv("",0);
6099 if (sv_isobject(ST(0)) == 0)
6100 {
6101 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6102 PackageName);
6103 goto PerlException;
6104 }
6105 reference=SvRV(ST(0));
6106
6107 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6108 if (image == (Image *) NULL)
6109 {
6110 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6111 PackageName);
6112 goto PerlException;
6113 }
6114
6115 region.x=0;
6116 region.y=0;
6117 region.width=image->columns;
6118 region.height=1;
6119 if (items == 1)
6120 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6121 for (i=2; i < items; i+=2)
6122 {
6123 attribute=(char *) SvPV(ST(i-1),na);
6124 switch (*attribute)
6125 {
6126 case 'g':
6127 case 'G':
6128 {
6129 if (LocaleCompare(attribute,"geometry") == 0)
6130 {
6131 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6132 break;
6133 }
6134 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6135 attribute);
6136 break;
6137 }
6138 case 'H':
6139 case 'h':
6140 {
6141 if (LocaleCompare(attribute,"height") == 0)
6142 {
6143 region.height=SvIV(ST(i));
6144 continue;
6145 }
6146 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6147 attribute);
6148 break;
6149 }
6150 case 'X':
6151 case 'x':
6152 {
6153 if (LocaleCompare(attribute,"x") == 0)
6154 {
6155 region.x=SvIV(ST(i));
6156 continue;
6157 }
6158 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6159 attribute);
6160 break;
6161 }
6162 case 'Y':
6163 case 'y':
6164 {
6165 if (LocaleCompare(attribute,"y") == 0)
6166 {
6167 region.y=SvIV(ST(i));
6168 continue;
6169 }
6170 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6171 attribute);
6172 break;
6173 }
6174 case 'W':
6175 case 'w':
6176 {
6177 if (LocaleCompare(attribute,"width") == 0)
6178 {
6179 region.width=SvIV(ST(i));
6180 continue;
6181 }
6182 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6183 attribute);
6184 break;
6185 }
6186 }
6187 }
6188 blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6189 region.height,exception);
6190 if (blob != (void *) NULL)
6191 goto PerlEnd;
6192
6193 PerlException:
6194 InheritPerlException(exception,perl_exception);
6195 exception=DestroyExceptionInfo(exception);
6196 SvREFCNT_dec(perl_exception); /* throw away all errors */
6197
6198 PerlEnd:
6199 RETVAL = (void *) blob;
6200 }
6201 OUTPUT:
6202 RETVAL
6203
6204#
6205###############################################################################
6206# #
6207# #
6208# #
6209# G e t A u t h e n t i c M e t a c o n t e n t #
6210# #
6211# #
6212# #
6213###############################################################################
6214#
6215#
6216void *
6217GetAuthenticMetacontent(ref,...)
6218 Image::Magick ref = NO_INIT
6219 ALIAS:
6220 getauthenticmetacontent = 1
6221 GetMetacontent = 2
6222 getmetacontent = 3
6223 CODE:
6224 {
6225 ExceptionInfo
6226 *exception;
6227
6228 Image
6229 *image;
6230
6231 struct PackageInfo
6232 *info;
6233
6234 SV
6235 *perl_exception,
6236 *reference;
6237
6238 void
6239 *blob = NULL;
6240
6241 PERL_UNUSED_VAR(ref);
6242 PERL_UNUSED_VAR(ix);
6243 exception=AcquireExceptionInfo();
6244 perl_exception=newSVpv("",0);
6245 if (sv_isobject(ST(0)) == 0)
6246 {
6247 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6248 PackageName);
6249 goto PerlException;
6250 }
6251 reference=SvRV(ST(0));
6252
6253 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6254 if (image == (Image *) NULL)
6255 {
6256 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6257 PackageName);
6258 goto PerlException;
6259 }
6260
6261 blob=(void *) GetAuthenticMetacontent(image);
6262 if (blob != (void *) NULL)
6263 goto PerlEnd;
6264
6265 PerlException:
6266 InheritPerlException(exception,perl_exception);
6267 exception=DestroyExceptionInfo(exception);
6268 SvREFCNT_dec(perl_exception); /* throw away all errors */
6269
6270 PerlEnd:
6271 RETVAL = blob;
6272 }
6273 OUTPUT:
6274 RETVAL
6275
6276#
6277###############################################################################
6278# #
6279# #
6280# #
6281# G e t V i r t u a l M e t a c o n t e n t #
6282# #
6283# #
6284# #
6285###############################################################################
6286#
6287#
6288void *
6289GetVirtualMetacontent(ref,...)
6290 Image::Magick ref = NO_INIT
6291 ALIAS:
6292 getvirtualmetacontent = 1
6293 CODE:
6294 {
6295 ExceptionInfo
6296 *exception;
6297
6298 Image
6299 *image;
6300
6301 struct PackageInfo
6302 *info;
6303
6304 SV
6305 *perl_exception,
6306 *reference;
6307
6308 void
6309 *blob = NULL;
6310
6311 PERL_UNUSED_VAR(ref);
6312 PERL_UNUSED_VAR(ix);
6313 exception=AcquireExceptionInfo();
6314 perl_exception=newSVpv("",0);
6315 if (sv_isobject(ST(0)) == 0)
6316 {
6317 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6318 PackageName);
6319 goto PerlException;
6320 }
6321 reference=SvRV(ST(0));
6322
6323 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6324 if (image == (Image *) NULL)
6325 {
6326 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6327 PackageName);
6328 goto PerlException;
6329 }
6330
6331 blob=(void *) GetVirtualMetacontent(image);
6332 if (blob != (void *) NULL)
6333 goto PerlEnd;
6334
6335 PerlException:
6336 InheritPerlException(exception,perl_exception);
6337 exception=DestroyExceptionInfo(exception);
6338 SvREFCNT_dec(perl_exception); /* throw away all errors */
6339
6340 PerlEnd:
6341 RETVAL = blob;
6342 }
6343 OUTPUT:
6344 RETVAL
6345
6346#
6347###############################################################################
6348# #
6349# #
6350# #
6351# H i s t o g r a m #
6352# #
6353# #
6354# #
6355###############################################################################
6356#
6357#
6358void
6359Histogram(ref,...)
6360 Image::Magick ref=NO_INIT
6361 ALIAS:
6362 HistogramImage = 1
6363 histogram = 2
6364 histogramimage = 3
6365 PPCODE:
6366 {
6367 AV
6368 *av;
6369
6370 char
cristy151b66d2015-04-15 10:50:31 +00006371 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00006372
6373 PixelInfo
6374 *histogram;
6375
6376 ExceptionInfo
6377 *exception;
6378
6379 Image
6380 *image;
6381
6382 register ssize_t
6383 i;
6384
6385 ssize_t
6386 count;
6387
6388 struct PackageInfo
6389 *info;
6390
6391 SV
6392 *perl_exception,
6393 *reference;
6394
6395 size_t
6396 number_colors;
6397
6398 PERL_UNUSED_VAR(ref);
6399 PERL_UNUSED_VAR(ix);
6400 exception=AcquireExceptionInfo();
6401 perl_exception=newSVpv("",0);
6402 av=NULL;
6403 if (sv_isobject(ST(0)) == 0)
6404 {
6405 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6406 PackageName);
6407 goto PerlException;
6408 }
6409 reference=SvRV(ST(0));
6410 av=newAV();
6411 SvREFCNT_dec(av);
6412 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6413 if (image == (Image *) NULL)
6414 {
6415 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6416 PackageName);
6417 goto PerlException;
6418 }
cristy4a3ce0a2013-08-03 20:06:59 +00006419 count=0;
6420 for ( ; image; image=image->next)
6421 {
6422 histogram=GetImageHistogram(image,&number_colors,exception);
6423 if (histogram == (PixelInfo *) NULL)
6424 continue;
6425 count+=(ssize_t) number_colors;
6426 EXTEND(sp,6*count);
6427 for (i=0; i < (ssize_t) number_colors; i++)
6428 {
cristy151b66d2015-04-15 10:50:31 +00006429 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006430 histogram[i].red);
6431 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006432 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006433 histogram[i].green);
6434 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006435 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006436 histogram[i].blue);
6437 PUSHs(sv_2mortal(newSVpv(message,0)));
6438 if (image->colorspace == CMYKColorspace)
6439 {
cristy151b66d2015-04-15 10:50:31 +00006440 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006441 histogram[i].black);
6442 PUSHs(sv_2mortal(newSVpv(message,0)));
6443 }
cristy151b66d2015-04-15 10:50:31 +00006444 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
cristy4a3ce0a2013-08-03 20:06:59 +00006445 histogram[i].alpha);
6446 PUSHs(sv_2mortal(newSVpv(message,0)));
cristy151b66d2015-04-15 10:50:31 +00006447 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
cristy4a3ce0a2013-08-03 20:06:59 +00006448 histogram[i].count);
6449 PUSHs(sv_2mortal(newSVpv(message,0)));
6450 }
6451 histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6452 }
6453
6454 PerlException:
6455 InheritPerlException(exception,perl_exception);
6456 exception=DestroyExceptionInfo(exception);
6457 SvREFCNT_dec(perl_exception);
6458 }
6459
6460#
6461###############################################################################
6462# #
6463# #
6464# #
6465# G e t P i x e l #
6466# #
6467# #
6468# #
6469###############################################################################
6470#
6471#
6472void
6473GetPixel(ref,...)
6474 Image::Magick ref=NO_INIT
6475 ALIAS:
6476 getpixel = 1
6477 getPixel = 2
6478 PPCODE:
6479 {
6480 AV
6481 *av;
6482
6483 char
6484 *attribute;
6485
6486 ExceptionInfo
6487 *exception;
6488
6489 Image
6490 *image;
6491
6492 MagickBooleanType
6493 normalize;
6494
6495 RectangleInfo
6496 region;
6497
6498 register const Quantum
6499 *p;
6500
6501 register ssize_t
6502 i;
6503
6504 ssize_t
6505 option;
6506
6507 struct PackageInfo
6508 *info;
6509
6510 SV
6511 *perl_exception,
6512 *reference; /* reference is the SV* of ref=SvIV(reference) */
6513
6514 PERL_UNUSED_VAR(ref);
6515 PERL_UNUSED_VAR(ix);
6516 exception=AcquireExceptionInfo();
6517 perl_exception=newSVpv("",0);
6518 reference=SvRV(ST(0));
6519 av=(AV *) reference;
6520 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6521 exception);
6522 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6523 if (image == (Image *) NULL)
6524 {
6525 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6526 PackageName);
6527 goto PerlException;
6528 }
6529 normalize=MagickTrue;
6530 region.x=0;
6531 region.y=0;
6532 region.width=image->columns;
6533 region.height=1;
6534 if (items == 1)
6535 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6536 for (i=2; i < items; i+=2)
6537 {
6538 attribute=(char *) SvPV(ST(i-1),na);
6539 switch (*attribute)
6540 {
6541 case 'C':
6542 case 'c':
6543 {
6544 if (LocaleCompare(attribute,"channel") == 0)
6545 {
6546 ssize_t
6547 option;
6548
6549 option=ParseChannelOption(SvPV(ST(i),na));
6550 if (option < 0)
6551 {
6552 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6553 SvPV(ST(i),na));
6554 return;
6555 }
cristybcd59342015-06-07 14:07:19 +00006556 (void) SetPixelChannelMask(image,(ChannelType) option);
cristy4a3ce0a2013-08-03 20:06:59 +00006557 break;
6558 }
6559 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6560 attribute);
6561 break;
6562 }
6563 case 'g':
6564 case 'G':
6565 {
6566 if (LocaleCompare(attribute,"geometry") == 0)
6567 {
6568 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6569 break;
6570 }
6571 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6572 attribute);
6573 break;
6574 }
6575 case 'N':
6576 case 'n':
6577 {
6578 if (LocaleCompare(attribute,"normalize") == 0)
6579 {
6580 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6581 SvPV(ST(i),na));
6582 if (option < 0)
6583 {
6584 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6585 SvPV(ST(i),na));
6586 break;
6587 }
6588 normalize=option != 0 ? MagickTrue : MagickFalse;
6589 break;
6590 }
6591 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6592 attribute);
6593 break;
6594 }
6595 case 'x':
6596 case 'X':
6597 {
6598 if (LocaleCompare(attribute,"x") == 0)
6599 {
6600 region.x=SvIV(ST(i));
6601 break;
6602 }
6603 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6604 attribute);
6605 break;
6606 }
6607 case 'y':
6608 case 'Y':
6609 {
6610 if (LocaleCompare(attribute,"y") == 0)
6611 {
6612 region.y=SvIV(ST(i));
6613 break;
6614 }
6615 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6616 attribute);
6617 break;
6618 }
6619 default:
6620 {
6621 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6622 attribute);
6623 break;
6624 }
6625 }
6626 }
6627 p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6628 if (p == (const Quantum *) NULL)
6629 PUSHs(&sv_undef);
6630 else
6631 {
6632 double
6633 scale;
6634
6635 scale=1.0;
6636 if (normalize != MagickFalse)
6637 scale=1.0/QuantumRange;
6638 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6639 PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6640 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6641 PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6642 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6643 PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6644 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6645 (image->colorspace == CMYKColorspace))
6646 PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6647 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6648 PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6649 }
6650
6651 PerlException:
6652 InheritPerlException(exception,perl_exception);
6653 exception=DestroyExceptionInfo(exception);
6654 SvREFCNT_dec(perl_exception);
6655 }
6656
6657#
6658###############################################################################
6659# #
6660# #
6661# #
6662# G e t P i x e l s #
6663# #
6664# #
6665# #
6666###############################################################################
6667#
6668#
6669void
6670GetPixels(ref,...)
6671 Image::Magick ref=NO_INIT
6672 ALIAS:
6673 getpixels = 1
6674 getPixels = 2
6675 PPCODE:
6676 {
6677 AV
6678 *av;
6679
6680 char
6681 *attribute;
6682
6683 const char
6684 *map;
6685
6686 ExceptionInfo
6687 *exception;
6688
6689 Image
6690 *image;
6691
6692 MagickBooleanType
6693 normalize,
6694 status;
6695
6696 RectangleInfo
6697 region;
6698
6699 register ssize_t
6700 i;
6701
6702 ssize_t
6703 option;
6704
6705 struct PackageInfo
6706 *info;
6707
6708 SV
6709 *perl_exception,
6710 *reference; /* reference is the SV* of ref=SvIV(reference) */
6711
6712 PERL_UNUSED_VAR(ref);
6713 PERL_UNUSED_VAR(ix);
6714 exception=AcquireExceptionInfo();
6715 perl_exception=newSVpv("",0);
6716 reference=SvRV(ST(0));
6717 av=(AV *) reference;
6718 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6719 exception);
6720 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6721 if (image == (Image *) NULL)
6722 {
6723 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6724 PackageName);
6725 goto PerlException;
6726 }
6727 map="RGB";
cristy17f11b02014-12-20 19:37:04 +00006728 if (image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00006729 map="RGBA";
6730 if (image->colorspace == CMYKColorspace)
6731 {
6732 map="CMYK";
cristy17f11b02014-12-20 19:37:04 +00006733 if (image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00006734 map="CMYKA";
6735 }
6736 normalize=MagickFalse;
6737 region.x=0;
6738 region.y=0;
6739 region.width=image->columns;
6740 region.height=1;
6741 if (items == 1)
6742 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6743 for (i=2; i < items; i+=2)
6744 {
6745 attribute=(char *) SvPV(ST(i-1),na);
6746 switch (*attribute)
6747 {
6748 case 'g':
6749 case 'G':
6750 {
6751 if (LocaleCompare(attribute,"geometry") == 0)
6752 {
6753 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6754 break;
6755 }
6756 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6757 attribute);
6758 break;
6759 }
6760 case 'H':
6761 case 'h':
6762 {
6763 if (LocaleCompare(attribute,"height") == 0)
6764 {
6765 region.height=SvIV(ST(i));
6766 break;
6767 }
6768 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6769 attribute);
6770 break;
6771 }
6772 case 'M':
6773 case 'm':
6774 {
6775 if (LocaleCompare(attribute,"map") == 0)
6776 {
6777 map=SvPV(ST(i),na);
6778 break;
6779 }
6780 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6781 attribute);
6782 break;
6783 }
6784 case 'N':
6785 case 'n':
6786 {
6787 if (LocaleCompare(attribute,"normalize") == 0)
6788 {
6789 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6790 SvPV(ST(i),na));
6791 if (option < 0)
6792 {
6793 ThrowPerlException(exception,OptionError,"UnrecognizedType",
6794 SvPV(ST(i),na));
6795 break;
6796 }
6797 normalize=option != 0 ? MagickTrue : MagickFalse;
6798 break;
6799 }
6800 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6801 attribute);
6802 break;
6803 }
6804 case 'W':
6805 case 'w':
6806 {
6807 if (LocaleCompare(attribute,"width") == 0)
6808 {
6809 region.width=SvIV(ST(i));
6810 break;
6811 }
6812 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6813 attribute);
6814 break;
6815 }
6816 case 'x':
6817 case 'X':
6818 {
6819 if (LocaleCompare(attribute,"x") == 0)
6820 {
6821 region.x=SvIV(ST(i));
6822 break;
6823 }
6824 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6825 attribute);
6826 break;
6827 }
6828 case 'y':
6829 case 'Y':
6830 {
6831 if (LocaleCompare(attribute,"y") == 0)
6832 {
6833 region.y=SvIV(ST(i));
6834 break;
6835 }
6836 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6837 attribute);
6838 break;
6839 }
6840 default:
6841 {
6842 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6843 attribute);
6844 break;
6845 }
6846 }
6847 }
6848 if (normalize != MagickFalse)
6849 {
6850 float
6851 *pixels;
6852
6853 pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6854 region.height*sizeof(*pixels));
6855 if (pixels == (float *) NULL)
6856 {
6857 ThrowPerlException(exception,ResourceLimitError,
6858 "MemoryAllocationFailed",PackageName);
6859 goto PerlException;
6860 }
6861 status=ExportImagePixels(image,region.x,region.y,region.width,
6862 region.height,map,FloatPixel,pixels,exception);
6863 if (status == MagickFalse)
6864 PUSHs(&sv_undef);
6865 else
6866 {
6867 EXTEND(sp,strlen(map)*region.width*region.height);
6868 for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6869 PUSHs(sv_2mortal(newSVnv(pixels[i])));
6870 }
6871 pixels=(float *) RelinquishMagickMemory(pixels);
6872 }
6873 else
6874 {
6875 Quantum
6876 *pixels;
6877
6878 pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6879 region.height*sizeof(*pixels));
6880 if (pixels == (Quantum *) NULL)
6881 {
6882 ThrowPerlException(exception,ResourceLimitError,
6883 "MemoryAllocationFailed",PackageName);
6884 goto PerlException;
6885 }
6886 status=ExportImagePixels(image,region.x,region.y,region.width,
6887 region.height,map,QuantumPixel,pixels,exception);
6888 if (status == MagickFalse)
6889 PUSHs(&sv_undef);
6890 else
6891 {
6892 EXTEND(sp,strlen(map)*region.width*region.height);
6893 for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6894 PUSHs(sv_2mortal(newSViv(pixels[i])));
6895 }
6896 pixels=(Quantum *) RelinquishMagickMemory(pixels);
6897 }
6898
6899 PerlException:
6900 InheritPerlException(exception,perl_exception);
6901 exception=DestroyExceptionInfo(exception);
6902 SvREFCNT_dec(perl_exception);
6903 }
6904
6905#
6906###############################################################################
6907# #
6908# #
6909# #
6910# I m a g e T o B l o b #
6911# #
6912# #
6913# #
6914###############################################################################
6915#
6916#
6917void
6918ImageToBlob(ref,...)
6919 Image::Magick ref=NO_INIT
6920 ALIAS:
6921 ImageToBlob = 1
6922 imagetoblob = 2
6923 toblob = 3
6924 blob = 4
6925 PPCODE:
6926 {
6927 char
cristy151b66d2015-04-15 10:50:31 +00006928 filename[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00006929
6930 ExceptionInfo
6931 *exception;
6932
6933 Image
6934 *image,
6935 *next;
6936
6937 register ssize_t
6938 i;
6939
6940 struct PackageInfo
6941 *info,
6942 *package_info;
6943
6944 size_t
6945 length;
6946
6947 ssize_t
6948 scene;
6949
6950 SV
6951 *perl_exception,
6952 *reference;
6953
6954 void
6955 *blob;
6956
6957 PERL_UNUSED_VAR(ref);
6958 PERL_UNUSED_VAR(ix);
6959 exception=AcquireExceptionInfo();
6960 perl_exception=newSVpv("",0);
6961 package_info=(struct PackageInfo *) NULL;
6962 if (sv_isobject(ST(0)) == 0)
6963 {
6964 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6965 PackageName);
6966 goto PerlException;
6967 }
6968 reference=SvRV(ST(0));
6969 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6970 if (image == (Image *) NULL)
6971 {
6972 ThrowPerlException(exception,OptionError,"NoImagesDefined",
6973 PackageName);
6974 goto PerlException;
6975 }
6976 package_info=ClonePackageInfo(info,exception);
6977 for (i=2; i < items; i+=2)
6978 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6979 (void) CopyMagickString(filename,package_info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00006980 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00006981 scene=0;
6982 for (next=image; next; next=next->next)
6983 {
cristy151b66d2015-04-15 10:50:31 +00006984 (void) CopyMagickString(next->filename,filename,MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +00006985 next->scene=scene++;
6986 }
6987 SetImageInfo(package_info->image_info,(unsigned int)
6988 GetImageListLength(image),exception);
6989 EXTEND(sp,(ssize_t) GetImageListLength(image));
6990 for ( ; image; image=image->next)
6991 {
6992 length=0;
6993 blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6994 if (blob != (char *) NULL)
6995 {
6996 PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6997 blob=(unsigned char *) RelinquishMagickMemory(blob);
6998 }
6999 if (package_info->image_info->adjoin)
7000 break;
7001 }
7002
7003 PerlException:
7004 if (package_info != (struct PackageInfo *) NULL)
7005 DestroyPackageInfo(package_info);
7006 InheritPerlException(exception,perl_exception);
7007 exception=DestroyExceptionInfo(exception);
7008 SvREFCNT_dec(perl_exception); /* throw away all errors */
7009 }
7010
7011#
7012###############################################################################
7013# #
7014# #
7015# #
7016# L a y e r s #
7017# #
7018# #
7019# #
7020###############################################################################
7021#
7022#
7023void
7024Layers(ref,...)
7025 Image::Magick ref=NO_INIT
7026 ALIAS:
7027 Layers = 1
7028 layers = 2
7029 OptimizeImageLayers = 3
7030 optimizelayers = 4
7031 optimizeimagelayers = 5
7032 PPCODE:
7033 {
7034 AV
7035 *av;
7036
7037 char
7038 *attribute;
7039
7040 CompositeOperator
7041 compose;
7042
7043 ExceptionInfo
7044 *exception;
7045
7046 HV
7047 *hv;
7048
7049 Image
7050 *image,
7051 *layers;
7052
7053 LayerMethod
7054 method;
7055
7056 register ssize_t
7057 i;
7058
7059 ssize_t
7060 option,
7061 sp;
7062
7063 struct PackageInfo
7064 *info;
7065
7066 SV
7067 *av_reference,
7068 *perl_exception,
7069 *reference,
7070 *rv,
7071 *sv;
7072
7073 PERL_UNUSED_VAR(ref);
7074 PERL_UNUSED_VAR(ix);
7075 exception=AcquireExceptionInfo();
7076 perl_exception=newSVpv("",0);
7077 sv=NULL;
7078 if (sv_isobject(ST(0)) == 0)
7079 {
7080 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7081 PackageName);
7082 goto PerlException;
7083 }
7084 reference=SvRV(ST(0));
7085 hv=SvSTASH(reference);
7086 av=newAV();
7087 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7088 SvREFCNT_dec(av);
7089 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7090 if (image == (Image *) NULL)
7091 {
7092 ThrowPerlException(exception,OptionError,"NoImagesDefined",
7093 PackageName);
7094 goto PerlException;
7095 }
7096 compose=image->compose;
7097 method=OptimizeLayer;
7098 for (i=2; i < items; i+=2)
7099 {
7100 attribute=(char *) SvPV(ST(i-1),na);
7101 switch (*attribute)
7102 {
7103 case 'C':
7104 case 'c':
7105 {
7106 if (LocaleCompare(attribute,"compose") == 0)
7107 {
7108 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7109 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7110 if (sp < 0)
7111 {
7112 ThrowPerlException(exception,OptionError,"UnrecognizedType",
7113 SvPV(ST(i),na));
7114 break;
7115 }
7116 compose=(CompositeOperator) sp;
7117 break;
7118 }
7119 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7120 attribute);
7121 break;
7122 }
7123 case 'M':
7124 case 'm':
7125 {
7126 if (LocaleCompare(attribute,"method") == 0)
7127 {
7128 option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7129 SvPV(ST(i),na));
7130 if (option < 0)
7131 {
7132 ThrowPerlException(exception,OptionError,"UnrecognizedType",
7133 SvPV(ST(i),na));
7134 break;
7135 }
7136 method=(LayerMethod) option;
7137 break;
7138 }
7139 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7140 attribute);
7141 break;
7142 }
7143 default:
7144 {
7145 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7146 attribute);
7147 break;
7148 }
7149 }
7150 }
7151 layers=(Image *) NULL;
7152 switch (method)
7153 {
7154 case CompareAnyLayer:
7155 case CompareClearLayer:
7156 case CompareOverlayLayer:
7157 default:
7158 {
7159 layers=CompareImagesLayers(image,method,exception);
7160 break;
7161 }
7162 case MergeLayer:
7163 case FlattenLayer:
7164 case MosaicLayer:
7165 {
7166 layers=MergeImageLayers(image,method,exception);
7167 break;
7168 }
7169 case DisposeLayer:
7170 {
7171 layers=DisposeImages(image,exception);
7172 break;
7173 }
7174 case OptimizeImageLayer:
7175 {
7176 layers=OptimizeImageLayers(image,exception);
7177 break;
7178 }
7179 case OptimizePlusLayer:
7180 {
7181 layers=OptimizePlusImageLayers(image,exception);
7182 break;
7183 }
7184 case OptimizeTransLayer:
7185 {
7186 OptimizeImageTransparency(image,exception);
7187 break;
7188 }
7189 case RemoveDupsLayer:
7190 {
7191 RemoveDuplicateLayers(&image,exception);
7192 break;
7193 }
7194 case RemoveZeroLayer:
7195 {
7196 RemoveZeroDelayLayers(&image,exception);
7197 break;
7198 }
7199 case OptimizeLayer:
7200 {
7201 QuantizeInfo
7202 *quantize_info;
7203
7204 /*
7205 General Purpose, GIF Animation Optimizer.
7206 */
7207 layers=CoalesceImages(image,exception);
7208 if (layers == (Image *) NULL)
7209 break;
7210 image=layers;
7211 layers=OptimizeImageLayers(image,exception);
7212 if (layers == (Image *) NULL)
7213 break;
7214 image=DestroyImageList(image);
7215 image=layers;
7216 layers=(Image *) NULL;
7217 OptimizeImageTransparency(image,exception);
7218 quantize_info=AcquireQuantizeInfo(info->image_info);
7219 (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7220 quantize_info=DestroyQuantizeInfo(quantize_info);
7221 break;
7222 }
7223 case CompositeLayer:
7224 {
7225 Image
7226 *source;
7227
7228 RectangleInfo
7229 geometry;
7230
7231 /*
7232 Split image sequence at the first 'NULL:' image.
7233 */
7234 source=image;
7235 while (source != (Image *) NULL)
7236 {
7237 source=GetNextImageInList(source);
7238 if ((source != (Image *) NULL) &&
7239 (LocaleCompare(source->magick,"NULL") == 0))
7240 break;
7241 }
7242 if (source != (Image *) NULL)
7243 {
7244 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7245 (GetNextImageInList(source) == (Image *) NULL))
7246 source=(Image *) NULL;
7247 else
7248 {
7249 /*
7250 Separate the two lists, junk the null: image.
7251 */
7252 source=SplitImageList(source->previous);
7253 DeleteImageFromList(&source);
7254 }
7255 }
7256 if (source == (Image *) NULL)
7257 {
7258 (void) ThrowMagickException(exception,GetMagickModule(),
7259 OptionError,"MissingNullSeparator","layers Composite");
7260 break;
7261 }
7262 /*
7263 Adjust offset with gravity and virtual canvas.
7264 */
7265 SetGeometry(image,&geometry);
7266 (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7267 geometry.width=source->page.width != 0 ? source->page.width :
7268 source->columns;
7269 geometry.height=source->page.height != 0 ? source->page.height :
7270 source->rows;
7271 GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7272 image->columns,image->page.height != 0 ? image->page.height :
7273 image->rows,image->gravity,&geometry);
7274 CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7275 source=DestroyImageList(source);
7276 break;
7277 }
7278 }
7279 if (layers != (Image *) NULL)
7280 image=layers;
cristy83a28a02013-08-03 20:25:48 +00007281 else
7282 image=CloneImage(image,0,0,MagickTrue,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007283 if (image == (Image *) NULL)
7284 goto PerlException;
7285 for ( ; image; image=image->next)
7286 {
7287 AddImageToRegistry(sv,image);
7288 rv=newRV(sv);
7289 av_push(av,sv_bless(rv,hv));
7290 SvREFCNT_dec(sv);
7291 }
7292 exception=DestroyExceptionInfo(exception);
7293 ST(0)=av_reference;
7294 SvREFCNT_dec(perl_exception);
7295 XSRETURN(1);
7296
7297 PerlException:
7298 InheritPerlException(exception,perl_exception);
7299 exception=DestroyExceptionInfo(exception);
7300 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7301 SvPOK_on(perl_exception);
7302 ST(0)=sv_2mortal(perl_exception);
7303 XSRETURN(1);
7304 }
7305
7306#
7307###############################################################################
7308# #
7309# #
7310# #
7311# M a g i c k T o M i m e #
7312# #
7313# #
7314# #
7315###############################################################################
7316#
7317#
7318SV *
7319MagickToMime(ref,name)
7320 Image::Magick ref=NO_INIT
7321 char *name
7322 ALIAS:
7323 magicktomime = 1
7324 CODE:
7325 {
7326 char
7327 *mime;
7328
7329 PERL_UNUSED_VAR(ref);
7330 PERL_UNUSED_VAR(ix);
7331 mime=MagickToMime(name);
7332 RETVAL=newSVpv(mime,0);
7333 mime=(char *) RelinquishMagickMemory(mime);
7334 }
7335 OUTPUT:
7336 RETVAL
7337
7338#
7339###############################################################################
7340# #
7341# #
7342# #
7343# M o g r i f y #
7344# #
7345# #
7346# #
7347###############################################################################
7348#
7349#
7350void
7351Mogrify(ref,...)
7352 Image::Magick ref=NO_INIT
7353 ALIAS:
7354 Comment = 1
7355 CommentImage = 2
7356 Label = 3
7357 LabelImage = 4
7358 AddNoise = 5
7359 AddNoiseImage = 6
7360 Colorize = 7
7361 ColorizeImage = 8
7362 Border = 9
7363 BorderImage = 10
7364 Blur = 11
7365 BlurImage = 12
7366 Chop = 13
7367 ChopImage = 14
7368 Crop = 15
7369 CropImage = 16
7370 Despeckle = 17
7371 DespeckleImage = 18
7372 Edge = 19
7373 EdgeImage = 20
7374 Emboss = 21
7375 EmbossImage = 22
7376 Enhance = 23
7377 EnhanceImage = 24
7378 Flip = 25
7379 FlipImage = 26
7380 Flop = 27
7381 FlopImage = 28
7382 Frame = 29
7383 FrameImage = 30
7384 Implode = 31
7385 ImplodeImage = 32
7386 Magnify = 33
7387 MagnifyImage = 34
7388 MedianFilter = 35
7389 MedianConvolveImage = 36
7390 Minify = 37
7391 MinifyImage = 38
7392 OilPaint = 39
7393 OilPaintImage = 40
7394 ReduceNoise = 41
7395 ReduceNoiseImage = 42
7396 Roll = 43
7397 RollImage = 44
7398 Rotate = 45
7399 RotateImage = 46
7400 Sample = 47
7401 SampleImage = 48
7402 Scale = 49
7403 ScaleImage = 50
7404 Shade = 51
7405 ShadeImage = 52
7406 Sharpen = 53
7407 SharpenImage = 54
7408 Shear = 55
7409 ShearImage = 56
7410 Spread = 57
7411 SpreadImage = 58
7412 Swirl = 59
7413 SwirlImage = 60
7414 Resize = 61
7415 ResizeImage = 62
7416 Zoom = 63
7417 ZoomImage = 64
7418 Annotate = 65
7419 AnnotateImage = 66
7420 ColorFloodfill = 67
7421 ColorFloodfillImage= 68
7422 Composite = 69
7423 CompositeImage = 70
7424 Contrast = 71
7425 ContrastImage = 72
7426 CycleColormap = 73
7427 CycleColormapImage = 74
7428 Draw = 75
7429 DrawImage = 76
7430 Equalize = 77
7431 EqualizeImage = 78
7432 Gamma = 79
7433 GammaImage = 80
7434 Map = 81
7435 MapImage = 82
7436 MatteFloodfill = 83
7437 MatteFloodfillImage= 84
7438 Modulate = 85
7439 ModulateImage = 86
7440 Negate = 87
7441 NegateImage = 88
7442 Normalize = 89
7443 NormalizeImage = 90
7444 NumberColors = 91
7445 NumberColorsImage = 92
7446 Opaque = 93
7447 OpaqueImage = 94
7448 Quantize = 95
7449 QuantizeImage = 96
7450 Raise = 97
7451 RaiseImage = 98
7452 Segment = 99
7453 SegmentImage = 100
7454 Signature = 101
7455 SignatureImage = 102
7456 Solarize = 103
7457 SolarizeImage = 104
7458 Sync = 105
7459 SyncImage = 106
7460 Texture = 107
7461 TextureImage = 108
7462 Evaluate = 109
7463 EvaluateImage = 110
7464 Transparent = 111
7465 TransparentImage = 112
7466 Threshold = 113
7467 ThresholdImage = 114
7468 Charcoal = 115
7469 CharcoalImage = 116
7470 Trim = 117
7471 TrimImage = 118
7472 Wave = 119
7473 WaveImage = 120
7474 Separate = 121
7475 SeparateImage = 122
7476 Stereo = 125
7477 StereoImage = 126
7478 Stegano = 127
7479 SteganoImage = 128
7480 Deconstruct = 129
7481 DeconstructImage = 130
7482 GaussianBlur = 131
7483 GaussianBlurImage = 132
7484 Convolve = 133
7485 ConvolveImage = 134
7486 Profile = 135
7487 ProfileImage = 136
7488 UnsharpMask = 137
7489 UnsharpMaskImage = 138
7490 MotionBlur = 139
7491 MotionBlurImage = 140
7492 OrderedDither = 141
7493 OrderedDitherImage = 142
7494 Shave = 143
7495 ShaveImage = 144
7496 Level = 145
7497 LevelImage = 146
7498 Clip = 147
7499 ClipImage = 148
7500 AffineTransform = 149
7501 AffineTransformImage = 150
7502 Difference = 151
7503 DifferenceImage = 152
7504 AdaptiveThreshold = 153
7505 AdaptiveThresholdImage = 154
7506 Resample = 155
7507 ResampleImage = 156
7508 Describe = 157
7509 DescribeImage = 158
7510 BlackThreshold = 159
7511 BlackThresholdImage= 160
7512 WhiteThreshold = 161
7513 WhiteThresholdImage= 162
cristy60c73c02014-03-25 12:09:58 +00007514 RotationalBlur = 163
7515 RotationalBlurImage= 164
cristy4a3ce0a2013-08-03 20:06:59 +00007516 Thumbnail = 165
7517 ThumbnailImage = 166
7518 Strip = 167
7519 StripImage = 168
7520 Tint = 169
7521 TintImage = 170
7522 Channel = 171
7523 ChannelImage = 172
7524 Splice = 173
7525 SpliceImage = 174
7526 Posterize = 175
7527 PosterizeImage = 176
7528 Shadow = 177
7529 ShadowImage = 178
7530 Identify = 179
7531 IdentifyImage = 180
7532 SepiaTone = 181
7533 SepiaToneImage = 182
7534 SigmoidalContrast = 183
7535 SigmoidalContrastImage = 184
7536 Extent = 185
7537 ExtentImage = 186
7538 Vignette = 187
7539 VignetteImage = 188
7540 ContrastStretch = 189
7541 ContrastStretchImage = 190
7542 Sans0 = 191
7543 Sans0Image = 192
7544 Sans1 = 193
7545 Sans1Image = 194
7546 AdaptiveSharpen = 195
7547 AdaptiveSharpenImage = 196
7548 Transpose = 197
7549 TransposeImage = 198
7550 Transverse = 199
7551 TransverseImage = 200
7552 AutoOrient = 201
7553 AutoOrientImage = 202
7554 AdaptiveBlur = 203
7555 AdaptiveBlurImage = 204
7556 Sketch = 205
7557 SketchImage = 206
7558 UniqueColors = 207
7559 UniqueColorsImage = 208
7560 AdaptiveResize = 209
7561 AdaptiveResizeImage= 210
7562 ClipMask = 211
7563 ClipMaskImage = 212
7564 LinearStretch = 213
7565 LinearStretchImage = 214
7566 ColorMatrix = 215
7567 ColorMatrixImage = 216
7568 Mask = 217
7569 MaskImage = 218
7570 Polaroid = 219
7571 PolaroidImage = 220
7572 FloodfillPaint = 221
7573 FloodfillPaintImage= 222
7574 Distort = 223
7575 DistortImage = 224
7576 Clut = 225
7577 ClutImage = 226
7578 LiquidRescale = 227
7579 LiquidRescaleImage = 228
7580 Encipher = 229
7581 EncipherImage = 230
7582 Decipher = 231
7583 DecipherImage = 232
7584 Deskew = 233
7585 DeskewImage = 234
7586 Remap = 235
7587 RemapImage = 236
7588 SparseColor = 237
7589 SparseColorImage = 238
7590 Function = 239
7591 FunctionImage = 240
7592 SelectiveBlur = 241
7593 SelectiveBlurImage = 242
7594 HaldClut = 243
7595 HaldClutImage = 244
7596 BlueShift = 245
7597 BlueShiftImage = 246
7598 ForwardFourierTransform = 247
7599 ForwardFourierTransformImage = 248
7600 InverseFourierTransform = 249
7601 InverseFourierTransformImage = 250
7602 ColorDecisionList = 251
7603 ColorDecisionListImage = 252
7604 AutoGamma = 253
7605 AutoGammaImage = 254
7606 AutoLevel = 255
7607 AutoLevelImage = 256
7608 LevelColors = 257
7609 LevelImageColors = 258
7610 Clamp = 259
7611 ClampImage = 260
7612 BrightnessContrast = 261
7613 BrightnessContrastImage = 262
7614 Morphology = 263
7615 MorphologyImage = 264
Cristy3ca633e2016-02-13 12:49:01 -05007616 Mode = 265
7617 ModeImage = 266
7618 Statistic = 267
7619 StatisticImage = 268
7620 Perceptible = 269
7621 PerceptibleImage = 270
7622 Poly = 271
7623 PolyImage = 272
7624 Grayscale = 273
7625 GrayscaleImage = 274
7626 CannyEdge = 275
7627 CannyEdgeImage = 276
7628 HoughLine = 277
7629 HoughLineImage = 278
7630 MeanShift = 279
7631 MeanShiftImage = 280
7632 Kuwahara = 281
7633 KuwaharaImage = 282
Cristy0f5df812017-07-04 18:30:05 -04007634 ConnectedComponents = 283
7635 ConnectedComponentsImage = 284
Cristy3ca633e2016-02-13 12:49:01 -05007636 CopyPixels = 285
7637 CopyImagePixels = 286
Cristy5488c982016-02-13 14:07:50 -05007638 Color = 287
7639 ColorImage = 288
Cristy2d830ed2016-02-21 10:54:16 -05007640 WaveletDenoise = 289
7641 WaveletDenoiseImage= 290
Cristy99a57162016-12-05 11:47:57 -05007642 Colorspace = 291
7643 ColorspaceImage = 292
Cristy53353872017-07-02 12:24:24 -04007644 AutoThreshold = 293
7645 AutoThresholdImage = 294
Cristy532b3382018-08-05 17:56:56 -04007646 RangeThreshold = 295
7647 RangeThresholdImage= 296
Cristy9f252542018-11-21 19:13:46 -05007648 CLAHE = 297
7649 CLAHEImage = 298
cristy4a3ce0a2013-08-03 20:06:59 +00007650 MogrifyRegion = 666
7651 PPCODE:
7652 {
7653 AffineMatrix
7654 affine,
7655 current;
7656
7657 char
7658 attribute_flag[MaxArguments],
cristy151b66d2015-04-15 10:50:31 +00007659 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00007660
7661 ChannelType
7662 channel,
7663 channel_mask;
7664
7665 CompositeOperator
7666 compose;
7667
7668 const char
7669 *attribute,
7670 *value;
7671
7672 double
7673 angle;
7674
7675 ExceptionInfo
7676 *exception;
7677
7678 GeometryInfo
7679 geometry_info;
7680
7681 Image
7682 *image,
Cristy7e567962018-02-03 12:42:20 -05007683 *next;
cristy4a3ce0a2013-08-03 20:06:59 +00007684
cristy4a3ce0a2013-08-03 20:06:59 +00007685 MagickStatusType
7686 flags;
7687
7688 PixelInfo
7689 fill_color;
7690
7691 RectangleInfo
7692 geometry,
7693 region_info;
7694
7695 register ssize_t
7696 i;
7697
7698 ssize_t
7699 base,
7700 j,
7701 number_images;
7702
7703 struct Methods
7704 *rp;
7705
7706 struct PackageInfo
7707 *info;
7708
7709 SV
7710 *perl_exception,
7711 **pv,
7712 *reference,
7713 **reference_vector;
7714
7715 struct ArgumentList
7716 argument_list[MaxArguments];
7717
7718 PERL_UNUSED_VAR(ref);
7719 PERL_UNUSED_VAR(ix);
7720 exception=AcquireExceptionInfo();
7721 perl_exception=newSVpv("",0);
7722 reference_vector=NULL;
cristy4a3ce0a2013-08-03 20:06:59 +00007723 number_images=0;
7724 base=2;
7725 if (sv_isobject(ST(0)) == 0)
7726 {
7727 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7728 PackageName);
7729 goto PerlException;
7730 }
7731 reference=SvRV(ST(0));
7732 region_info.width=0;
7733 region_info.height=0;
7734 region_info.x=0;
7735 region_info.y=0;
cristy4a3ce0a2013-08-03 20:06:59 +00007736 image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7737 if (ix && (ix != 666))
7738 {
7739 /*
7740 Called as Method(...)
7741 */
7742 ix=(ix+1)/2;
7743 rp=(&Methods[ix-1]);
7744 attribute=rp->name;
7745 }
7746 else
7747 {
7748 /*
7749 Called as Mogrify("Method",...)
7750 */
7751 attribute=(char *) SvPV(ST(1),na);
7752 if (ix)
7753 {
7754 flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7755 attribute=(char *) SvPV(ST(2),na);
7756 base++;
7757 }
7758 for (rp=Methods; ; rp++)
7759 {
7760 if (rp >= EndOf(Methods))
7761 {
7762 ThrowPerlException(exception,OptionError,
7763 "UnrecognizedPerlMagickMethod",attribute);
7764 goto PerlException;
7765 }
7766 if (strEQcase(attribute,rp->name))
7767 break;
7768 }
7769 ix=rp-Methods+1;
7770 base++;
7771 }
7772 if (image == (Image *) NULL)
7773 {
7774 ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7775 goto PerlException;
7776 }
7777 Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7778 Zero(&attribute_flag,NumberOf(attribute_flag),char);
7779 for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7780 {
7781 Arguments
7782 *pp,
7783 *qq;
7784
7785 ssize_t
7786 ssize_test;
7787
7788 struct ArgumentList
7789 *al;
7790
7791 SV
7792 *sv;
7793
7794 sv=NULL;
7795 ssize_test=0;
7796 pp=(Arguments *) NULL;
7797 qq=rp->arguments;
7798 if (i == items)
7799 {
7800 pp=rp->arguments,
7801 sv=ST(i-1);
7802 }
7803 else
7804 for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7805 {
7806 if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7807 break;
7808 if (strEQcase(attribute,qq->method) > ssize_test)
7809 {
7810 pp=qq;
7811 ssize_test=strEQcase(attribute,qq->method);
7812 }
7813 }
7814 if (pp == (Arguments *) NULL)
7815 {
7816 ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7817 attribute);
7818 goto continue_outer_loop;
7819 }
7820 al=(&argument_list[pp-rp->arguments]);
7821 switch (pp->type)
7822 {
7823 case ArrayReference:
7824 {
7825 if (SvTYPE(sv) != SVt_RV)
7826 {
cristy151b66d2015-04-15 10:50:31 +00007827 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007828 "invalid %.60s value",pp->method);
7829 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7830 goto continue_outer_loop;
7831 }
7832 al->array_reference=SvRV(sv);
7833 break;
7834 }
7835 case RealReference:
7836 {
7837 al->real_reference=SvNV(sv);
7838 break;
7839 }
7840 case FileReference:
7841 {
7842 al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7843 break;
7844 }
7845 case ImageReference:
7846 {
7847 if (!sv_isobject(sv) ||
7848 !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7849 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7850 {
7851 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7852 PackageName);
7853 goto PerlException;
7854 }
7855 break;
7856 }
7857 case IntegerReference:
7858 {
7859 al->integer_reference=SvIV(sv);
7860 break;
7861 }
7862 case StringReference:
7863 {
7864 al->string_reference=(char *) SvPV(sv,al->length);
7865 if (sv_isobject(sv))
7866 al->image_reference=SetupList(aTHX_ SvRV(sv),
7867 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7868 break;
7869 }
7870 default:
7871 {
7872 /*
7873 Is a string; look up name.
7874 */
7875 if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7876 {
7877 al->string_reference=(char *) SvPV(sv,al->length);
7878 al->integer_reference=(-1);
7879 break;
7880 }
7881 al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7882 MagickFalse,SvPV(sv,na));
7883 if (pp->type == MagickChannelOptions)
7884 al->integer_reference=ParseChannelOption(SvPV(sv,na));
7885 if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7886 {
cristy151b66d2015-04-15 10:50:31 +00007887 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00007888 "invalid %.60s value",pp->method);
7889 ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7890 goto continue_outer_loop;
7891 }
7892 break;
7893 }
7894 }
7895 attribute_flag[pp-rp->arguments]++;
7896 continue_outer_loop: ;
7897 }
7898 (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7899 pv=reference_vector;
7900 SetGeometryInfo(&geometry_info);
7901 channel=DefaultChannels;
7902 for (next=image; next; next=next->next)
7903 {
7904 image=next;
7905 SetGeometry(image,&geometry);
7906 if ((region_info.width*region_info.height) != 0)
Cristy7e567962018-02-03 12:42:20 -05007907 (void) SetImageRegionMask(image,WritePixelMask,&region_info,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007908 switch (ix)
7909 {
7910 default:
7911 {
cristy151b66d2015-04-15 10:50:31 +00007912 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
cristy4a3ce0a2013-08-03 20:06:59 +00007913 ThrowPerlException(exception,OptionError,
7914 "UnrecognizedPerlMagickMethod",message);
7915 goto PerlException;
7916 }
7917 case 1: /* Comment */
7918 {
7919 if (attribute_flag[0] == 0)
7920 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007921 (void) SetImageProperty(image,"comment",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007922 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007923 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007924 break;
7925 }
7926 case 2: /* Label */
7927 {
7928 if (attribute_flag[0] == 0)
7929 argument_list[0].string_reference=(char *) NULL;
Cristy935a4052017-03-31 17:45:37 -04007930 (void) SetImageProperty(image,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +00007931 info ? info->image_info : (ImageInfo *) NULL,image,
Cristy935a4052017-03-31 17:45:37 -04007932 argument_list[0].string_reference,exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +00007933 break;
7934 }
7935 case 3: /* AddNoise */
7936 {
7937 double
7938 attenuate;
7939
7940 if (attribute_flag[0] == 0)
7941 argument_list[0].integer_reference=UniformNoise;
7942 attenuate=1.0;
7943 if (attribute_flag[1] != 0)
7944 attenuate=argument_list[1].real_reference;
7945 if (attribute_flag[2] != 0)
7946 channel=(ChannelType) argument_list[2].integer_reference;
7947 channel_mask=SetImageChannelMask(image,channel);
7948 image=AddNoiseImage(image,(NoiseType)
7949 argument_list[0].integer_reference,attenuate,exception);
7950 if (image != (Image *) NULL)
7951 (void) SetImageChannelMask(image,channel_mask);
7952 break;
7953 }
7954 case 4: /* Colorize */
7955 {
7956 PixelInfo
7957 target;
7958
7959 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7960 0,0,&target,exception);
7961 if (attribute_flag[0] != 0)
7962 (void) QueryColorCompliance(argument_list[0].string_reference,
7963 AllCompliance,&target,exception);
7964 if (attribute_flag[1] == 0)
7965 argument_list[1].string_reference="100%";
7966 image=ColorizeImage(image,argument_list[1].string_reference,&target,
7967 exception);
7968 break;
7969 }
7970 case 5: /* Border */
7971 {
7972 CompositeOperator
7973 compose;
7974
7975 geometry.width=0;
7976 geometry.height=0;
7977 if (attribute_flag[0] != 0)
7978 flags=ParsePageGeometry(image,argument_list[0].string_reference,
7979 &geometry,exception);
7980 if (attribute_flag[1] != 0)
7981 geometry.width=argument_list[1].integer_reference;
7982 if (attribute_flag[2] != 0)
7983 geometry.height=argument_list[2].integer_reference;
7984 if (attribute_flag[3] != 0)
7985 QueryColorCompliance(argument_list[3].string_reference,
7986 AllCompliance,&image->border_color,exception);
7987 if (attribute_flag[4] != 0)
7988 QueryColorCompliance(argument_list[4].string_reference,
7989 AllCompliance,&image->border_color,exception);
7990 if (attribute_flag[5] != 0)
7991 QueryColorCompliance(argument_list[5].string_reference,
7992 AllCompliance,&image->border_color,exception);
7993 compose=image->compose;
7994 if (attribute_flag[6] != 0)
7995 compose=(CompositeOperator) argument_list[6].integer_reference;
7996 image=BorderImage(image,&geometry,compose,exception);
7997 break;
7998 }
7999 case 6: /* Blur */
8000 {
8001 if (attribute_flag[0] != 0)
8002 {
8003 flags=ParseGeometry(argument_list[0].string_reference,
8004 &geometry_info);
8005 if ((flags & SigmaValue) == 0)
8006 geometry_info.sigma=1.0;
8007 }
8008 if (attribute_flag[1] != 0)
8009 geometry_info.rho=argument_list[1].real_reference;
8010 if (attribute_flag[2] != 0)
8011 geometry_info.sigma=argument_list[2].real_reference;
8012 if (attribute_flag[3] != 0)
8013 channel=(ChannelType) argument_list[3].integer_reference;
8014 channel_mask=SetImageChannelMask(image,channel);
8015 image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
8016 exception);
8017 if (image != (Image *) NULL)
8018 (void) SetImageChannelMask(image,channel_mask);
8019 break;
8020 }
8021 case 7: /* Chop */
8022 {
cristy260bd762014-08-15 12:46:34 +00008023 if (attribute_flag[5] != 0)
8024 image->gravity=(GravityType) argument_list[5].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00008025 if (attribute_flag[0] != 0)
8026 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8027 &geometry,exception);
8028 if (attribute_flag[1] != 0)
8029 geometry.width=argument_list[1].integer_reference;
8030 if (attribute_flag[2] != 0)
8031 geometry.height=argument_list[2].integer_reference;
8032 if (attribute_flag[3] != 0)
8033 geometry.x=argument_list[3].integer_reference;
8034 if (attribute_flag[4] != 0)
8035 geometry.y=argument_list[4].integer_reference;
8036 image=ChopImage(image,&geometry,exception);
8037 break;
8038 }
8039 case 8: /* Crop */
8040 {
8041 if (attribute_flag[6] != 0)
8042 image->gravity=(GravityType) argument_list[6].integer_reference;
8043 if (attribute_flag[0] != 0)
8044 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8045 &geometry,exception);
8046 if (attribute_flag[1] != 0)
8047 geometry.width=argument_list[1].integer_reference;
8048 if (attribute_flag[2] != 0)
8049 geometry.height=argument_list[2].integer_reference;
8050 if (attribute_flag[3] != 0)
8051 geometry.x=argument_list[3].integer_reference;
8052 if (attribute_flag[4] != 0)
8053 geometry.y=argument_list[4].integer_reference;
8054 if (attribute_flag[5] != 0)
8055 image->fuzz=StringToDoubleInterval(
8056 argument_list[5].string_reference,(double) QuantumRange+1.0);
8057 image=CropImage(image,&geometry,exception);
8058 break;
8059 }
8060 case 9: /* Despeckle */
8061 {
8062 image=DespeckleImage(image,exception);
8063 break;
8064 }
8065 case 10: /* Edge */
8066 {
8067 if (attribute_flag[0] != 0)
8068 geometry_info.rho=argument_list[0].real_reference;
8069 image=EdgeImage(image,geometry_info.rho,exception);
8070 break;
8071 }
8072 case 11: /* Emboss */
8073 {
8074 if (attribute_flag[0] != 0)
8075 {
8076 flags=ParseGeometry(argument_list[0].string_reference,
8077 &geometry_info);
8078 if ((flags & SigmaValue) == 0)
8079 geometry_info.sigma=1.0;
8080 }
8081 if (attribute_flag[1] != 0)
8082 geometry_info.rho=argument_list[1].real_reference;
8083 if (attribute_flag[2] != 0)
8084 geometry_info.sigma=argument_list[2].real_reference;
8085 image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8086 exception);
8087 break;
8088 }
8089 case 12: /* Enhance */
8090 {
8091 image=EnhanceImage(image,exception);
8092 break;
8093 }
8094 case 13: /* Flip */
8095 {
8096 image=FlipImage(image,exception);
8097 break;
8098 }
8099 case 14: /* Flop */
8100 {
8101 image=FlopImage(image,exception);
8102 break;
8103 }
8104 case 15: /* Frame */
8105 {
8106 CompositeOperator
8107 compose;
8108
8109 FrameInfo
8110 frame_info;
8111
8112 if (attribute_flag[0] != 0)
8113 {
8114 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8115 &geometry,exception);
8116 frame_info.width=geometry.width;
8117 frame_info.height=geometry.height;
8118 frame_info.outer_bevel=geometry.x;
8119 frame_info.inner_bevel=geometry.y;
8120 }
8121 if (attribute_flag[1] != 0)
8122 frame_info.width=argument_list[1].integer_reference;
8123 if (attribute_flag[2] != 0)
8124 frame_info.height=argument_list[2].integer_reference;
8125 if (attribute_flag[3] != 0)
8126 frame_info.inner_bevel=argument_list[3].integer_reference;
8127 if (attribute_flag[4] != 0)
8128 frame_info.outer_bevel=argument_list[4].integer_reference;
8129 if (attribute_flag[5] != 0)
8130 QueryColorCompliance(argument_list[5].string_reference,
8131 AllCompliance,&fill_color,exception);
8132 if (attribute_flag[6] != 0)
8133 QueryColorCompliance(argument_list[6].string_reference,
8134 AllCompliance,&fill_color,exception);
8135 frame_info.x=(ssize_t) frame_info.width;
8136 frame_info.y=(ssize_t) frame_info.height;
8137 frame_info.width=image->columns+2*frame_info.x;
8138 frame_info.height=image->rows+2*frame_info.y;
8139 if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
Cristy8645e042016-02-03 16:35:29 -05008140 image->alpha_color=fill_color;
cristy4a3ce0a2013-08-03 20:06:59 +00008141 compose=image->compose;
8142 if (attribute_flag[7] != 0)
8143 compose=(CompositeOperator) argument_list[7].integer_reference;
8144 image=FrameImage(image,&frame_info,compose,exception);
8145 break;
8146 }
8147 case 16: /* Implode */
8148 {
8149 PixelInterpolateMethod
8150 method;
8151
8152 if (attribute_flag[0] == 0)
8153 argument_list[0].real_reference=0.5;
8154 method=UndefinedInterpolatePixel;
8155 if (attribute_flag[1] != 0)
8156 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8157 image=ImplodeImage(image,argument_list[0].real_reference,
8158 method,exception);
8159 break;
8160 }
8161 case 17: /* Magnify */
8162 {
8163 image=MagnifyImage(image,exception);
8164 break;
8165 }
8166 case 18: /* MedianFilter */
8167 {
8168 if (attribute_flag[0] != 0)
8169 {
8170 flags=ParseGeometry(argument_list[0].string_reference,
8171 &geometry_info);
8172 if ((flags & SigmaValue) == 0)
8173 geometry_info.sigma=geometry_info.rho;
8174 }
8175 if (attribute_flag[1] != 0)
8176 geometry_info.rho=argument_list[1].real_reference;
8177 if (attribute_flag[2] != 0)
8178 geometry_info.sigma=argument_list[2].real_reference;
8179 if (attribute_flag[3] != 0)
8180 channel=(ChannelType) argument_list[3].integer_reference;
8181 channel_mask=SetImageChannelMask(image,channel);
8182 image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8183 (size_t) geometry_info.sigma,exception);
8184 if (image != (Image *) NULL)
8185 (void) SetImageChannelMask(image,channel_mask);
8186 break;
8187 }
8188 case 19: /* Minify */
8189 {
8190 image=MinifyImage(image,exception);
8191 break;
8192 }
8193 case 20: /* OilPaint */
8194 {
8195 if (attribute_flag[0] == 0)
8196 argument_list[0].real_reference=0.0;
8197 if (attribute_flag[1] == 0)
8198 argument_list[1].real_reference=1.0;
8199 image=OilPaintImage(image,argument_list[0].real_reference,
8200 argument_list[1].real_reference,exception);
8201 break;
8202 }
8203 case 21: /* ReduceNoise */
8204 {
8205 if (attribute_flag[0] != 0)
8206 {
8207 flags=ParseGeometry(argument_list[0].string_reference,
8208 &geometry_info);
8209 if ((flags & SigmaValue) == 0)
8210 geometry_info.sigma=1.0;
8211 }
8212 if (attribute_flag[1] != 0)
8213 geometry_info.rho=argument_list[1].real_reference;
8214 if (attribute_flag[2] != 0)
8215 geometry_info.sigma=argument_list[2].real_reference;
8216 if (attribute_flag[3] != 0)
8217 channel=(ChannelType) argument_list[3].integer_reference;
8218 channel_mask=SetImageChannelMask(image,channel);
8219 image=StatisticImage(image,NonpeakStatistic,(size_t)
8220 geometry_info.rho,(size_t) geometry_info.sigma,exception);
8221 if (image != (Image *) NULL)
8222 (void) SetImageChannelMask(image,channel_mask);
8223 break;
8224 }
8225 case 22: /* Roll */
8226 {
8227 if (attribute_flag[0] != 0)
Cristyf94b0842017-07-14 07:05:02 -04008228 {
8229 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8230 &geometry,exception);
8231 if ((flags & PercentValue) != 0)
8232 {
8233 geometry.x*=(double) image->columns/100.0;
8234 geometry.y*=(double) image->rows/100.0;
8235 }
8236 }
cristy4a3ce0a2013-08-03 20:06:59 +00008237 if (attribute_flag[1] != 0)
8238 geometry.x=argument_list[1].integer_reference;
8239 if (attribute_flag[2] != 0)
8240 geometry.y=argument_list[2].integer_reference;
8241 image=RollImage(image,geometry.x,geometry.y,exception);
8242 break;
8243 }
8244 case 23: /* Rotate */
8245 {
8246 if (attribute_flag[0] == 0)
8247 argument_list[0].real_reference=90.0;
8248 if (attribute_flag[1] != 0)
8249 {
8250 QueryColorCompliance(argument_list[1].string_reference,
8251 AllCompliance,&image->background_color,exception);
cristy17f11b02014-12-20 19:37:04 +00008252 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8253 (image->alpha_trait == UndefinedPixelTrait))
cristy4a3ce0a2013-08-03 20:06:59 +00008254 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8255 }
8256 image=RotateImage(image,argument_list[0].real_reference,exception);
8257 break;
8258 }
8259 case 24: /* Sample */
8260 {
8261 if (attribute_flag[0] != 0)
8262 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8263 &geometry,exception);
8264 if (attribute_flag[1] != 0)
8265 geometry.width=argument_list[1].integer_reference;
8266 if (attribute_flag[2] != 0)
8267 geometry.height=argument_list[2].integer_reference;
8268 image=SampleImage(image,geometry.width,geometry.height,exception);
8269 break;
8270 }
8271 case 25: /* Scale */
8272 {
8273 if (attribute_flag[0] != 0)
8274 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8275 &geometry,exception);
8276 if (attribute_flag[1] != 0)
8277 geometry.width=argument_list[1].integer_reference;
8278 if (attribute_flag[2] != 0)
8279 geometry.height=argument_list[2].integer_reference;
8280 image=ScaleImage(image,geometry.width,geometry.height,exception);
8281 break;
8282 }
8283 case 26: /* Shade */
8284 {
8285 if (attribute_flag[0] != 0)
8286 {
8287 flags=ParseGeometry(argument_list[0].string_reference,
8288 &geometry_info);
8289 if ((flags & SigmaValue) == 0)
8290 geometry_info.sigma=0.0;
8291 }
8292 if (attribute_flag[1] != 0)
8293 geometry_info.rho=argument_list[1].real_reference;
8294 if (attribute_flag[2] != 0)
8295 geometry_info.sigma=argument_list[2].real_reference;
8296 image=ShadeImage(image,
8297 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8298 geometry_info.rho,geometry_info.sigma,exception);
8299 break;
8300 }
8301 case 27: /* Sharpen */
8302 {
8303 if (attribute_flag[0] != 0)
8304 {
8305 flags=ParseGeometry(argument_list[0].string_reference,
8306 &geometry_info);
8307 if ((flags & SigmaValue) == 0)
8308 geometry_info.sigma=1.0;
8309 }
8310 if (attribute_flag[1] != 0)
8311 geometry_info.rho=argument_list[1].real_reference;
8312 if (attribute_flag[2] != 0)
8313 geometry_info.sigma=argument_list[2].real_reference;
8314 if (attribute_flag[3] != 0)
8315 channel=(ChannelType) argument_list[3].integer_reference;
8316 channel_mask=SetImageChannelMask(image,channel);
8317 image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8318 exception);
8319 if (image != (Image *) NULL)
8320 (void) SetImageChannelMask(image,channel_mask);
8321 break;
8322 }
8323 case 28: /* Shear */
8324 {
8325 if (attribute_flag[0] != 0)
8326 {
8327 flags=ParseGeometry(argument_list[0].string_reference,
8328 &geometry_info);
8329 if ((flags & SigmaValue) == 0)
8330 geometry_info.sigma=geometry_info.rho;
8331 }
8332 if (attribute_flag[1] != 0)
8333 geometry_info.rho=argument_list[1].real_reference;
8334 if (attribute_flag[2] != 0)
8335 geometry_info.sigma=argument_list[2].real_reference;
8336 if (attribute_flag[3] != 0)
8337 QueryColorCompliance(argument_list[3].string_reference,
8338 AllCompliance,&image->background_color,exception);
8339 if (attribute_flag[4] != 0)
8340 QueryColorCompliance(argument_list[4].string_reference,
8341 AllCompliance,&image->background_color,exception);
8342 image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8343 exception);
8344 break;
8345 }
8346 case 29: /* Spread */
8347 {
Cristye3319c12015-08-24 07:11:48 -04008348 PixelInterpolateMethod
8349 method;
8350
cristy4a3ce0a2013-08-03 20:06:59 +00008351 if (attribute_flag[0] == 0)
8352 argument_list[0].real_reference=1.0;
Cristye3319c12015-08-24 07:11:48 -04008353 method=UndefinedInterpolatePixel;
8354 if (attribute_flag[1] != 0)
8355 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8356 image=SpreadImage(image,method,argument_list[0].real_reference,
8357 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008358 break;
8359 }
8360 case 30: /* Swirl */
8361 {
8362 PixelInterpolateMethod
8363 method;
8364
8365 if (attribute_flag[0] == 0)
8366 argument_list[0].real_reference=50.0;
8367 method=UndefinedInterpolatePixel;
8368 if (attribute_flag[1] != 0)
8369 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8370 image=SwirlImage(image,argument_list[0].real_reference,
8371 method,exception);
8372 break;
8373 }
8374 case 31: /* Resize */
8375 case 32: /* Zoom */
8376 {
8377 if (attribute_flag[0] != 0)
8378 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8379 &geometry,exception);
8380 if (attribute_flag[1] != 0)
8381 geometry.width=argument_list[1].integer_reference;
8382 if (attribute_flag[2] != 0)
8383 geometry.height=argument_list[2].integer_reference;
8384 if (attribute_flag[3] == 0)
8385 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8386 if (attribute_flag[4] != 0)
8387 SetImageArtifact(image,"filter:support",
8388 argument_list[4].string_reference);
8389 image=ResizeImage(image,geometry.width,geometry.height,
Cristy8645e042016-02-03 16:35:29 -05008390 (FilterType) argument_list[3].integer_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00008391 exception);
8392 break;
8393 }
8394 case 33: /* Annotate */
8395 {
8396 DrawInfo
8397 *draw_info;
8398
8399 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8400 (DrawInfo *) NULL);
8401 if (attribute_flag[0] != 0)
8402 {
8403 char
8404 *text;
8405
8406 text=InterpretImageProperties(info ? info->image_info :
8407 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8408 exception);
8409 (void) CloneString(&draw_info->text,text);
8410 text=DestroyString(text);
8411 }
8412 if (attribute_flag[1] != 0)
8413 (void) CloneString(&draw_info->font,
8414 argument_list[1].string_reference);
8415 if (attribute_flag[2] != 0)
8416 draw_info->pointsize=argument_list[2].real_reference;
8417 if (attribute_flag[3] != 0)
8418 (void) CloneString(&draw_info->density,
8419 argument_list[3].string_reference);
8420 if (attribute_flag[4] != 0)
8421 (void) QueryColorCompliance(argument_list[4].string_reference,
8422 AllCompliance,&draw_info->undercolor,exception);
8423 if (attribute_flag[5] != 0)
8424 {
8425 (void) QueryColorCompliance(argument_list[5].string_reference,
8426 AllCompliance,&draw_info->stroke,exception);
8427 if (argument_list[5].image_reference != (Image *) NULL)
8428 draw_info->stroke_pattern=CloneImage(
8429 argument_list[5].image_reference,0,0,MagickTrue,exception);
8430 }
8431 if (attribute_flag[6] != 0)
8432 {
8433 (void) QueryColorCompliance(argument_list[6].string_reference,
8434 AllCompliance,&draw_info->fill,exception);
8435 if (argument_list[6].image_reference != (Image *) NULL)
8436 draw_info->fill_pattern=CloneImage(
8437 argument_list[6].image_reference,0,0,MagickTrue,exception);
8438 }
8439 if (attribute_flag[7] != 0)
8440 {
8441 (void) CloneString(&draw_info->geometry,
8442 argument_list[7].string_reference);
8443 flags=ParsePageGeometry(image,argument_list[7].string_reference,
8444 &geometry,exception);
8445 if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8446 geometry_info.sigma=geometry_info.xi;
8447 }
8448 if (attribute_flag[8] != 0)
8449 (void) QueryColorCompliance(argument_list[8].string_reference,
8450 AllCompliance,&draw_info->fill,exception);
8451 if (attribute_flag[11] != 0)
8452 draw_info->gravity=(GravityType)
8453 argument_list[11].integer_reference;
8454 if (attribute_flag[25] != 0)
8455 {
8456 AV
8457 *av;
8458
8459 av=(AV *) argument_list[25].array_reference;
8460 if ((av_len(av) != 3) && (av_len(av) != 5))
8461 {
8462 ThrowPerlException(exception,OptionError,
8463 "affine matrix must have 4 or 6 elements",PackageName);
8464 goto PerlException;
8465 }
8466 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8467 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8468 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8469 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8470 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8471 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8472 {
8473 ThrowPerlException(exception,OptionError,
8474 "affine matrix is singular",PackageName);
8475 goto PerlException;
8476 }
8477 if (av_len(av) == 5)
8478 {
8479 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8480 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8481 }
8482 }
8483 for (j=12; j < 17; j++)
8484 {
8485 if (attribute_flag[j] == 0)
8486 continue;
8487 value=argument_list[j].string_reference;
8488 angle=argument_list[j].real_reference;
8489 current=draw_info->affine;
8490 GetAffineMatrix(&affine);
8491 switch (j)
8492 {
8493 case 12:
8494 {
8495 /*
8496 Translate.
8497 */
8498 flags=ParseGeometry(value,&geometry_info);
8499 affine.tx=geometry_info.xi;
8500 affine.ty=geometry_info.psi;
8501 if ((flags & PsiValue) == 0)
8502 affine.ty=affine.tx;
8503 break;
8504 }
8505 case 13:
8506 {
8507 /*
8508 Scale.
8509 */
8510 flags=ParseGeometry(value,&geometry_info);
8511 affine.sx=geometry_info.rho;
8512 affine.sy=geometry_info.sigma;
8513 if ((flags & SigmaValue) == 0)
8514 affine.sy=affine.sx;
8515 break;
8516 }
8517 case 14:
8518 {
8519 /*
8520 Rotate.
8521 */
8522 if (angle == 0.0)
8523 break;
8524 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8525 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8526 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8527 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8528 break;
8529 }
8530 case 15:
8531 {
8532 /*
8533 SkewX.
8534 */
8535 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8536 break;
8537 }
8538 case 16:
8539 {
8540 /*
8541 SkewY.
8542 */
8543 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8544 break;
8545 }
8546 }
8547 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8548 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8549 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8550 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8551 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8552 current.tx;
8553 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8554 current.ty;
8555 }
8556 if (attribute_flag[9] == 0)
8557 argument_list[9].real_reference=0.0;
8558 if (attribute_flag[10] == 0)
8559 argument_list[10].real_reference=0.0;
8560 if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8561 {
8562 char
cristy151b66d2015-04-15 10:50:31 +00008563 geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008564
cristy151b66d2015-04-15 10:50:31 +00008565 (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
cristy4a3ce0a2013-08-03 20:06:59 +00008566 (double) argument_list[9].real_reference+draw_info->affine.tx,
8567 (double) argument_list[10].real_reference+draw_info->affine.ty);
8568 (void) CloneString(&draw_info->geometry,geometry);
8569 }
8570 if (attribute_flag[17] != 0)
8571 draw_info->stroke_width=argument_list[17].real_reference;
8572 if (attribute_flag[18] != 0)
8573 {
8574 draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8575 MagickTrue : MagickFalse;
8576 draw_info->stroke_antialias=draw_info->text_antialias;
8577 }
8578 if (attribute_flag[19] != 0)
8579 (void) CloneString(&draw_info->family,
8580 argument_list[19].string_reference);
8581 if (attribute_flag[20] != 0)
8582 draw_info->style=(StyleType) argument_list[20].integer_reference;
8583 if (attribute_flag[21] != 0)
8584 draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8585 if (attribute_flag[22] != 0)
8586 draw_info->weight=argument_list[22].integer_reference;
8587 if (attribute_flag[23] != 0)
8588 draw_info->align=(AlignType) argument_list[23].integer_reference;
8589 if (attribute_flag[24] != 0)
8590 (void) CloneString(&draw_info->encoding,
8591 argument_list[24].string_reference);
8592 if (attribute_flag[25] != 0)
8593 draw_info->fill_pattern=CloneImage(
8594 argument_list[25].image_reference,0,0,MagickTrue,exception);
8595 if (attribute_flag[26] != 0)
8596 draw_info->fill_pattern=CloneImage(
8597 argument_list[26].image_reference,0,0,MagickTrue,exception);
8598 if (attribute_flag[27] != 0)
8599 draw_info->stroke_pattern=CloneImage(
8600 argument_list[27].image_reference,0,0,MagickTrue,exception);
8601 if (attribute_flag[29] != 0)
8602 draw_info->kerning=argument_list[29].real_reference;
8603 if (attribute_flag[30] != 0)
8604 draw_info->interline_spacing=argument_list[30].real_reference;
8605 if (attribute_flag[31] != 0)
8606 draw_info->interword_spacing=argument_list[31].real_reference;
8607 if (attribute_flag[32] != 0)
8608 draw_info->direction=(DirectionType)
8609 argument_list[32].integer_reference;
Cristy3d1de822019-02-15 18:06:30 -05008610 if (attribute_flag[33] != 0)
8611 draw_info->decorate=(DecorationType)
8612 argument_list[33].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00008613 (void) AnnotateImage(image,draw_info,exception);
8614 draw_info=DestroyDrawInfo(draw_info);
8615 break;
8616 }
8617 case 34: /* ColorFloodfill */
8618 {
8619 DrawInfo
8620 *draw_info;
8621
8622 MagickBooleanType
8623 invert;
8624
8625 PixelInfo
8626 target;
8627
8628 draw_info=CloneDrawInfo(info ? info->image_info :
8629 (ImageInfo *) NULL,(DrawInfo *) NULL);
8630 if (attribute_flag[0] != 0)
8631 flags=ParsePageGeometry(image,argument_list[0].string_reference,
8632 &geometry,exception);
8633 if (attribute_flag[1] != 0)
8634 geometry.x=argument_list[1].integer_reference;
8635 if (attribute_flag[2] != 0)
8636 geometry.y=argument_list[2].integer_reference;
8637 if (attribute_flag[3] != 0)
8638 (void) QueryColorCompliance(argument_list[3].string_reference,
8639 AllCompliance,&draw_info->fill,exception);
8640 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8641 geometry.x,geometry.y,&target,exception);
8642 invert=MagickFalse;
8643 if (attribute_flag[4] != 0)
8644 {
8645 QueryColorCompliance(argument_list[4].string_reference,
8646 AllCompliance,&target,exception);
8647 invert=MagickTrue;
8648 }
8649 if (attribute_flag[5] != 0)
8650 image->fuzz=StringToDoubleInterval(
8651 argument_list[5].string_reference,(double) QuantumRange+1.0);
8652 if (attribute_flag[6] != 0)
8653 invert=(MagickBooleanType) argument_list[6].integer_reference;
8654 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8655 geometry.y,invert,exception);
8656 draw_info=DestroyDrawInfo(draw_info);
8657 break;
8658 }
8659 case 35: /* Composite */
8660 {
8661 char
cristy151b66d2015-04-15 10:50:31 +00008662 composite_geometry[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00008663
8664 Image
8665 *composite_image,
8666 *rotate_image;
8667
8668 MagickBooleanType
8669 clip_to_self;
8670
8671 compose=OverCompositeOp;
8672 if (attribute_flag[0] != 0)
8673 composite_image=argument_list[0].image_reference;
8674 else
8675 {
8676 ThrowPerlException(exception,OptionError,
8677 "CompositeImageRequired",PackageName);
8678 goto PerlException;
8679 }
8680 /*
8681 Parameter Handling used for BOTH normal and tiled composition.
8682 */
8683 if (attribute_flag[1] != 0) /* compose */
8684 compose=(CompositeOperator) argument_list[1].integer_reference;
8685 if (attribute_flag[6] != 0) /* opacity */
8686 {
8687 if (compose != DissolveCompositeOp)
8688 (void) SetImageAlpha(composite_image,(Quantum)
8689 StringToDoubleInterval(argument_list[6].string_reference,
8690 (double) QuantumRange+1.0),exception);
8691 else
8692 {
8693 CacheView
8694 *composite_view;
8695
8696 double
8697 opacity;
8698
8699 MagickBooleanType
8700 sync;
8701
8702 register ssize_t
8703 x;
8704
8705 register Quantum
8706 *q;
8707
8708 ssize_t
8709 y;
8710
8711 /*
8712 Handle dissolve composite operator (patch by
8713 Kevin A. McGrail).
8714 */
8715 (void) CloneString(&image->geometry,
8716 argument_list[6].string_reference);
8717 opacity=(Quantum) StringToDoubleInterval(
8718 argument_list[6].string_reference,(double) QuantumRange+
8719 1.0);
cristy17f11b02014-12-20 19:37:04 +00008720 if (composite_image->alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00008721 (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8722 composite_view=AcquireAuthenticCacheView(composite_image,exception);
8723 for (y=0; y < (ssize_t) composite_image->rows ; y++)
8724 {
8725 q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8726 composite_image->columns,1,exception);
8727 for (x=0; x < (ssize_t) composite_image->columns; x++)
8728 {
8729 if (GetPixelAlpha(image,q) == OpaqueAlpha)
8730 SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8731 q);
8732 q+=GetPixelChannels(composite_image);
8733 }
8734 sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8735 if (sync == MagickFalse)
8736 break;
8737 }
8738 composite_view=DestroyCacheView(composite_view);
8739 }
8740 }
8741 if (attribute_flag[9] != 0) /* "color=>" */
8742 QueryColorCompliance(argument_list[9].string_reference,
8743 AllCompliance,&composite_image->background_color,exception);
8744 if (attribute_flag[12] != 0) /* "interpolate=>" */
8745 image->interpolate=(PixelInterpolateMethod)
8746 argument_list[12].integer_reference;
8747 if (attribute_flag[13] != 0) /* "args=>" */
8748 (void) SetImageArtifact(composite_image,"compose:args",
8749 argument_list[13].string_reference);
8750 if (attribute_flag[14] != 0) /* "blend=>" depreciated */
8751 (void) SetImageArtifact(composite_image,"compose:args",
8752 argument_list[14].string_reference);
Cristy72aed842018-07-08 18:25:50 -04008753 clip_to_self=MagickTrue;
8754 switch (compose)
8755 {
8756 case ClearCompositeOp:
8757 case SrcCompositeOp:
8758 case InCompositeOp:
8759 case SrcInCompositeOp:
8760 case OutCompositeOp:
8761 case SrcOutCompositeOp:
8762 case DstInCompositeOp:
8763 case DstAtopCompositeOp:
Cristy901f5212018-07-08 18:43:34 -04008764 case CopyAlphaCompositeOp:
Cristy72aed842018-07-08 18:25:50 -04008765 case ChangeMaskCompositeOp:
8766 case DissolveCompositeOp:
8767 case BlendCompositeOp:
8768 {
Cristy901f5212018-07-08 18:43:34 -04008769 clip_to_self=MagickFalse;
Cristy72aed842018-07-08 18:25:50 -04008770 break;
8771 }
8772 default:
8773 break;
8774 }
cristy4a3ce0a2013-08-03 20:06:59 +00008775 if (attribute_flag[15] != 0)
8776 clip_to_self=(MagickBooleanType)
8777 argument_list[15].integer_reference;
8778 /*
8779 Tiling Composition (with orthogonal rotate).
8780 */
8781 rotate_image=(Image *) NULL;
8782 if (attribute_flag[8] != 0) /* "rotate=>" */
8783 {
8784 /*
8785 Rotate image.
8786 */
8787 rotate_image=RotateImage(composite_image,
8788 argument_list[8].real_reference,exception);
8789 if (rotate_image == (Image *) NULL)
8790 break;
8791 }
8792 if ((attribute_flag[7] != 0) &&
8793 (argument_list[7].integer_reference != 0)) /* tile */
8794 {
8795 ssize_t
8796 x,
8797 y;
8798
8799 /*
8800 Tile the composite image.
8801 */
cristy4a3ce0a2013-08-03 20:06:59 +00008802 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8803 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8804 {
8805 if (attribute_flag[8] != 0) /* rotate */
8806 (void) CompositeImage(image,rotate_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008807 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008808 else
8809 (void) CompositeImage(image,composite_image,compose,
Cristyde6c67d2018-07-08 19:14:08 -04008810 MagickTrue,x,y,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008811 }
8812 if (attribute_flag[8] != 0) /* rotate */
8813 rotate_image=DestroyImage(rotate_image);
8814 break;
8815 }
8816 /*
8817 Parameter Handling used used ONLY for normal composition.
8818 */
8819 if (attribute_flag[5] != 0) /* gravity */
8820 image->gravity=(GravityType) argument_list[5].integer_reference;
8821 if (attribute_flag[2] != 0) /* geometry offset */
8822 {
8823 SetGeometry(image,&geometry);
8824 (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8825 &geometry);
8826 GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8827 &geometry);
8828 }
8829 if (attribute_flag[3] != 0) /* x offset */
8830 geometry.x=argument_list[3].integer_reference;
8831 if (attribute_flag[4] != 0) /* y offset */
8832 geometry.y=argument_list[4].integer_reference;
8833 if (attribute_flag[10] != 0) /* mask */
8834 {
8835 if ((image->compose == DisplaceCompositeOp) ||
8836 (image->compose == DistortCompositeOp))
8837 {
8838 /*
8839 Merge Y displacement into X displacement image.
8840 */
8841 composite_image=CloneImage(composite_image,0,0,MagickTrue,
8842 exception);
8843 (void) CompositeImage(composite_image,
8844 argument_list[10].image_reference,CopyGreenCompositeOp,
Cristy74e39292018-07-08 13:13:20 -04008845 clip_to_self,0,0,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008846 }
8847 else
8848 {
8849 Image
8850 *mask_image;
8851
8852 /*
8853 Set a blending mask for the composition.
8854 */
8855 mask_image=CloneImage(argument_list[10].image_reference,0,0,
8856 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +00008857 (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
cristyf3023752015-07-28 17:13:22 +00008858 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008859 mask_image=DestroyImage(mask_image);
8860 }
8861 }
8862 if (attribute_flag[11] != 0) /* channel */
8863 channel=(ChannelType) argument_list[11].integer_reference;
8864 /*
8865 Composite two images (normal composition).
8866 */
cristy151b66d2015-04-15 10:50:31 +00008867 (void) FormatLocaleString(composite_geometry,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +00008868 "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8869 (double) composite_image->rows,(double) geometry.x,(double)
8870 geometry.y);
8871 flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8872 exception);
8873 channel_mask=SetImageChannelMask(image,channel);
8874 if (attribute_flag[8] == 0) /* no rotate */
8875 CompositeImage(image,composite_image,compose,clip_to_self,
8876 geometry.x,geometry.y,exception);
8877 else
8878 {
8879 /*
8880 Position adjust rotated image then composite.
8881 */
8882 geometry.x-=(ssize_t) (rotate_image->columns-
8883 composite_image->columns)/2;
8884 geometry.y-=(ssize_t) (rotate_image->rows-
8885 composite_image->rows)/2;
8886 CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8887 geometry.y,exception);
8888 rotate_image=DestroyImage(rotate_image);
8889 }
8890 if (attribute_flag[10] != 0) /* mask */
8891 {
8892 if ((image->compose == DisplaceCompositeOp) ||
8893 (image->compose == DistortCompositeOp))
8894 composite_image=DestroyImage(composite_image);
8895 else
cristy1f7ffb72015-07-29 11:07:03 +00008896 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
cristyf3023752015-07-28 17:13:22 +00008897 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00008898 }
8899 (void) SetImageChannelMask(image,channel_mask);
8900 break;
8901 }
8902 case 36: /* Contrast */
8903 {
8904 if (attribute_flag[0] == 0)
8905 argument_list[0].integer_reference=0;
8906 (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8907 MagickTrue : MagickFalse,exception);
8908 break;
8909 }
8910 case 37: /* CycleColormap */
8911 {
8912 if (attribute_flag[0] == 0)
8913 argument_list[0].integer_reference=6;
8914 (void) CycleColormapImage(image,argument_list[0].integer_reference,
8915 exception);
8916 break;
8917 }
8918 case 38: /* Draw */
8919 {
8920 DrawInfo
8921 *draw_info;
8922
8923 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8924 (DrawInfo *) NULL);
8925 (void) CloneString(&draw_info->primitive,"point");
8926 if (attribute_flag[0] != 0)
8927 {
8928 if (argument_list[0].integer_reference < 0)
8929 (void) CloneString(&draw_info->primitive,
8930 argument_list[0].string_reference);
8931 else
8932 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8933 MagickPrimitiveOptions,argument_list[0].integer_reference));
8934 }
8935 if (attribute_flag[1] != 0)
8936 {
8937 if (LocaleCompare(draw_info->primitive,"path") == 0)
8938 {
8939 (void) ConcatenateString(&draw_info->primitive," '");
8940 ConcatenateString(&draw_info->primitive,
8941 argument_list[1].string_reference);
8942 (void) ConcatenateString(&draw_info->primitive,"'");
8943 }
8944 else
8945 {
8946 (void) ConcatenateString(&draw_info->primitive," ");
8947 ConcatenateString(&draw_info->primitive,
8948 argument_list[1].string_reference);
8949 }
8950 }
8951 if (attribute_flag[2] != 0)
8952 {
8953 (void) ConcatenateString(&draw_info->primitive," ");
8954 (void) ConcatenateString(&draw_info->primitive,
8955 CommandOptionToMnemonic(MagickMethodOptions,
8956 argument_list[2].integer_reference));
8957 }
8958 if (attribute_flag[3] != 0)
8959 {
8960 (void) QueryColorCompliance(argument_list[3].string_reference,
8961 AllCompliance,&draw_info->stroke,exception);
8962 if (argument_list[3].image_reference != (Image *) NULL)
8963 draw_info->stroke_pattern=CloneImage(
8964 argument_list[3].image_reference,0,0,MagickTrue,exception);
8965 }
8966 if (attribute_flag[4] != 0)
8967 {
8968 (void) QueryColorCompliance(argument_list[4].string_reference,
8969 AllCompliance,&draw_info->fill,exception);
8970 if (argument_list[4].image_reference != (Image *) NULL)
8971 draw_info->fill_pattern=CloneImage(
8972 argument_list[4].image_reference,0,0,MagickTrue,exception);
8973 }
8974 if (attribute_flag[5] != 0)
8975 draw_info->stroke_width=argument_list[5].real_reference;
8976 if (attribute_flag[6] != 0)
8977 (void) CloneString(&draw_info->font,
8978 argument_list[6].string_reference);
8979 if (attribute_flag[7] != 0)
8980 (void) QueryColorCompliance(argument_list[7].string_reference,
8981 AllCompliance,&draw_info->border_color,exception);
8982 if (attribute_flag[8] != 0)
8983 draw_info->affine.tx=argument_list[8].real_reference;
8984 if (attribute_flag[9] != 0)
8985 draw_info->affine.ty=argument_list[9].real_reference;
8986 if (attribute_flag[20] != 0)
8987 {
8988 AV
8989 *av;
8990
8991 av=(AV *) argument_list[20].array_reference;
8992 if ((av_len(av) != 3) && (av_len(av) != 5))
8993 {
8994 ThrowPerlException(exception,OptionError,
8995 "affine matrix must have 4 or 6 elements",PackageName);
8996 goto PerlException;
8997 }
8998 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8999 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9000 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9001 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9002 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9003 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9004 {
9005 ThrowPerlException(exception,OptionError,
9006 "affine matrix is singular",PackageName);
9007 goto PerlException;
9008 }
9009 if (av_len(av) == 5)
9010 {
9011 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9012 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9013 }
9014 }
9015 for (j=10; j < 15; j++)
9016 {
9017 if (attribute_flag[j] == 0)
9018 continue;
9019 value=argument_list[j].string_reference;
9020 angle=argument_list[j].real_reference;
9021 current=draw_info->affine;
9022 GetAffineMatrix(&affine);
9023 switch (j)
9024 {
9025 case 10:
9026 {
9027 /*
9028 Translate.
9029 */
9030 flags=ParseGeometry(value,&geometry_info);
9031 affine.tx=geometry_info.xi;
9032 affine.ty=geometry_info.psi;
9033 if ((flags & PsiValue) == 0)
9034 affine.ty=affine.tx;
9035 break;
9036 }
9037 case 11:
9038 {
9039 /*
9040 Scale.
9041 */
9042 flags=ParseGeometry(value,&geometry_info);
9043 affine.sx=geometry_info.rho;
9044 affine.sy=geometry_info.sigma;
9045 if ((flags & SigmaValue) == 0)
9046 affine.sy=affine.sx;
9047 break;
9048 }
9049 case 12:
9050 {
9051 /*
9052 Rotate.
9053 */
9054 if (angle == 0.0)
9055 break;
9056 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9057 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9058 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9059 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9060 break;
9061 }
9062 case 13:
9063 {
9064 /*
9065 SkewX.
9066 */
9067 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9068 break;
9069 }
9070 case 14:
9071 {
9072 /*
9073 SkewY.
9074 */
9075 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9076 break;
9077 }
9078 }
9079 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9080 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9081 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9082 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9083 draw_info->affine.tx=
9084 current.sx*affine.tx+current.ry*affine.ty+current.tx;
9085 draw_info->affine.ty=
9086 current.rx*affine.tx+current.sy*affine.ty+current.ty;
9087 }
9088 if (attribute_flag[15] != 0)
9089 draw_info->fill_pattern=CloneImage(
9090 argument_list[15].image_reference,0,0,MagickTrue,exception);
9091 if (attribute_flag[16] != 0)
9092 draw_info->pointsize=argument_list[16].real_reference;
9093 if (attribute_flag[17] != 0)
9094 {
Cristy36c30b62018-11-22 09:33:30 -05009095 draw_info->stroke_antialias=argument_list[17].integer_reference != 0 ? MagickTrue : MagickFalse;
cristy4a3ce0a2013-08-03 20:06:59 +00009096 draw_info->text_antialias=draw_info->stroke_antialias;
9097 }
9098 if (attribute_flag[18] != 0)
9099 (void) CloneString(&draw_info->density,
9100 argument_list[18].string_reference);
9101 if (attribute_flag[19] != 0)
9102 draw_info->stroke_width=argument_list[19].real_reference;
9103 if (attribute_flag[21] != 0)
9104 draw_info->dash_offset=argument_list[21].real_reference;
9105 if (attribute_flag[22] != 0)
9106 {
9107 AV
9108 *av;
9109
9110 av=(AV *) argument_list[22].array_reference;
9111 draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9112 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9113 if (draw_info->dash_pattern != (double *) NULL)
9114 {
9115 for (i=0; i <= av_len(av); i++)
9116 draw_info->dash_pattern[i]=(double)
9117 SvNV(*(av_fetch(av,i,0)));
9118 draw_info->dash_pattern[i]=0.0;
9119 }
9120 }
9121 if (attribute_flag[23] != 0)
9122 image->interpolate=(PixelInterpolateMethod)
9123 argument_list[23].integer_reference;
9124 if ((attribute_flag[24] != 0) &&
9125 (draw_info->fill_pattern != (Image *) NULL))
9126 flags=ParsePageGeometry(draw_info->fill_pattern,
9127 argument_list[24].string_reference,
9128 &draw_info->fill_pattern->tile_offset,exception);
9129 if (attribute_flag[25] != 0)
9130 {
9131 (void) ConcatenateString(&draw_info->primitive," '");
9132 (void) ConcatenateString(&draw_info->primitive,
9133 argument_list[25].string_reference);
9134 (void) ConcatenateString(&draw_info->primitive,"'");
9135 }
9136 if (attribute_flag[26] != 0)
9137 draw_info->fill_pattern=CloneImage(
9138 argument_list[26].image_reference,0,0,MagickTrue,exception);
9139 if (attribute_flag[27] != 0)
9140 draw_info->stroke_pattern=CloneImage(
9141 argument_list[27].image_reference,0,0,MagickTrue,exception);
9142 if (attribute_flag[28] != 0)
9143 (void) CloneString(&draw_info->primitive,
9144 argument_list[28].string_reference);
9145 if (attribute_flag[29] != 0)
9146 draw_info->kerning=argument_list[29].real_reference;
9147 if (attribute_flag[30] != 0)
9148 draw_info->interline_spacing=argument_list[30].real_reference;
9149 if (attribute_flag[31] != 0)
9150 draw_info->interword_spacing=argument_list[31].real_reference;
9151 if (attribute_flag[32] != 0)
9152 draw_info->direction=(DirectionType)
9153 argument_list[32].integer_reference;
Cristy36c30b62018-11-22 09:33:30 -05009154 (void) DrawImage(image,draw_info,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009155 draw_info=DestroyDrawInfo(draw_info);
9156 break;
9157 }
9158 case 39: /* Equalize */
9159 {
9160 if (attribute_flag[0] != 0)
9161 channel=(ChannelType) argument_list[0].integer_reference;
9162 channel_mask=SetImageChannelMask(image,channel);
Cristy36c30b62018-11-22 09:33:30 -05009163 (void) EqualizeImage(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009164 (void) SetImageChannelMask(image,channel_mask);
9165 break;
9166 }
9167 case 40: /* Gamma */
9168 {
9169 if (attribute_flag[1] != 0)
9170 channel=(ChannelType) argument_list[1].integer_reference;
9171 if (attribute_flag[2] == 0)
9172 argument_list[2].real_reference=1.0;
9173 if (attribute_flag[3] == 0)
9174 argument_list[3].real_reference=1.0;
9175 if (attribute_flag[4] == 0)
9176 argument_list[4].real_reference=1.0;
9177 if (attribute_flag[0] == 0)
9178 {
cristy151b66d2015-04-15 10:50:31 +00009179 (void) FormatLocaleString(message,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -05009180 "%.20g,%.20g,%.20g",(double) argument_list[2].real_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009181 (double) argument_list[3].real_reference,
9182 (double) argument_list[4].real_reference);
9183 argument_list[0].string_reference=message;
9184 }
9185 (void) GammaImage(image,StringToDouble(
9186 argument_list[0].string_reference,(char **) NULL),exception);
9187 break;
9188 }
9189 case 41: /* Map */
9190 {
9191 QuantizeInfo
9192 *quantize_info;
9193
9194 if (attribute_flag[0] == 0)
9195 {
9196 ThrowPerlException(exception,OptionError,"MapImageRequired",
9197 PackageName);
9198 goto PerlException;
9199 }
9200 quantize_info=AcquireQuantizeInfo(info->image_info);
9201 if (attribute_flag[1] != 0)
9202 quantize_info->dither_method=(DitherMethod)
9203 argument_list[1].integer_reference;
9204 (void) RemapImages(quantize_info,image,
9205 argument_list[0].image_reference,exception);
9206 quantize_info=DestroyQuantizeInfo(quantize_info);
9207 break;
9208 }
9209 case 42: /* MatteFloodfill */
9210 {
9211 DrawInfo
9212 *draw_info;
9213
9214 MagickBooleanType
9215 invert;
9216
9217 PixelInfo
9218 target;
9219
9220 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9221 (DrawInfo *) NULL);
9222 if (attribute_flag[0] != 0)
9223 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9224 &geometry,exception);
9225 if (attribute_flag[1] != 0)
9226 geometry.x=argument_list[1].integer_reference;
9227 if (attribute_flag[2] != 0)
9228 geometry.y=argument_list[2].integer_reference;
cristy17f11b02014-12-20 19:37:04 +00009229 if (image->alpha_trait == UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +00009230 (void) SetImageAlpha(image,OpaqueAlpha,exception);
9231 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9232 geometry.x,geometry.y,&target,exception);
9233 if (attribute_flag[4] != 0)
9234 QueryColorCompliance(argument_list[4].string_reference,
9235 AllCompliance,&target,exception);
9236 if (attribute_flag[3] != 0)
9237 target.alpha=StringToDoubleInterval(
9238 argument_list[3].string_reference,(double) (double) QuantumRange+
9239 1.0);
9240 if (attribute_flag[5] != 0)
9241 image->fuzz=StringToDoubleInterval(
9242 argument_list[5].string_reference,(double) QuantumRange+1.0);
9243 invert=MagickFalse;
9244 if (attribute_flag[6] != 0)
9245 invert=(MagickBooleanType) argument_list[6].integer_reference;
9246 channel_mask=SetImageChannelMask(image,AlphaChannel);
9247 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9248 geometry.y,invert,exception);
9249 (void) SetImageChannelMask(image,channel_mask);
9250 draw_info=DestroyDrawInfo(draw_info);
9251 break;
9252 }
9253 case 43: /* Modulate */
9254 {
9255 char
cristy151b66d2015-04-15 10:50:31 +00009256 modulate[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +00009257
9258 geometry_info.rho=100.0;
9259 geometry_info.sigma=100.0;
9260 geometry_info.xi=100.0;
9261 if (attribute_flag[0] != 0)
9262 (void)ParseGeometry(argument_list[0].string_reference,
9263 &geometry_info);
9264 if (attribute_flag[1] != 0)
9265 geometry_info.xi=argument_list[1].real_reference;
9266 if (attribute_flag[2] != 0)
9267 geometry_info.sigma=argument_list[2].real_reference;
9268 if (attribute_flag[3] != 0)
9269 {
9270 geometry_info.sigma=argument_list[3].real_reference;
9271 SetImageArtifact(image,"modulate:colorspace","HWB");
9272 }
9273 if (attribute_flag[4] != 0)
9274 {
9275 geometry_info.rho=argument_list[4].real_reference;
9276 SetImageArtifact(image,"modulate:colorspace","HSB");
9277 }
9278 if (attribute_flag[5] != 0)
9279 {
9280 geometry_info.sigma=argument_list[5].real_reference;
9281 SetImageArtifact(image,"modulate:colorspace","HSL");
9282 }
9283 if (attribute_flag[6] != 0)
9284 {
9285 geometry_info.rho=argument_list[6].real_reference;
9286 SetImageArtifact(image,"modulate:colorspace","HWB");
9287 }
Cristy935a4052017-03-31 17:45:37 -04009288 (void) FormatLocaleString(modulate,MagickPathExtent,"%.20g,%.20g,%.20g",
9289 geometry_info.rho,geometry_info.sigma,geometry_info.xi);
cristy4a3ce0a2013-08-03 20:06:59 +00009290 (void) ModulateImage(image,modulate,exception);
9291 break;
9292 }
9293 case 44: /* Negate */
9294 {
9295 if (attribute_flag[0] == 0)
9296 argument_list[0].integer_reference=0;
9297 if (attribute_flag[1] != 0)
9298 channel=(ChannelType) argument_list[1].integer_reference;
9299 channel_mask=SetImageChannelMask(image,channel);
9300 (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9301 MagickTrue : MagickFalse,exception);
9302 (void) SetImageChannelMask(image,channel_mask);
9303 break;
9304 }
9305 case 45: /* Normalize */
9306 {
9307 if (attribute_flag[0] != 0)
9308 channel=(ChannelType) argument_list[0].integer_reference;
9309 channel_mask=SetImageChannelMask(image,channel);
9310 NormalizeImage(image,exception);
9311 (void) SetImageChannelMask(image,channel_mask);
9312 break;
9313 }
9314 case 46: /* NumberColors */
9315 break;
9316 case 47: /* Opaque */
9317 {
9318 MagickBooleanType
9319 invert;
9320
9321 PixelInfo
9322 fill_color,
9323 target;
9324
9325 (void) QueryColorCompliance("none",AllCompliance,&target,
9326 exception);
9327 (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9328 exception);
9329 if (attribute_flag[0] != 0)
9330 (void) QueryColorCompliance(argument_list[0].string_reference,
9331 AllCompliance,&target,exception);
9332 if (attribute_flag[1] != 0)
9333 (void) QueryColorCompliance(argument_list[1].string_reference,
9334 AllCompliance,&fill_color,exception);
9335 if (attribute_flag[2] != 0)
9336 image->fuzz=StringToDoubleInterval(
9337 argument_list[2].string_reference,(double) QuantumRange+1.0);
9338 if (attribute_flag[3] != 0)
9339 channel=(ChannelType) argument_list[3].integer_reference;
9340 invert=MagickFalse;
9341 if (attribute_flag[4] != 0)
9342 invert=(MagickBooleanType) argument_list[4].integer_reference;
9343 channel_mask=SetImageChannelMask(image,channel);
9344 (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9345 (void) SetImageChannelMask(image,channel_mask);
9346 break;
9347 }
9348 case 48: /* Quantize */
9349 {
9350 QuantizeInfo
9351 *quantize_info;
9352
9353 quantize_info=AcquireQuantizeInfo(info->image_info);
9354 if (attribute_flag[0] != 0)
9355 quantize_info->number_colors=(size_t)
9356 argument_list[0].integer_reference;
9357 if (attribute_flag[1] != 0)
9358 quantize_info->tree_depth=(size_t)
9359 argument_list[1].integer_reference;
9360 if (attribute_flag[2] != 0)
9361 quantize_info->colorspace=(ColorspaceType)
9362 argument_list[2].integer_reference;
9363 if (attribute_flag[3] != 0)
cristy785c9342014-03-19 22:06:39 +00009364 quantize_info->dither_method=(DitherMethod)
9365 argument_list[3].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +00009366 if (attribute_flag[4] != 0)
cristy71716d52014-03-19 10:11:11 +00009367 quantize_info->measure_error=
9368 argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
cristy4a3ce0a2013-08-03 20:06:59 +00009369 if (attribute_flag[6] != 0)
cristyd472dd82014-03-19 22:04:36 +00009370 (void) QueryColorCompliance(argument_list[6].string_reference,
cristyf7563392014-03-25 13:54:04 +00009371 AllCompliance,&image->transparent_color,exception);
cristy71716d52014-03-19 10:11:11 +00009372 if (attribute_flag[7] != 0)
cristy4a3ce0a2013-08-03 20:06:59 +00009373 quantize_info->dither_method=(DitherMethod)
cristy71716d52014-03-19 10:11:11 +00009374 argument_list[7].integer_reference;
9375 if (attribute_flag[5] && argument_list[5].integer_reference)
cristyf7563392014-03-25 13:54:04 +00009376 (void) QuantizeImages(quantize_info,image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009377 else
cristyf7563392014-03-25 13:54:04 +00009378 if ((image->storage_class == DirectClass) ||
9379 (image->colors > quantize_info->number_colors) ||
9380 (quantize_info->colorspace == GRAYColorspace))
9381 (void) QuantizeImage(quantize_info,image,exception);
9382 else
9383 CompressImageColormap(image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009384 quantize_info=DestroyQuantizeInfo(quantize_info);
9385 break;
9386 }
9387 case 49: /* Raise */
9388 {
9389 if (attribute_flag[0] != 0)
9390 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9391 &geometry,exception);
9392 if (attribute_flag[1] != 0)
9393 geometry.width=argument_list[1].integer_reference;
9394 if (attribute_flag[2] != 0)
9395 geometry.height=argument_list[2].integer_reference;
9396 if (attribute_flag[3] == 0)
9397 argument_list[3].integer_reference=1;
9398 (void) RaiseImage(image,&geometry,
9399 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9400 exception);
9401 break;
9402 }
9403 case 50: /* Segment */
9404 {
9405 ColorspaceType
9406 colorspace;
9407
9408 double
9409 cluster_threshold,
9410 smoothing_threshold;
9411
9412 MagickBooleanType
9413 verbose;
9414
9415 cluster_threshold=1.0;
9416 smoothing_threshold=1.5;
9417 colorspace=sRGBColorspace;
9418 verbose=MagickFalse;
9419 if (attribute_flag[0] != 0)
9420 {
9421 flags=ParseGeometry(argument_list[0].string_reference,
9422 &geometry_info);
9423 cluster_threshold=geometry_info.rho;
9424 if (flags & SigmaValue)
9425 smoothing_threshold=geometry_info.sigma;
9426 }
9427 if (attribute_flag[1] != 0)
9428 cluster_threshold=argument_list[1].real_reference;
9429 if (attribute_flag[2] != 0)
9430 smoothing_threshold=argument_list[2].real_reference;
9431 if (attribute_flag[3] != 0)
9432 colorspace=(ColorspaceType) argument_list[3].integer_reference;
9433 if (attribute_flag[4] != 0)
9434 verbose=argument_list[4].integer_reference != 0 ?
9435 MagickTrue : MagickFalse;
9436 (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9437 smoothing_threshold,exception);
9438 break;
9439 }
9440 case 51: /* Signature */
9441 {
9442 (void) SignatureImage(image,exception);
9443 break;
9444 }
9445 case 52: /* Solarize */
9446 {
9447 geometry_info.rho=QuantumRange/2.0;
9448 if (attribute_flag[0] != 0)
9449 flags=ParseGeometry(argument_list[0].string_reference,
9450 &geometry_info);
9451 if (attribute_flag[1] != 0)
9452 geometry_info.rho=StringToDoubleInterval(
9453 argument_list[1].string_reference,(double) QuantumRange+1.0);
9454 (void) SolarizeImage(image,geometry_info.rho,exception);
9455 break;
9456 }
9457 case 53: /* Sync */
9458 {
9459 (void) SyncImage(image,exception);
9460 break;
9461 }
9462 case 54: /* Texture */
9463 {
9464 if (attribute_flag[0] == 0)
9465 break;
9466 TextureImage(image,argument_list[0].image_reference,exception);
9467 break;
9468 }
9469 case 55: /* Evalute */
9470 {
9471 MagickEvaluateOperator
9472 op;
9473
9474 op=SetEvaluateOperator;
9475 if (attribute_flag[0] == MagickFalse)
9476 argument_list[0].real_reference=0.0;
9477 if (attribute_flag[1] != MagickFalse)
9478 op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9479 if (attribute_flag[2] != MagickFalse)
9480 channel=(ChannelType) argument_list[2].integer_reference;
9481 channel_mask=SetImageChannelMask(image,channel);
9482 (void) EvaluateImage(image,op,argument_list[0].real_reference,
9483 exception);
9484 (void) SetImageChannelMask(image,channel_mask);
9485 break;
9486 }
9487 case 56: /* Transparent */
9488 {
9489 double
9490 opacity;
9491
9492 MagickBooleanType
9493 invert;
9494
9495 PixelInfo
9496 target;
9497
9498 (void) QueryColorCompliance("none",AllCompliance,&target,
9499 exception);
9500 if (attribute_flag[0] != 0)
9501 (void) QueryColorCompliance(argument_list[0].string_reference,
9502 AllCompliance,&target,exception);
9503 opacity=TransparentAlpha;
9504 if (attribute_flag[1] != 0)
9505 opacity=StringToDoubleInterval(argument_list[1].string_reference,
9506 (double) QuantumRange+1.0);
9507 if (attribute_flag[2] != 0)
9508 image->fuzz=StringToDoubleInterval(
9509 argument_list[2].string_reference,(double) QuantumRange+1.0);
9510 if (attribute_flag[3] == 0)
9511 argument_list[3].integer_reference=0;
9512 invert=MagickFalse;
9513 if (attribute_flag[3] != 0)
9514 invert=(MagickBooleanType) argument_list[3].integer_reference;
9515 (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9516 invert,exception);
9517 break;
9518 }
9519 case 57: /* Threshold */
9520 {
9521 double
9522 threshold;
9523
9524 if (attribute_flag[0] == 0)
9525 argument_list[0].string_reference="50%";
9526 if (attribute_flag[1] != 0)
9527 channel=(ChannelType) argument_list[1].integer_reference;
9528 threshold=StringToDoubleInterval(argument_list[0].string_reference,
9529 (double) QuantumRange+1.0);
9530 channel_mask=SetImageChannelMask(image,channel);
9531 (void) BilevelImage(image,threshold,exception);
9532 (void) SetImageChannelMask(image,channel_mask);
9533 break;
9534 }
9535 case 58: /* Charcoal */
9536 {
9537 if (attribute_flag[0] != 0)
9538 {
9539 flags=ParseGeometry(argument_list[0].string_reference,
9540 &geometry_info);
9541 if ((flags & SigmaValue) == 0)
9542 geometry_info.sigma=1.0;
9543 }
9544 if (attribute_flag[1] != 0)
9545 geometry_info.rho=argument_list[1].real_reference;
9546 if (attribute_flag[2] != 0)
9547 geometry_info.sigma=argument_list[2].real_reference;
9548 image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9549 exception);
9550 break;
9551 }
9552 case 59: /* Trim */
9553 {
9554 if (attribute_flag[0] != 0)
9555 image->fuzz=StringToDoubleInterval(
9556 argument_list[0].string_reference,(double) QuantumRange+1.0);
9557 image=TrimImage(image,exception);
9558 break;
9559 }
9560 case 60: /* Wave */
9561 {
9562 PixelInterpolateMethod
9563 method;
9564
9565 if (attribute_flag[0] != 0)
9566 {
9567 flags=ParseGeometry(argument_list[0].string_reference,
9568 &geometry_info);
9569 if ((flags & SigmaValue) == 0)
9570 geometry_info.sigma=1.0;
9571 }
9572 if (attribute_flag[1] != 0)
9573 geometry_info.rho=argument_list[1].real_reference;
9574 if (attribute_flag[2] != 0)
9575 geometry_info.sigma=argument_list[2].real_reference;
9576 method=UndefinedInterpolatePixel;
9577 if (attribute_flag[3] != 0)
9578 method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9579 image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9580 method,exception);
9581 break;
9582 }
9583 case 61: /* Separate */
9584 {
9585 if (attribute_flag[0] != 0)
9586 channel=(ChannelType) argument_list[0].integer_reference;
9587 image=SeparateImage(image,channel,exception);
9588 break;
9589 }
9590 case 63: /* Stereo */
9591 {
9592 if (attribute_flag[0] == 0)
9593 {
9594 ThrowPerlException(exception,OptionError,"StereoImageRequired",
9595 PackageName);
9596 goto PerlException;
9597 }
9598 if (attribute_flag[1] != 0)
9599 geometry.x=argument_list[1].integer_reference;
9600 if (attribute_flag[2] != 0)
9601 geometry.y=argument_list[2].integer_reference;
9602 image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9603 geometry.x,geometry.y,exception);
9604 break;
9605 }
9606 case 64: /* Stegano */
9607 {
9608 if (attribute_flag[0] == 0)
9609 {
9610 ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9611 PackageName);
9612 goto PerlException;
9613 }
9614 if (attribute_flag[1] == 0)
9615 argument_list[1].integer_reference=0;
9616 image->offset=argument_list[1].integer_reference;
9617 image=SteganoImage(image,argument_list[0].image_reference,exception);
9618 break;
9619 }
9620 case 65: /* Deconstruct */
9621 {
9622 image=CompareImagesLayers(image,CompareAnyLayer,exception);
9623 break;
9624 }
9625 case 66: /* GaussianBlur */
9626 {
9627 if (attribute_flag[0] != 0)
9628 {
9629 flags=ParseGeometry(argument_list[0].string_reference,
9630 &geometry_info);
9631 if ((flags & SigmaValue) == 0)
9632 geometry_info.sigma=1.0;
9633 }
9634 if (attribute_flag[1] != 0)
9635 geometry_info.rho=argument_list[1].real_reference;
9636 if (attribute_flag[2] != 0)
9637 geometry_info.sigma=argument_list[2].real_reference;
9638 if (attribute_flag[3] != 0)
9639 channel=(ChannelType) argument_list[3].integer_reference;
9640 channel_mask=SetImageChannelMask(image,channel);
9641 image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9642 exception);
9643 if (image != (Image *) NULL)
9644 (void) SetImageChannelMask(image,channel_mask);
9645 break;
9646 }
9647 case 67: /* Convolve */
9648 {
9649 KernelInfo
9650 *kernel;
9651
9652 kernel=(KernelInfo *) NULL;
9653 if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9654 break;
9655 if (attribute_flag[0] != 0)
9656 {
9657 AV
9658 *av;
9659
9660 size_t
9661 order;
9662
cristy2c57b742014-10-31 00:40:34 +00009663 kernel=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009664 if (kernel == (KernelInfo *) NULL)
9665 break;
9666 av=(AV *) argument_list[0].array_reference;
9667 order=(size_t) sqrt(av_len(av)+1);
9668 kernel->width=order;
9669 kernel->height=order;
9670 kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9671 order*sizeof(*kernel->values));
9672 if (kernel->values == (MagickRealType *) NULL)
9673 {
9674 kernel=DestroyKernelInfo(kernel);
9675 ThrowPerlException(exception,ResourceLimitFatalError,
9676 "MemoryAllocationFailed",PackageName);
9677 goto PerlException;
9678 }
9679 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9680 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9681 for ( ; j < (ssize_t) (order*order); j++)
9682 kernel->values[j]=0.0;
9683 }
9684 if (attribute_flag[1] != 0)
9685 channel=(ChannelType) argument_list[1].integer_reference;
9686 if (attribute_flag[2] != 0)
Cristyc4ff6bd2017-07-05 21:00:11 -04009687 SetImageArtifact(image,"convolve:bias",
cristy4a3ce0a2013-08-03 20:06:59 +00009688 argument_list[2].string_reference);
9689 if (attribute_flag[3] != 0)
9690 {
cristy2c57b742014-10-31 00:40:34 +00009691 kernel=AcquireKernelInfo(argument_list[3].string_reference,
9692 exception);
cristy4a3ce0a2013-08-03 20:06:59 +00009693 if (kernel == (KernelInfo *) NULL)
9694 break;
9695 }
9696 channel_mask=SetImageChannelMask(image,channel);
9697 image=ConvolveImage(image,kernel,exception);
9698 if (image != (Image *) NULL)
9699 (void) SetImageChannelMask(image,channel_mask);
9700 kernel=DestroyKernelInfo(kernel);
9701 break;
9702 }
9703 case 68: /* Profile */
9704 {
9705 const char
9706 *name;
9707
9708 Image
9709 *profile_image;
9710
9711 ImageInfo
9712 *profile_info;
9713
9714 StringInfo
9715 *profile;
9716
9717 name="*";
9718 if (attribute_flag[0] != 0)
9719 name=argument_list[0].string_reference;
9720 if (attribute_flag[2] != 0)
9721 image->rendering_intent=(RenderingIntent)
9722 argument_list[2].integer_reference;
9723 if (attribute_flag[3] != 0)
9724 image->black_point_compensation=
9725 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9726 if (attribute_flag[1] != 0)
9727 {
9728 if (argument_list[1].length == 0)
9729 {
9730 /*
9731 Remove a profile from the image.
9732 */
9733 (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9734 exception);
9735 break;
9736 }
9737 /*
9738 Associate user supplied profile with the image.
9739 */
9740 profile=AcquireStringInfo(argument_list[1].length);
9741 SetStringInfoDatum(profile,(const unsigned char *)
9742 argument_list[1].string_reference);
9743 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9744 (size_t) GetStringInfoLength(profile),exception);
9745 profile=DestroyStringInfo(profile);
9746 break;
9747 }
9748 /*
9749 Associate a profile with the image.
9750 */
9751 profile_info=CloneImageInfo(info ? info->image_info :
9752 (ImageInfo *) NULL);
9753 profile_image=ReadImages(profile_info,name,exception);
9754 if (profile_image == (Image *) NULL)
9755 break;
9756 ResetImageProfileIterator(profile_image);
9757 name=GetNextImageProfile(profile_image);
9758 while (name != (const char *) NULL)
9759 {
9760 const StringInfo
9761 *profile;
9762
9763 profile=GetImageProfile(profile_image,name);
9764 if (profile != (const StringInfo *) NULL)
9765 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9766 (size_t) GetStringInfoLength(profile),exception);
9767 name=GetNextImageProfile(profile_image);
9768 }
9769 profile_image=DestroyImage(profile_image);
9770 profile_info=DestroyImageInfo(profile_info);
9771 break;
9772 }
9773 case 69: /* UnsharpMask */
9774 {
9775 if (attribute_flag[0] != 0)
9776 {
9777 flags=ParseGeometry(argument_list[0].string_reference,
9778 &geometry_info);
9779 if ((flags & SigmaValue) == 0)
9780 geometry_info.sigma=1.0;
9781 if ((flags & XiValue) == 0)
9782 geometry_info.xi=1.0;
9783 if ((flags & PsiValue) == 0)
9784 geometry_info.psi=0.5;
9785 }
9786 if (attribute_flag[1] != 0)
9787 geometry_info.rho=argument_list[1].real_reference;
9788 if (attribute_flag[2] != 0)
9789 geometry_info.sigma=argument_list[2].real_reference;
9790 if (attribute_flag[3] != 0)
9791 geometry_info.xi=argument_list[3].real_reference;
9792 if (attribute_flag[4] != 0)
9793 geometry_info.psi=argument_list[4].real_reference;
9794 if (attribute_flag[5] != 0)
9795 channel=(ChannelType) argument_list[5].integer_reference;
9796 channel_mask=SetImageChannelMask(image,channel);
9797 image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9798 geometry_info.xi,geometry_info.psi,exception);
9799 if (image != (Image *) NULL)
9800 (void) SetImageChannelMask(image,channel_mask);
9801 break;
9802 }
9803 case 70: /* MotionBlur */
9804 {
9805 if (attribute_flag[0] != 0)
9806 {
9807 flags=ParseGeometry(argument_list[0].string_reference,
9808 &geometry_info);
9809 if ((flags & SigmaValue) == 0)
9810 geometry_info.sigma=1.0;
9811 if ((flags & XiValue) == 0)
9812 geometry_info.xi=1.0;
9813 }
9814 if (attribute_flag[1] != 0)
9815 geometry_info.rho=argument_list[1].real_reference;
9816 if (attribute_flag[2] != 0)
9817 geometry_info.sigma=argument_list[2].real_reference;
9818 if (attribute_flag[3] != 0)
9819 geometry_info.xi=argument_list[3].real_reference;
9820 if (attribute_flag[4] != 0)
9821 channel=(ChannelType) argument_list[4].integer_reference;
9822 channel_mask=SetImageChannelMask(image,channel);
9823 image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9824 geometry_info.xi,exception);
9825 if (image != (Image *) NULL)
9826 (void) SetImageChannelMask(image,channel_mask);
9827 break;
9828 }
9829 case 71: /* OrderedDither */
9830 {
9831 if (attribute_flag[0] == 0)
9832 argument_list[0].string_reference="o8x8";
9833 if (attribute_flag[1] != 0)
9834 channel=(ChannelType) argument_list[1].integer_reference;
9835 channel_mask=SetImageChannelMask(image,channel);
Cristy6b93c072016-02-04 07:45:48 -05009836 (void) OrderedDitherImage(image,argument_list[0].string_reference,
cristy4a3ce0a2013-08-03 20:06:59 +00009837 exception);
9838 (void) SetImageChannelMask(image,channel_mask);
9839 break;
9840 }
9841 case 72: /* Shave */
9842 {
9843 if (attribute_flag[0] != 0)
9844 flags=ParsePageGeometry(image,argument_list[0].string_reference,
9845 &geometry,exception);
9846 if (attribute_flag[1] != 0)
9847 geometry.width=argument_list[1].integer_reference;
9848 if (attribute_flag[2] != 0)
9849 geometry.height=argument_list[2].integer_reference;
9850 image=ShaveImage(image,&geometry,exception);
9851 break;
9852 }
9853 case 73: /* Level */
9854 {
9855 double
9856 black_point,
9857 gamma,
9858 white_point;
9859
9860 black_point=0.0;
9861 white_point=(double) image->columns*image->rows;
9862 gamma=1.0;
9863 if (attribute_flag[0] != 0)
9864 {
9865 flags=ParseGeometry(argument_list[0].string_reference,
9866 &geometry_info);
9867 black_point=geometry_info.rho;
9868 if ((flags & SigmaValue) != 0)
9869 white_point=geometry_info.sigma;
9870 if ((flags & XiValue) != 0)
9871 gamma=geometry_info.xi;
9872 if ((flags & PercentValue) != 0)
9873 {
9874 black_point*=(double) (QuantumRange/100.0);
9875 white_point*=(double) (QuantumRange/100.0);
9876 }
9877 if ((flags & SigmaValue) == 0)
9878 white_point=(double) QuantumRange-black_point;
9879 }
9880 if (attribute_flag[1] != 0)
9881 black_point=argument_list[1].real_reference;
9882 if (attribute_flag[2] != 0)
9883 white_point=argument_list[2].real_reference;
9884 if (attribute_flag[3] != 0)
9885 gamma=argument_list[3].real_reference;
9886 if (attribute_flag[4] != 0)
9887 channel=(ChannelType) argument_list[4].integer_reference;
9888 if (attribute_flag[5] != 0)
9889 {
9890 argument_list[0].real_reference=argument_list[5].real_reference;
9891 attribute_flag[0]=attribute_flag[5];
9892 }
9893 channel_mask=SetImageChannelMask(image,channel);
9894 (void) LevelImage(image,black_point,white_point,gamma,exception);
9895 (void) SetImageChannelMask(image,channel_mask);
9896 break;
9897 }
9898 case 74: /* Clip */
9899 {
9900 if (attribute_flag[0] == 0)
9901 argument_list[0].string_reference="#1";
9902 if (attribute_flag[1] == 0)
9903 argument_list[1].integer_reference=MagickTrue;
9904 (void) ClipImagePath(image,argument_list[0].string_reference,
9905 argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9906 exception);
9907 break;
9908 }
9909 case 75: /* AffineTransform */
9910 {
9911 DrawInfo
9912 *draw_info;
9913
9914 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9915 (DrawInfo *) NULL);
9916 if (attribute_flag[0] != 0)
9917 {
9918 AV
9919 *av;
9920
9921 av=(AV *) argument_list[0].array_reference;
9922 if ((av_len(av) != 3) && (av_len(av) != 5))
9923 {
9924 ThrowPerlException(exception,OptionError,
9925 "affine matrix must have 4 or 6 elements",PackageName);
9926 goto PerlException;
9927 }
9928 draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9929 draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9930 draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9931 draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9932 if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9933 draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9934 {
9935 ThrowPerlException(exception,OptionError,
9936 "affine matrix is singular",PackageName);
9937 goto PerlException;
9938 }
9939 if (av_len(av) == 5)
9940 {
9941 draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9942 draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9943 }
9944 }
9945 for (j=1; j < 6; j++)
9946 {
9947 if (attribute_flag[j] == 0)
9948 continue;
9949 value=argument_list[j].string_reference;
9950 angle=argument_list[j].real_reference;
9951 current=draw_info->affine;
9952 GetAffineMatrix(&affine);
9953 switch (j)
9954 {
9955 case 1:
9956 {
9957 /*
9958 Translate.
9959 */
9960 flags=ParseGeometry(value,&geometry_info);
9961 affine.tx=geometry_info.xi;
9962 affine.ty=geometry_info.psi;
9963 if ((flags & PsiValue) == 0)
9964 affine.ty=affine.tx;
9965 break;
9966 }
9967 case 2:
9968 {
9969 /*
9970 Scale.
9971 */
9972 flags=ParseGeometry(value,&geometry_info);
9973 affine.sx=geometry_info.rho;
9974 affine.sy=geometry_info.sigma;
9975 if ((flags & SigmaValue) == 0)
9976 affine.sy=affine.sx;
9977 break;
9978 }
9979 case 3:
9980 {
9981 /*
9982 Rotate.
9983 */
9984 if (angle == 0.0)
9985 break;
9986 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9987 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9988 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9989 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9990 break;
9991 }
9992 case 4:
9993 {
9994 /*
9995 SkewX.
9996 */
9997 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9998 break;
9999 }
10000 case 5:
10001 {
10002 /*
10003 SkewY.
10004 */
10005 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
10006 break;
10007 }
10008 }
10009 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
10010 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
10011 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
10012 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
10013 draw_info->affine.tx=
10014 current.sx*affine.tx+current.ry*affine.ty+current.tx;
10015 draw_info->affine.ty=
10016 current.rx*affine.tx+current.sy*affine.ty+current.ty;
10017 }
10018 if (attribute_flag[6] != 0)
10019 image->interpolate=(PixelInterpolateMethod)
10020 argument_list[6].integer_reference;
10021 if (attribute_flag[7] != 0)
10022 QueryColorCompliance(argument_list[7].string_reference,
10023 AllCompliance,&image->background_color,exception);
10024 image=AffineTransformImage(image,&draw_info->affine,exception);
10025 draw_info=DestroyDrawInfo(draw_info);
10026 break;
10027 }
10028 case 76: /* Difference */
10029 {
10030 if (attribute_flag[0] == 0)
10031 {
10032 ThrowPerlException(exception,OptionError,
10033 "ReferenceImageRequired",PackageName);
10034 goto PerlException;
10035 }
10036 if (attribute_flag[1] != 0)
10037 image->fuzz=StringToDoubleInterval(
10038 argument_list[1].string_reference,(double) QuantumRange+1.0);
Cristyf2479812015-12-12 12:17:43 -050010039 (void) SetImageColorMetric(image,argument_list[0].image_reference,
cristy4a3ce0a2013-08-03 20:06:59 +000010040 exception);
10041 break;
10042 }
10043 case 77: /* AdaptiveThreshold */
10044 {
10045 if (attribute_flag[0] != 0)
10046 {
10047 flags=ParseGeometry(argument_list[0].string_reference,
10048 &geometry_info);
10049 if ((flags & PercentValue) != 0)
10050 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10051 }
10052 if (attribute_flag[1] != 0)
10053 geometry_info.rho=argument_list[1].integer_reference;
10054 if (attribute_flag[2] != 0)
10055 geometry_info.sigma=argument_list[2].integer_reference;
10056 if (attribute_flag[3] != 0)
10057 geometry_info.xi=argument_list[3].integer_reference;;
10058 image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
10059 (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
10060 break;
10061 }
10062 case 78: /* Resample */
10063 {
10064 size_t
10065 height,
10066 width;
10067
10068 if (attribute_flag[0] != 0)
10069 {
10070 flags=ParseGeometry(argument_list[0].string_reference,
10071 &geometry_info);
10072 if ((flags & SigmaValue) == 0)
10073 geometry_info.sigma=geometry_info.rho;
10074 }
10075 if (attribute_flag[1] != 0)
10076 geometry_info.rho=argument_list[1].real_reference;
10077 if (attribute_flag[2] != 0)
10078 geometry_info.sigma=argument_list[2].real_reference;
10079 if (attribute_flag[3] == 0)
10080 argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10081 if (attribute_flag[4] == 0)
10082 SetImageArtifact(image,"filter:support",
10083 argument_list[4].string_reference);
10084 width=(size_t) (geometry_info.rho*image->columns/
10085 (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10086 height=(size_t) (geometry_info.sigma*image->rows/
10087 (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
Cristy8645e042016-02-03 16:35:29 -050010088 image=ResizeImage(image,width,height,(FilterType)
cristy4a3ce0a2013-08-03 20:06:59 +000010089 argument_list[3].integer_reference,exception);
10090 if (image != (Image *) NULL)
10091 {
10092 image->resolution.x=geometry_info.rho;
10093 image->resolution.y=geometry_info.sigma;
10094 }
10095 break;
10096 }
10097 case 79: /* Describe */
10098 {
10099 if (attribute_flag[0] == 0)
10100 argument_list[0].file_reference=(FILE *) NULL;
10101 if (attribute_flag[1] != 0)
10102 (void) SetImageArtifact(image,"identify:features",
10103 argument_list[1].string_reference);
10104 (void) IdentifyImage(image,argument_list[0].file_reference,
10105 MagickTrue,exception);
10106 break;
10107 }
10108 case 80: /* BlackThreshold */
10109 {
10110 if (attribute_flag[0] == 0)
10111 argument_list[0].string_reference="50%";
10112 if (attribute_flag[2] != 0)
10113 channel=(ChannelType) argument_list[2].integer_reference;
10114 channel_mask=SetImageChannelMask(image,channel);
10115 BlackThresholdImage(image,argument_list[0].string_reference,
10116 exception);
10117 (void) SetImageChannelMask(image,channel_mask);
10118 break;
10119 }
10120 case 81: /* WhiteThreshold */
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 WhiteThresholdImage(image,argument_list[0].string_reference,
10128 exception);
10129 (void) SetImageChannelMask(image,channel_mask);
10130 break;
10131 }
cristy60c73c02014-03-25 12:09:58 +000010132 case 82: /* RotationalBlur */
cristy4a3ce0a2013-08-03 20:06:59 +000010133 {
10134 if (attribute_flag[0] != 0)
10135 {
10136 flags=ParseGeometry(argument_list[0].string_reference,
10137 &geometry_info);
10138 }
10139 if (attribute_flag[1] != 0)
10140 geometry_info.rho=argument_list[1].real_reference;
10141 if (attribute_flag[2] != 0)
10142 channel=(ChannelType) argument_list[2].integer_reference;
10143 channel_mask=SetImageChannelMask(image,channel);
cristy49d4d222014-03-16 00:37:58 +000010144 image=RotationalBlurImage(image,geometry_info.rho,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010145 if (image != (Image *) NULL)
10146 (void) SetImageChannelMask(image,channel_mask);
10147 break;
10148 }
10149 case 83: /* Thumbnail */
10150 {
10151 if (attribute_flag[0] != 0)
10152 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10153 &geometry,exception);
10154 if (attribute_flag[1] != 0)
10155 geometry.width=argument_list[1].integer_reference;
10156 if (attribute_flag[2] != 0)
10157 geometry.height=argument_list[2].integer_reference;
10158 image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10159 break;
10160 }
10161 case 84: /* Strip */
10162 {
10163 (void) StripImage(image,exception);
10164 break;
10165 }
10166 case 85: /* Tint */
10167 {
10168 PixelInfo
10169 tint;
10170
10171 GetPixelInfo(image,&tint);
10172 if (attribute_flag[0] != 0)
10173 (void) QueryColorCompliance(argument_list[0].string_reference,
10174 AllCompliance,&tint,exception);
10175 if (attribute_flag[1] == 0)
10176 argument_list[1].string_reference="100";
10177 image=TintImage(image,argument_list[1].string_reference,&tint,
10178 exception);
10179 break;
10180 }
10181 case 86: /* Channel */
10182 {
10183 if (attribute_flag[0] != 0)
10184 channel=(ChannelType) argument_list[0].integer_reference;
10185 image=SeparateImage(image,channel,exception);
10186 break;
10187 }
10188 case 87: /* Splice */
10189 {
cristy260bd762014-08-15 12:46:34 +000010190 if (attribute_flag[7] != 0)
10191 image->gravity=(GravityType) argument_list[7].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010192 if (attribute_flag[0] != 0)
10193 flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10194 &geometry,exception);
10195 if (attribute_flag[1] != 0)
10196 geometry.width=argument_list[1].integer_reference;
10197 if (attribute_flag[2] != 0)
10198 geometry.height=argument_list[2].integer_reference;
10199 if (attribute_flag[3] != 0)
10200 geometry.x=argument_list[3].integer_reference;
10201 if (attribute_flag[4] != 0)
10202 geometry.y=argument_list[4].integer_reference;
10203 if (attribute_flag[5] != 0)
10204 image->fuzz=StringToDoubleInterval(
10205 argument_list[5].string_reference,(double) QuantumRange+1.0);
10206 if (attribute_flag[6] != 0)
10207 (void) QueryColorCompliance(argument_list[6].string_reference,
10208 AllCompliance,&image->background_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010209 image=SpliceImage(image,&geometry,exception);
10210 break;
10211 }
10212 case 88: /* Posterize */
10213 {
10214 if (attribute_flag[0] == 0)
10215 argument_list[0].integer_reference=3;
10216 if (attribute_flag[1] == 0)
10217 argument_list[1].integer_reference=0;
10218 (void) PosterizeImage(image,argument_list[0].integer_reference,
10219 argument_list[1].integer_reference ? RiemersmaDitherMethod :
10220 NoDitherMethod,exception);
10221 break;
10222 }
10223 case 89: /* Shadow */
10224 {
10225 if (attribute_flag[0] != 0)
10226 {
10227 flags=ParseGeometry(argument_list[0].string_reference,
10228 &geometry_info);
10229 if ((flags & SigmaValue) == 0)
10230 geometry_info.sigma=1.0;
10231 if ((flags & XiValue) == 0)
10232 geometry_info.xi=4.0;
10233 if ((flags & PsiValue) == 0)
10234 geometry_info.psi=4.0;
10235 }
10236 if (attribute_flag[1] != 0)
10237 geometry_info.rho=argument_list[1].real_reference;
10238 if (attribute_flag[2] != 0)
10239 geometry_info.sigma=argument_list[2].real_reference;
10240 if (attribute_flag[3] != 0)
10241 geometry_info.xi=argument_list[3].integer_reference;
10242 if (attribute_flag[4] != 0)
10243 geometry_info.psi=argument_list[4].integer_reference;
10244 image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10245 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10246 ceil(geometry_info.psi-0.5),exception);
10247 break;
10248 }
10249 case 90: /* Identify */
10250 {
10251 if (attribute_flag[0] == 0)
10252 argument_list[0].file_reference=(FILE *) NULL;
10253 if (attribute_flag[1] != 0)
10254 (void) SetImageArtifact(image,"identify:features",
10255 argument_list[1].string_reference);
10256 if ((attribute_flag[2] != 0) &&
10257 (argument_list[2].integer_reference != 0))
10258 (void) SetImageArtifact(image,"identify:unique","true");
10259 (void) IdentifyImage(image,argument_list[0].file_reference,
10260 MagickTrue,exception);
10261 break;
10262 }
10263 case 91: /* SepiaTone */
10264 {
10265 if (attribute_flag[0] == 0)
10266 argument_list[0].real_reference=80.0*QuantumRange/100.0;
10267 image=SepiaToneImage(image,argument_list[0].real_reference,
10268 exception);
10269 break;
10270 }
10271 case 92: /* SigmoidalContrast */
10272 {
10273 MagickBooleanType
10274 sharpen;
10275
10276 if (attribute_flag[0] != 0)
10277 {
10278 flags=ParseGeometry(argument_list[0].string_reference,
10279 &geometry_info);
10280 if ((flags & SigmaValue) == 0)
10281 geometry_info.sigma=QuantumRange/2.0;
10282 if ((flags & PercentValue) != 0)
10283 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10284 }
10285 if (attribute_flag[1] != 0)
10286 geometry_info.rho=argument_list[1].real_reference;
10287 if (attribute_flag[2] != 0)
10288 geometry_info.sigma=argument_list[2].real_reference;
10289 if (attribute_flag[3] != 0)
10290 channel=(ChannelType) argument_list[3].integer_reference;
10291 sharpen=MagickTrue;
10292 if (attribute_flag[4] != 0)
10293 sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10294 MagickFalse;
10295 channel_mask=SetImageChannelMask(image,channel);
10296 (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10297 geometry_info.sigma,exception);
10298 (void) SetImageChannelMask(image,channel_mask);
10299 break;
10300 }
10301 case 93: /* Extent */
10302 {
10303 if (attribute_flag[7] != 0)
10304 image->gravity=(GravityType) argument_list[7].integer_reference;
10305 if (attribute_flag[0] != 0)
10306 {
10307 int
10308 flags;
10309
10310 flags=ParseGravityGeometry(image,
10311 argument_list[0].string_reference,&geometry,exception);
10312 (void) flags;
10313 if (geometry.width == 0)
10314 geometry.width=image->columns;
10315 if (geometry.height == 0)
10316 geometry.height=image->rows;
10317 }
10318 if (attribute_flag[1] != 0)
10319 geometry.width=argument_list[1].integer_reference;
10320 if (attribute_flag[2] != 0)
10321 geometry.height=argument_list[2].integer_reference;
10322 if (attribute_flag[3] != 0)
10323 geometry.x=argument_list[3].integer_reference;
10324 if (attribute_flag[4] != 0)
10325 geometry.y=argument_list[4].integer_reference;
10326 if (attribute_flag[5] != 0)
10327 image->fuzz=StringToDoubleInterval(
10328 argument_list[5].string_reference,(double) QuantumRange+1.0);
10329 if (attribute_flag[6] != 0)
10330 (void) QueryColorCompliance(argument_list[6].string_reference,
10331 AllCompliance,&image->background_color,exception);
10332 image=ExtentImage(image,&geometry,exception);
10333 break;
10334 }
10335 case 94: /* Vignette */
10336 {
10337 if (attribute_flag[0] != 0)
10338 {
10339 flags=ParseGeometry(argument_list[0].string_reference,
10340 &geometry_info);
10341 if ((flags & SigmaValue) == 0)
10342 geometry_info.sigma=1.0;
10343 if ((flags & XiValue) == 0)
10344 geometry_info.xi=0.1*image->columns;
10345 if ((flags & PsiValue) == 0)
10346 geometry_info.psi=0.1*image->rows;
10347 }
10348 if (attribute_flag[1] != 0)
10349 geometry_info.rho=argument_list[1].real_reference;
10350 if (attribute_flag[2] != 0)
10351 geometry_info.sigma=argument_list[2].real_reference;
10352 if (attribute_flag[3] != 0)
10353 geometry_info.xi=argument_list[3].integer_reference;
10354 if (attribute_flag[4] != 0)
10355 geometry_info.psi=argument_list[4].integer_reference;
10356 if (attribute_flag[5] != 0)
10357 (void) QueryColorCompliance(argument_list[5].string_reference,
10358 AllCompliance,&image->background_color,exception);
10359 image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10360 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10361 ceil(geometry_info.psi-0.5),exception);
10362 break;
10363 }
10364 case 95: /* ContrastStretch */
10365 {
10366 double
10367 black_point,
10368 white_point;
10369
10370 black_point=0.0;
10371 white_point=(double) image->columns*image->rows;
10372 if (attribute_flag[0] != 0)
10373 {
10374 flags=ParseGeometry(argument_list[0].string_reference,
10375 &geometry_info);
10376 black_point=geometry_info.rho;
10377 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10378 black_point;
10379 if ((flags & PercentValue) != 0)
10380 {
10381 black_point*=(double) image->columns*image->rows/100.0;
10382 white_point*=(double) image->columns*image->rows/100.0;
10383 }
10384 white_point=(double) image->columns*image->rows-
10385 white_point;
10386 }
10387 if (attribute_flag[1] != 0)
10388 black_point=argument_list[1].real_reference;
10389 if (attribute_flag[2] != 0)
10390 white_point=argument_list[2].real_reference;
10391 if (attribute_flag[4] != 0)
10392 channel=(ChannelType) argument_list[4].integer_reference;
10393 channel_mask=SetImageChannelMask(image,channel);
10394 (void) ContrastStretchImage(image,black_point,white_point,exception);
10395 (void) SetImageChannelMask(image,channel_mask);
10396 break;
10397 }
10398 case 96: /* Sans0 */
10399 {
10400 break;
10401 }
10402 case 97: /* Sans1 */
10403 {
10404 break;
10405 }
10406 case 98: /* AdaptiveSharpen */
10407 {
10408 if (attribute_flag[0] != 0)
10409 {
10410 flags=ParseGeometry(argument_list[0].string_reference,
10411 &geometry_info);
10412 if ((flags & SigmaValue) == 0)
10413 geometry_info.sigma=1.0;
10414 if ((flags & XiValue) == 0)
10415 geometry_info.xi=0.0;
10416 }
10417 if (attribute_flag[1] != 0)
10418 geometry_info.rho=argument_list[1].real_reference;
10419 if (attribute_flag[2] != 0)
10420 geometry_info.sigma=argument_list[2].real_reference;
10421 if (attribute_flag[3] != 0)
10422 geometry_info.xi=argument_list[3].real_reference;
10423 if (attribute_flag[4] != 0)
10424 channel=(ChannelType) argument_list[4].integer_reference;
10425 channel_mask=SetImageChannelMask(image,channel);
10426 image=AdaptiveSharpenImage(image,geometry_info.rho,
10427 geometry_info.sigma,exception);
10428 if (image != (Image *) NULL)
10429 (void) SetImageChannelMask(image,channel_mask);
10430 break;
10431 }
10432 case 99: /* Transpose */
10433 {
10434 image=TransposeImage(image,exception);
10435 break;
10436 }
10437 case 100: /* Tranverse */
10438 {
10439 image=TransverseImage(image,exception);
10440 break;
10441 }
10442 case 101: /* AutoOrient */
10443 {
10444 image=AutoOrientImage(image,image->orientation,exception);
10445 break;
10446 }
10447 case 102: /* AdaptiveBlur */
10448 {
10449 if (attribute_flag[0] != 0)
10450 {
10451 flags=ParseGeometry(argument_list[0].string_reference,
10452 &geometry_info);
10453 if ((flags & SigmaValue) == 0)
10454 geometry_info.sigma=1.0;
10455 if ((flags & XiValue) == 0)
10456 geometry_info.xi=0.0;
10457 }
10458 if (attribute_flag[1] != 0)
10459 geometry_info.rho=argument_list[1].real_reference;
10460 if (attribute_flag[2] != 0)
10461 geometry_info.sigma=argument_list[2].real_reference;
10462 if (attribute_flag[3] != 0)
10463 channel=(ChannelType) argument_list[3].integer_reference;
10464 channel_mask=SetImageChannelMask(image,channel);
10465 image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10466 exception);
10467 if (image != (Image *) NULL)
10468 (void) SetImageChannelMask(image,channel_mask);
10469 break;
10470 }
10471 case 103: /* Sketch */
10472 {
10473 if (attribute_flag[0] != 0)
10474 {
10475 flags=ParseGeometry(argument_list[0].string_reference,
10476 &geometry_info);
10477 if ((flags & SigmaValue) == 0)
10478 geometry_info.sigma=1.0;
10479 if ((flags & XiValue) == 0)
10480 geometry_info.xi=1.0;
10481 }
10482 if (attribute_flag[1] != 0)
10483 geometry_info.rho=argument_list[1].real_reference;
10484 if (attribute_flag[2] != 0)
10485 geometry_info.sigma=argument_list[2].real_reference;
10486 if (attribute_flag[3] != 0)
10487 geometry_info.xi=argument_list[3].real_reference;
10488 image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10489 geometry_info.xi,exception);
10490 break;
10491 }
10492 case 104: /* UniqueColors */
10493 {
10494 image=UniqueImageColors(image,exception);
10495 break;
10496 }
10497 case 105: /* AdaptiveResize */
10498 {
10499 if (attribute_flag[0] != 0)
10500 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10501 &geometry,exception);
10502 if (attribute_flag[1] != 0)
10503 geometry.width=argument_list[1].integer_reference;
10504 if (attribute_flag[2] != 0)
10505 geometry.height=argument_list[2].integer_reference;
10506 if (attribute_flag[3] != 0)
Cristy8645e042016-02-03 16:35:29 -050010507 image->filter=(FilterType) argument_list[4].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010508 if (attribute_flag[4] != 0)
10509 SetImageArtifact(image,"filter:support",
10510 argument_list[4].string_reference);
10511 image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10512 exception);
10513 break;
10514 }
10515 case 106: /* ClipMask */
10516 {
10517 Image
10518 *mask_image;
10519
10520 if (attribute_flag[0] == 0)
10521 {
10522 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10523 PackageName);
10524 goto PerlException;
10525 }
10526 mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10527 exception);
cristy1f7ffb72015-07-29 11:07:03 +000010528 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010529 mask_image=DestroyImage(mask_image);
10530 break;
10531 }
10532 case 107: /* LinearStretch */
10533 {
10534 double
10535 black_point,
10536 white_point;
10537
10538 black_point=0.0;
10539 white_point=(double) image->columns*image->rows;
10540 if (attribute_flag[0] != 0)
10541 {
10542 flags=ParseGeometry(argument_list[0].string_reference,
10543 &geometry_info);
10544 if ((flags & SigmaValue) != 0)
10545 white_point=geometry_info.sigma;
10546 if ((flags & PercentValue) != 0)
10547 {
10548 black_point*=(double) image->columns*image->rows/100.0;
10549 white_point*=(double) image->columns*image->rows/100.0;
10550 }
10551 if ((flags & SigmaValue) == 0)
10552 white_point=(double) image->columns*image->rows-black_point;
10553 }
10554 if (attribute_flag[1] != 0)
10555 black_point=argument_list[1].real_reference;
10556 if (attribute_flag[2] != 0)
10557 white_point=argument_list[2].real_reference;
10558 (void) LinearStretchImage(image,black_point,white_point,exception);
10559 break;
10560 }
10561 case 108: /* ColorMatrix */
10562 {
10563 AV
10564 *av;
10565
10566 double
10567 *color_matrix;
10568
10569 KernelInfo
10570 *kernel_info;
10571
10572 size_t
10573 order;
10574
10575 if (attribute_flag[0] == 0)
10576 break;
10577 av=(AV *) argument_list[0].array_reference;
10578 order=(size_t) sqrt(av_len(av)+1);
10579 color_matrix=(double *) AcquireQuantumMemory(order,order*
10580 sizeof(*color_matrix));
10581 if (color_matrix == (double *) NULL)
10582 {
10583 ThrowPerlException(exception,ResourceLimitFatalError,
10584 "MemoryAllocationFailed",PackageName);
10585 goto PerlException;
10586 }
10587 for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10588 color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10589 for ( ; j < (ssize_t) (order*order); j++)
10590 color_matrix[j]=0.0;
cristy2c57b742014-10-31 00:40:34 +000010591 kernel_info=AcquireKernelInfo((const char *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010592 if (kernel_info == (KernelInfo *) NULL)
10593 break;
10594 kernel_info->width=order;
10595 kernel_info->height=order;
10596 kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10597 order*sizeof(*kernel_info->values));
10598 if (kernel_info->values != (MagickRealType *) NULL)
10599 {
10600 for (i=0; i < (ssize_t) (order*order); i++)
10601 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10602 image=ColorMatrixImage(image,kernel_info,exception);
10603 }
10604 kernel_info=DestroyKernelInfo(kernel_info);
10605 color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10606 break;
10607 }
10608 case 109: /* Mask */
10609 {
10610 Image
10611 *mask_image;
10612
10613 if (attribute_flag[0] == 0)
10614 {
10615 ThrowPerlException(exception,OptionError,"MaskImageRequired",
10616 PackageName);
10617 goto PerlException;
10618 }
10619 mask_image=CloneImage(argument_list[0].image_reference,0,0,
10620 MagickTrue,exception);
cristy1f7ffb72015-07-29 11:07:03 +000010621 (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000010622 mask_image=DestroyImage(mask_image);
10623 break;
10624 }
10625 case 110: /* Polaroid */
10626 {
10627 char
10628 *caption;
10629
10630 DrawInfo
10631 *draw_info;
10632
10633 double
10634 angle;
10635
10636 PixelInterpolateMethod
10637 method;
10638
10639 draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10640 (DrawInfo *) NULL);
10641 caption=(char *) NULL;
10642 if (attribute_flag[0] != 0)
10643 caption=InterpretImageProperties(info ? info->image_info :
10644 (ImageInfo *) NULL,image,argument_list[0].string_reference,
10645 exception);
10646 angle=0.0;
10647 if (attribute_flag[1] != 0)
10648 angle=argument_list[1].real_reference;
10649 if (attribute_flag[2] != 0)
10650 (void) CloneString(&draw_info->font,
10651 argument_list[2].string_reference);
10652 if (attribute_flag[3] != 0)
10653 (void) QueryColorCompliance(argument_list[3].string_reference,
10654 AllCompliance,&draw_info->stroke,exception);
10655 if (attribute_flag[4] != 0)
10656 (void) QueryColorCompliance(argument_list[4].string_reference,
10657 AllCompliance,&draw_info->fill,exception);
10658 if (attribute_flag[5] != 0)
10659 draw_info->stroke_width=argument_list[5].real_reference;
10660 if (attribute_flag[6] != 0)
10661 draw_info->pointsize=argument_list[6].real_reference;
10662 if (attribute_flag[7] != 0)
10663 draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10664 if (attribute_flag[8] != 0)
10665 (void) QueryColorCompliance(argument_list[8].string_reference,
10666 AllCompliance,&image->background_color,exception);
10667 method=UndefinedInterpolatePixel;
10668 if (attribute_flag[9] != 0)
10669 method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10670 image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10671 draw_info=DestroyDrawInfo(draw_info);
10672 if (caption != (char *) NULL)
10673 caption=DestroyString(caption);
10674 break;
10675 }
10676 case 111: /* FloodfillPaint */
10677 {
10678 DrawInfo
10679 *draw_info;
10680
10681 MagickBooleanType
10682 invert;
10683
10684 PixelInfo
10685 target;
10686
10687 draw_info=CloneDrawInfo(info ? info->image_info :
10688 (ImageInfo *) NULL,(DrawInfo *) NULL);
10689 if (attribute_flag[0] != 0)
10690 flags=ParsePageGeometry(image,argument_list[0].string_reference,
10691 &geometry,exception);
10692 if (attribute_flag[1] != 0)
10693 geometry.x=argument_list[1].integer_reference;
10694 if (attribute_flag[2] != 0)
10695 geometry.y=argument_list[2].integer_reference;
10696 if (attribute_flag[3] != 0)
10697 (void) QueryColorCompliance(argument_list[3].string_reference,
10698 AllCompliance,&draw_info->fill,exception);
10699 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10700 geometry.x,geometry.y,&target,exception);
10701 if (attribute_flag[4] != 0)
10702 QueryColorCompliance(argument_list[4].string_reference,
10703 AllCompliance,&target,exception);
10704 if (attribute_flag[5] != 0)
10705 image->fuzz=StringToDoubleInterval(
10706 argument_list[5].string_reference,(double) QuantumRange+1.0);
10707 if (attribute_flag[6] != 0)
10708 channel=(ChannelType) argument_list[6].integer_reference;
10709 invert=MagickFalse;
10710 if (attribute_flag[7] != 0)
10711 invert=(MagickBooleanType) argument_list[7].integer_reference;
10712 channel_mask=SetImageChannelMask(image,channel);
10713 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10714 geometry.y,invert,exception);
10715 (void) SetImageChannelMask(image,channel_mask);
10716 draw_info=DestroyDrawInfo(draw_info);
10717 break;
10718 }
10719 case 112: /* Distort */
10720 {
10721 AV
10722 *av;
10723
10724 double
10725 *coordinates;
10726
Cristy8645e042016-02-03 16:35:29 -050010727 DistortMethod
cristy4a3ce0a2013-08-03 20:06:59 +000010728 method;
10729
10730 size_t
10731 number_coordinates;
10732
10733 VirtualPixelMethod
10734 virtual_pixel;
10735
10736 if (attribute_flag[0] == 0)
10737 break;
10738 method=UndefinedDistortion;
10739 if (attribute_flag[1] != 0)
Cristy8645e042016-02-03 16:35:29 -050010740 method=(DistortMethod) argument_list[1].integer_reference;
cristy4a3ce0a2013-08-03 20:06:59 +000010741 av=(AV *) argument_list[0].array_reference;
10742 number_coordinates=(size_t) av_len(av)+1;
10743 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10744 sizeof(*coordinates));
10745 if (coordinates == (double *) NULL)
10746 {
10747 ThrowPerlException(exception,ResourceLimitFatalError,
10748 "MemoryAllocationFailed",PackageName);
10749 goto PerlException;
10750 }
10751 for (j=0; j < (ssize_t) number_coordinates; j++)
10752 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10753 virtual_pixel=UndefinedVirtualPixelMethod;
10754 if (attribute_flag[2] != 0)
10755 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10756 argument_list[2].integer_reference,exception);
10757 image=DistortImage(image,method,number_coordinates,coordinates,
10758 argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10759 exception);
10760 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10761 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10762 exception);
10763 coordinates=(double *) RelinquishMagickMemory(coordinates);
10764 break;
10765 }
10766 case 113: /* Clut */
10767 {
10768 PixelInterpolateMethod
10769 method;
10770
10771 if (attribute_flag[0] == 0)
10772 {
10773 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10774 PackageName);
10775 goto PerlException;
10776 }
10777 method=UndefinedInterpolatePixel;
10778 if (attribute_flag[1] != 0)
10779 method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10780 if (attribute_flag[2] != 0)
10781 channel=(ChannelType) argument_list[2].integer_reference;
10782 channel_mask=SetImageChannelMask(image,channel);
10783 (void) ClutImage(image,argument_list[0].image_reference,method,
10784 exception);
10785 (void) SetImageChannelMask(image,channel_mask);
10786 break;
10787 }
10788 case 114: /* LiquidRescale */
10789 {
10790 if (attribute_flag[0] != 0)
10791 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10792 &geometry,exception);
10793 if (attribute_flag[1] != 0)
10794 geometry.width=argument_list[1].integer_reference;
10795 if (attribute_flag[2] != 0)
10796 geometry.height=argument_list[2].integer_reference;
10797 if (attribute_flag[3] == 0)
10798 argument_list[3].real_reference=1.0;
10799 if (attribute_flag[4] == 0)
10800 argument_list[4].real_reference=0.0;
10801 image=LiquidRescaleImage(image,geometry.width,geometry.height,
10802 argument_list[3].real_reference,argument_list[4].real_reference,
10803 exception);
10804 break;
10805 }
10806 case 115: /* EncipherImage */
10807 {
10808 (void) EncipherImage(image,argument_list[0].string_reference,
10809 exception);
10810 break;
10811 }
10812 case 116: /* DecipherImage */
10813 {
10814 (void) DecipherImage(image,argument_list[0].string_reference,
10815 exception);
10816 break;
10817 }
10818 case 117: /* Deskew */
10819 {
10820 geometry_info.rho=QuantumRange/2.0;
10821 if (attribute_flag[0] != 0)
10822 flags=ParseGeometry(argument_list[0].string_reference,
10823 &geometry_info);
10824 if (attribute_flag[1] != 0)
10825 geometry_info.rho=StringToDoubleInterval(
10826 argument_list[1].string_reference,(double) QuantumRange+1.0);
10827 image=DeskewImage(image,geometry_info.rho,exception);
10828 break;
10829 }
10830 case 118: /* Remap */
10831 {
10832 QuantizeInfo
10833 *quantize_info;
10834
10835 if (attribute_flag[0] == 0)
10836 {
10837 ThrowPerlException(exception,OptionError,"RemapImageRequired",
10838 PackageName);
10839 goto PerlException;
10840 }
10841 quantize_info=AcquireQuantizeInfo(info->image_info);
10842 if (attribute_flag[1] != 0)
10843 quantize_info->dither_method=(DitherMethod)
10844 argument_list[1].integer_reference;
10845 (void) RemapImages(quantize_info,image,
10846 argument_list[0].image_reference,exception);
10847 quantize_info=DestroyQuantizeInfo(quantize_info);
10848 break;
10849 }
10850 case 119: /* SparseColor */
10851 {
10852 AV
10853 *av;
10854
10855 double
10856 *coordinates;
10857
10858 SparseColorMethod
10859 method;
10860
10861 size_t
10862 number_coordinates;
10863
10864 VirtualPixelMethod
10865 virtual_pixel;
10866
10867 if (attribute_flag[0] == 0)
10868 break;
10869 method=UndefinedColorInterpolate;
10870 if (attribute_flag[1] != 0)
10871 method=(SparseColorMethod) argument_list[1].integer_reference;
10872 av=(AV *) argument_list[0].array_reference;
10873 number_coordinates=(size_t) av_len(av)+1;
10874 coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10875 sizeof(*coordinates));
10876 if (coordinates == (double *) NULL)
10877 {
10878 ThrowPerlException(exception,ResourceLimitFatalError,
10879 "MemoryAllocationFailed",PackageName);
10880 goto PerlException;
10881 }
10882 for (j=0; j < (ssize_t) number_coordinates; j++)
10883 coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10884 virtual_pixel=UndefinedVirtualPixelMethod;
10885 if (attribute_flag[2] != 0)
10886 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10887 argument_list[2].integer_reference,exception);
10888 if (attribute_flag[3] != 0)
10889 channel=(ChannelType) argument_list[3].integer_reference;
10890 channel_mask=SetImageChannelMask(image,channel);
10891 image=SparseColorImage(image,method,number_coordinates,coordinates,
10892 exception);
10893 if (image != (Image *) NULL)
10894 (void) SetImageChannelMask(image,channel_mask);
10895 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10896 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10897 exception);
10898 coordinates=(double *) RelinquishMagickMemory(coordinates);
10899 break;
10900 }
10901 case 120: /* Function */
10902 {
10903 AV
10904 *av;
10905
10906 double
10907 *parameters;
10908
10909 MagickFunction
10910 function;
10911
10912 size_t
10913 number_parameters;
10914
10915 VirtualPixelMethod
10916 virtual_pixel;
10917
10918 if (attribute_flag[0] == 0)
10919 break;
10920 function=UndefinedFunction;
10921 if (attribute_flag[1] != 0)
10922 function=(MagickFunction) argument_list[1].integer_reference;
10923 av=(AV *) argument_list[0].array_reference;
10924 number_parameters=(size_t) av_len(av)+1;
10925 parameters=(double *) AcquireQuantumMemory(number_parameters,
10926 sizeof(*parameters));
10927 if (parameters == (double *) NULL)
10928 {
10929 ThrowPerlException(exception,ResourceLimitFatalError,
10930 "MemoryAllocationFailed",PackageName);
10931 goto PerlException;
10932 }
10933 for (j=0; j < (ssize_t) number_parameters; j++)
10934 parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10935 virtual_pixel=UndefinedVirtualPixelMethod;
10936 if (attribute_flag[2] != 0)
10937 virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10938 argument_list[2].integer_reference,exception);
10939 (void) FunctionImage(image,function,number_parameters,parameters,
10940 exception);
10941 if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10942 virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10943 exception);
10944 parameters=(double *) RelinquishMagickMemory(parameters);
10945 break;
10946 }
10947 case 121: /* SelectiveBlur */
10948 {
10949 if (attribute_flag[0] != 0)
10950 {
10951 flags=ParseGeometry(argument_list[0].string_reference,
10952 &geometry_info);
10953 if ((flags & SigmaValue) == 0)
10954 geometry_info.sigma=1.0;
10955 if ((flags & PercentValue) != 0)
10956 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10957 }
10958 if (attribute_flag[1] != 0)
10959 geometry_info.rho=argument_list[1].real_reference;
10960 if (attribute_flag[2] != 0)
10961 geometry_info.sigma=argument_list[2].real_reference;
10962 if (attribute_flag[3] != 0)
10963 geometry_info.xi=argument_list[3].integer_reference;;
10964 if (attribute_flag[5] != 0)
10965 channel=(ChannelType) argument_list[5].integer_reference;
10966 channel_mask=SetImageChannelMask(image,channel);
10967 image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10968 geometry_info.xi,exception);
10969 if (image != (Image *) NULL)
10970 (void) SetImageChannelMask(image,channel_mask);
10971 break;
10972 }
10973 case 122: /* HaldClut */
10974 {
10975 if (attribute_flag[0] == 0)
10976 {
10977 ThrowPerlException(exception,OptionError,"ClutImageRequired",
10978 PackageName);
10979 goto PerlException;
10980 }
10981 if (attribute_flag[1] != 0)
10982 channel=(ChannelType) argument_list[1].integer_reference;
10983 channel_mask=SetImageChannelMask(image,channel);
10984 (void) HaldClutImage(image,argument_list[0].image_reference,
10985 exception);
10986 (void) SetImageChannelMask(image,channel_mask);
10987 break;
10988 }
10989 case 123: /* BlueShift */
10990 {
10991 if (attribute_flag[0] != 0)
10992 (void) ParseGeometry(argument_list[0].string_reference,
10993 &geometry_info);
10994 image=BlueShiftImage(image,geometry_info.rho,exception);
10995 break;
10996 }
10997 case 124: /* ForwardFourierTransformImage */
10998 {
10999 image=ForwardFourierTransformImage(image,
11000 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11001 exception);
11002 break;
11003 }
11004 case 125: /* InverseFourierTransformImage */
11005 {
11006 image=InverseFourierTransformImage(image,image->next,
11007 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11008 exception);
11009 break;
11010 }
11011 case 126: /* ColorDecisionList */
11012 {
11013 if (attribute_flag[0] == 0)
11014 argument_list[0].string_reference=(char *) NULL;
11015 (void) ColorDecisionListImage(image,
11016 argument_list[0].string_reference,exception);
11017 break;
11018 }
11019 case 127: /* AutoGamma */
11020 {
11021 if (attribute_flag[0] != 0)
11022 channel=(ChannelType) argument_list[0].integer_reference;
11023 channel_mask=SetImageChannelMask(image,channel);
11024 (void) AutoGammaImage(image,exception);
11025 (void) SetImageChannelMask(image,channel_mask);
11026 break;
11027 }
11028 case 128: /* AutoLevel */
11029 {
11030 if (attribute_flag[0] != 0)
11031 channel=(ChannelType) argument_list[0].integer_reference;
11032 channel_mask=SetImageChannelMask(image,channel);
11033 (void) AutoLevelImage(image,exception);
11034 (void) SetImageChannelMask(image,channel_mask);
11035 break;
11036 }
11037 case 129: /* LevelColors */
11038 {
11039 PixelInfo
11040 black_point,
11041 white_point;
11042
11043 (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
11044 exception);
11045 (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
11046 exception);
11047 if (attribute_flag[1] != 0)
11048 (void) QueryColorCompliance(
11049 argument_list[1].string_reference,AllCompliance,&black_point,
11050 exception);
11051 if (attribute_flag[2] != 0)
11052 (void) QueryColorCompliance(
11053 argument_list[2].string_reference,AllCompliance,&white_point,
11054 exception);
11055 if (attribute_flag[3] != 0)
11056 channel=(ChannelType) argument_list[3].integer_reference;
11057 channel_mask=SetImageChannelMask(image,channel);
11058 (void) LevelImageColors(image,&black_point,&white_point,
11059 argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11060 exception);
11061 (void) SetImageChannelMask(image,channel_mask);
11062 break;
11063 }
11064 case 130: /* Clamp */
11065 {
11066 if (attribute_flag[0] != 0)
11067 channel=(ChannelType) argument_list[0].integer_reference;
11068 channel_mask=SetImageChannelMask(image,channel);
11069 (void) ClampImage(image,exception);
11070 (void) SetImageChannelMask(image,channel_mask);
11071 break;
11072 }
11073 case 131: /* BrightnessContrast */
11074 {
11075 double
11076 brightness,
11077 contrast;
11078
11079 brightness=0.0;
11080 contrast=0.0;
11081 if (attribute_flag[0] != 0)
11082 {
11083 flags=ParseGeometry(argument_list[0].string_reference,
11084 &geometry_info);
11085 brightness=geometry_info.rho;
11086 if ((flags & SigmaValue) == 0)
11087 contrast=geometry_info.sigma;
11088 }
11089 if (attribute_flag[1] != 0)
11090 brightness=argument_list[1].real_reference;
11091 if (attribute_flag[2] != 0)
11092 contrast=argument_list[2].real_reference;
11093 if (attribute_flag[4] != 0)
11094 channel=(ChannelType) argument_list[4].integer_reference;
11095 channel_mask=SetImageChannelMask(image,channel);
11096 (void) BrightnessContrastImage(image,brightness,contrast,exception);
11097 (void) SetImageChannelMask(image,channel_mask);
11098 break;
11099 }
11100 case 132: /* Morphology */
11101 {
11102 KernelInfo
11103 *kernel;
11104
11105 MorphologyMethod
11106 method;
11107
11108 ssize_t
11109 iterations;
11110
11111 if (attribute_flag[0] == 0)
11112 break;
cristy2c57b742014-10-31 00:40:34 +000011113 kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011114 if (kernel == (KernelInfo *) NULL)
11115 break;
11116 if (attribute_flag[1] != 0)
11117 channel=(ChannelType) argument_list[1].integer_reference;
11118 method=UndefinedMorphology;
11119 if (attribute_flag[2] != 0)
11120 method=argument_list[2].integer_reference;
11121 iterations=1;
11122 if (attribute_flag[3] != 0)
11123 iterations=argument_list[3].integer_reference;
11124 channel_mask=SetImageChannelMask(image,channel);
11125 image=MorphologyImage(image,method,iterations,kernel,exception);
11126 if (image != (Image *) NULL)
11127 (void) SetImageChannelMask(image,channel_mask);
11128 kernel=DestroyKernelInfo(kernel);
11129 break;
11130 }
11131 case 133: /* Mode */
11132 {
11133 if (attribute_flag[0] != 0)
11134 {
11135 flags=ParseGeometry(argument_list[0].string_reference,
11136 &geometry_info);
11137 if ((flags & SigmaValue) == 0)
11138 geometry_info.sigma=1.0;
11139 }
11140 if (attribute_flag[1] != 0)
11141 geometry_info.rho=argument_list[1].real_reference;
11142 if (attribute_flag[2] != 0)
11143 geometry_info.sigma=argument_list[2].real_reference;
11144 if (attribute_flag[3] != 0)
11145 channel=(ChannelType) argument_list[3].integer_reference;
11146 channel_mask=SetImageChannelMask(image,channel);
11147 image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11148 (size_t) geometry_info.sigma,exception);
11149 if (image != (Image *) NULL)
11150 (void) SetImageChannelMask(image,channel_mask);
11151 break;
11152 }
11153 case 134: /* Statistic */
11154 {
11155 StatisticType
11156 statistic;
11157
11158 statistic=UndefinedStatistic;
11159 if (attribute_flag[0] != 0)
11160 {
11161 flags=ParseGeometry(argument_list[0].string_reference,
11162 &geometry_info);
11163 if ((flags & SigmaValue) == 0)
11164 geometry_info.sigma=1.0;
11165 }
11166 if (attribute_flag[1] != 0)
11167 geometry_info.rho=argument_list[1].real_reference;
11168 if (attribute_flag[2] != 0)
11169 geometry_info.sigma=argument_list[2].real_reference;
11170 if (attribute_flag[3] != 0)
11171 channel=(ChannelType) argument_list[3].integer_reference;
11172 if (attribute_flag[4] != 0)
11173 statistic=(StatisticType) argument_list[4].integer_reference;
11174 channel_mask=SetImageChannelMask(image,channel);
11175 image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11176 (size_t) geometry_info.sigma,exception);
11177 if (image != (Image *) NULL)
11178 (void) SetImageChannelMask(image,channel_mask);
11179 break;
11180 }
11181 case 135: /* Perceptible */
11182 {
11183 double
11184 epsilon;
11185
11186 epsilon=MagickEpsilon;
11187 if (attribute_flag[0] != 0)
11188 epsilon=argument_list[0].real_reference;
11189 if (attribute_flag[1] != 0)
11190 channel=(ChannelType) argument_list[1].integer_reference;
11191 channel_mask=SetImageChannelMask(image,channel);
11192 (void) PerceptibleImage(image,epsilon,exception);
11193 (void) SetImageChannelMask(image,channel_mask);
11194 break;
11195 }
11196 case 136: /* Poly */
11197 {
11198 AV
11199 *av;
11200
11201 double
11202 *terms;
11203
11204 size_t
11205 number_terms;
11206
11207 if (attribute_flag[0] == 0)
11208 break;
11209 if (attribute_flag[1] != 0)
11210 channel=(ChannelType) argument_list[1].integer_reference;
11211 av=(AV *) argument_list[0].array_reference;
11212 number_terms=(size_t) av_len(av);
11213 terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11214 if (terms == (double *) NULL)
11215 {
11216 ThrowPerlException(exception,ResourceLimitFatalError,
11217 "MemoryAllocationFailed",PackageName);
11218 goto PerlException;
11219 }
11220 for (j=0; j < av_len(av); j++)
11221 terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11222 image=PolynomialImage(image,number_terms >> 1,terms,exception);
11223 terms=(double *) RelinquishMagickMemory(terms);
11224 break;
11225 }
11226 case 137: /* Grayscale */
11227 {
11228 PixelIntensityMethod
11229 method;
11230
11231 method=UndefinedPixelIntensityMethod;
11232 if (attribute_flag[0] != 0)
11233 method=(PixelIntensityMethod) argument_list[0].integer_reference;
11234 (void) GrayscaleImage(image,method,exception);
11235 break;
11236 }
cristy4ceadb82014-03-29 15:30:43 +000011237 case 138: /* Canny */
11238 {
11239 if (attribute_flag[0] != 0)
11240 {
11241 flags=ParseGeometry(argument_list[0].string_reference,
11242 &geometry_info);
11243 if ((flags & SigmaValue) == 0)
11244 geometry_info.sigma=1.0;
11245 if ((flags & XiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011246 geometry_info.xi=0.10;
cristy4ceadb82014-03-29 15:30:43 +000011247 if ((flags & PsiValue) == 0)
cristyed9cf8c2014-04-10 18:27:13 +000011248 geometry_info.psi=0.30;
cristy41814f22014-04-09 20:53:11 +000011249 if ((flags & PercentValue) != 0)
11250 {
11251 geometry_info.xi/=100.0;
11252 geometry_info.psi/=100.0;
11253 }
cristy4ceadb82014-03-29 15:30:43 +000011254 }
11255 if (attribute_flag[1] != 0)
11256 geometry_info.rho=argument_list[1].real_reference;
11257 if (attribute_flag[2] != 0)
11258 geometry_info.sigma=argument_list[2].real_reference;
11259 if (attribute_flag[3] != 0)
11260 geometry_info.xi=argument_list[3].real_reference;
11261 if (attribute_flag[4] != 0)
11262 geometry_info.psi=argument_list[4].real_reference;
11263 if (attribute_flag[5] != 0)
11264 channel=(ChannelType) argument_list[5].integer_reference;
11265 channel_mask=SetImageChannelMask(image,channel);
11266 image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11267 geometry_info.xi,geometry_info.psi,exception);
11268 if (image != (Image *) NULL)
11269 (void) SetImageChannelMask(image,channel_mask);
11270 break;
11271 }
cristy2fc10e52014-04-26 14:13:53 +000011272 case 139: /* HoughLine */
cristy4e215022014-04-19 18:02:35 +000011273 {
11274 if (attribute_flag[0] != 0)
11275 {
11276 flags=ParseGeometry(argument_list[0].string_reference,
11277 &geometry_info);
11278 if ((flags & SigmaValue) == 0)
11279 geometry_info.sigma=geometry_info.rho;
cristy20f90422014-04-27 13:34:21 +000011280 if ((flags & XiValue) == 0)
11281 geometry_info.xi=40;
cristy4e215022014-04-19 18:02:35 +000011282 }
11283 if (attribute_flag[1] != 0)
11284 geometry_info.rho=(double) argument_list[1].integer_reference;
11285 if (attribute_flag[2] != 0)
11286 geometry_info.sigma=(double) argument_list[2].integer_reference;
11287 if (attribute_flag[3] != 0)
11288 geometry_info.xi=(double) argument_list[3].integer_reference;
cristy2fc10e52014-04-26 14:13:53 +000011289 image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11290 geometry_info.sigma,(size_t) geometry_info.xi,exception);
11291 break;
11292 }
11293 case 140: /* MeanShift */
11294 {
11295 if (attribute_flag[0] != 0)
11296 {
11297 flags=ParseGeometry(argument_list[0].string_reference,
11298 &geometry_info);
11299 if ((flags & SigmaValue) == 0)
11300 geometry_info.sigma=geometry_info.rho;
cristy2fc10e52014-04-26 14:13:53 +000011301 if ((flags & XiValue) == 0)
cristy1309fc32014-04-26 18:48:37 +000011302 geometry_info.xi=0.10*QuantumRange;
11303 if ((flags & PercentValue) != 0)
11304 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
cristy2fc10e52014-04-26 14:13:53 +000011305 }
11306 if (attribute_flag[1] != 0)
11307 geometry_info.rho=(double) argument_list[1].integer_reference;
11308 if (attribute_flag[2] != 0)
11309 geometry_info.sigma=(double) argument_list[2].integer_reference;
11310 if (attribute_flag[3] != 0)
11311 geometry_info.xi=(double) argument_list[3].integer_reference;
11312 image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
cristy1309fc32014-04-26 18:48:37 +000011313 geometry_info.sigma,geometry_info.xi,exception);
cristy4e215022014-04-19 18:02:35 +000011314 break;
11315 }
cristy3b207f82014-09-27 14:21:20 +000011316 case 141: /* Kuwahara */
11317 {
11318 if (attribute_flag[0] != 0)
11319 {
11320 flags=ParseGeometry(argument_list[0].string_reference,
11321 &geometry_info);
11322 if ((flags & SigmaValue) == 0)
cristy3a9903c2014-10-04 01:14:20 +000011323 geometry_info.sigma=geometry_info.rho-0.5;
cristy3b207f82014-09-27 14:21:20 +000011324 }
11325 if (attribute_flag[1] != 0)
11326 geometry_info.rho=argument_list[1].real_reference;
11327 if (attribute_flag[2] != 0)
11328 geometry_info.sigma=argument_list[2].real_reference;
11329 if (attribute_flag[3] != 0)
11330 channel=(ChannelType) argument_list[3].integer_reference;
11331 channel_mask=SetImageChannelMask(image,channel);
11332 image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11333 exception);
11334 if (image != (Image *) NULL)
11335 (void) SetImageChannelMask(image,channel_mask);
11336 break;
11337 }
Cristy0f5df812017-07-04 18:30:05 -040011338 case 142: /* ConnectedComponents */
cristy6e0b3bc2014-10-19 17:51:42 +000011339 {
11340 size_t
11341 connectivity;
11342
11343 connectivity=4;
11344 if (attribute_flag[0] != 0)
11345 connectivity=argument_list[0].integer_reference;
Cristy2ca0e9a2016-01-01 08:36:14 -050011346 image=ConnectedComponentsImage(image,connectivity,
Cristy4f83be82015-12-31 08:40:53 -050011347 (CCObjectInfo **) NULL,exception);
cristy6e0b3bc2014-10-19 17:51:42 +000011348 break;
11349 }
cristy0b94b392015-06-22 18:56:37 +000011350 case 143: /* Copy */
11351 {
11352 Image
11353 *source_image;
11354
11355 OffsetInfo
11356 offset;
11357
cristy2ffdb092015-06-25 14:31:20 +000011358 RectangleInfo
11359 offset_geometry;
11360
cristyf3a724a2015-06-25 13:02:53 +000011361 source_image=image;
cristy0b94b392015-06-22 18:56:37 +000011362 if (attribute_flag[0] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011363 source_image=argument_list[0].image_reference;
cristy2ffdb092015-06-25 14:31:20 +000011364 SetGeometry(source_image,&geometry);
cristy0b94b392015-06-22 18:56:37 +000011365 if (attribute_flag[1] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011366 flags=ParseGravityGeometry(source_image,
11367 argument_list[1].string_reference,&geometry,exception);
cristy0b94b392015-06-22 18:56:37 +000011368 if (attribute_flag[2] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011369 geometry.width=argument_list[2].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011370 if (attribute_flag[3] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011371 geometry.height=argument_list[3].integer_reference;
cristy0b94b392015-06-22 18:56:37 +000011372 if (attribute_flag[4] != 0)
cristyf3a724a2015-06-25 13:02:53 +000011373 geometry.x=argument_list[4].integer_reference;
11374 if (attribute_flag[5] != 0)
11375 geometry.y=argument_list[5].integer_reference;
11376 if (attribute_flag[6] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011377 image->gravity=(GravityType) argument_list[6].integer_reference;
dirk169d1642015-06-27 19:51:08 +000011378 SetGeometry(image,&offset_geometry);
cristyf3a724a2015-06-25 13:02:53 +000011379 if (attribute_flag[7] != 0)
cristy2ffdb092015-06-25 14:31:20 +000011380 flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11381 &offset_geometry,exception);
11382 offset.x=offset_geometry.x;
11383 offset.y=offset_geometry.y;
cristyf3a724a2015-06-25 13:02:53 +000011384 if (attribute_flag[8] != 0)
11385 offset.x=argument_list[8].integer_reference;
11386 if (attribute_flag[9] != 0)
11387 offset.y=argument_list[9].integer_reference;
cristycd6d5182015-06-23 17:22:15 +000011388 (void) CopyImagePixels(image,source_image,&geometry,&offset,
11389 exception);
cristy0b94b392015-06-22 18:56:37 +000011390 break;
11391 }
Cristy5488c982016-02-13 14:07:50 -050011392 case 144: /* Color */
11393 {
11394 PixelInfo
11395 color;
11396
Cristyf20e3562016-02-14 09:08:15 -050011397 (void) QueryColorCompliance("none",AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011398 if (attribute_flag[0] != 0)
Cristyf20e3562016-02-14 09:08:15 -050011399 (void) QueryColorCompliance(argument_list[0].string_reference,
11400 AllCompliance,&color,exception);
Cristy5488c982016-02-13 14:07:50 -050011401 (void) SetImageColor(image,&color,exception);
11402 break;
11403 }
Cristy2d830ed2016-02-21 10:54:16 -050011404 case 145: /* WaveletDenoise */
11405 {
Cristyc1759412016-02-27 12:17:58 -050011406 if (attribute_flag[0] != 0)
Cristyee21f7f2016-02-27 15:56:49 -050011407 {
11408 flags=ParseGeometry(argument_list[0].string_reference,
11409 &geometry_info);
11410 if ((flags & PercentValue) != 0)
Cristy23446632016-02-29 09:36:34 -050011411 {
11412 geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11413 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11414 }
Cristyee21f7f2016-02-27 15:56:49 -050011415 if ((flags & SigmaValue) == 0)
11416 geometry_info.sigma=0.0;
11417 }
Cristyc1759412016-02-27 12:17:58 -050011418 if (attribute_flag[1] != 0)
11419 geometry_info.rho=argument_list[1].real_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011420 if (attribute_flag[2] != 0)
Cristyc1759412016-02-27 12:17:58 -050011421 geometry_info.sigma=argument_list[2].real_reference;
11422 if (attribute_flag[3] != 0)
11423 channel=(ChannelType) argument_list[3].integer_reference;
Cristy2d830ed2016-02-21 10:54:16 -050011424 channel_mask=SetImageChannelMask(image,channel);
Cristyc1759412016-02-27 12:17:58 -050011425 image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11426 exception);
Cristy2d830ed2016-02-21 10:54:16 -050011427 if (image != (Image *) NULL)
11428 (void) SetImageChannelMask(image,channel_mask);
11429 break;
11430 }
Cristy99a57162016-12-05 11:47:57 -050011431 case 146: /* Colorspace */
11432 {
11433 ColorspaceType
11434 colorspace;
11435
11436 colorspace=sRGBColorspace;
11437 if (attribute_flag[0] != 0)
11438 colorspace=(ColorspaceType) argument_list[0].integer_reference;
11439 (void) TransformImageColorspace(image,colorspace,exception);
11440 break;
11441 }
Cristy53353872017-07-02 12:24:24 -040011442 case 147: /* AutoThreshold */
11443 {
11444 AutoThresholdMethod
11445 method;
11446
11447 method=UndefinedThresholdMethod;
11448 if (attribute_flag[0] != 0)
Cristyb63e7752017-07-02 13:22:01 -040011449 method=(AutoThresholdMethod) argument_list[0].integer_reference;
Cristy53353872017-07-02 12:24:24 -040011450 (void) AutoThresholdImage(image,method,exception);
11451 break;
11452 }
Cristy532b3382018-08-05 17:56:56 -040011453 case 148: /* RangeThreshold */
11454 {
11455 if (attribute_flag[0] != 0)
11456 {
11457 flags=ParseGeometry(argument_list[0].string_reference,
11458 &geometry_info);
11459 if ((flags & SigmaValue) == 0)
11460 geometry_info.sigma=geometry_info.rho;
11461 if ((flags & XiValue) == 0)
11462 geometry_info.xi=geometry_info.sigma;
11463 if ((flags & PsiValue) == 0)
11464 geometry_info.psi=geometry_info.xi;
11465 }
11466 if (attribute_flag[1] != 0)
11467 geometry_info.rho=argument_list[1].real_reference;
11468 if (attribute_flag[2] != 0)
11469 geometry_info.sigma=argument_list[2].real_reference;
11470 if (attribute_flag[3] != 0)
11471 geometry_info.xi=argument_list[3].real_reference;
11472 if (attribute_flag[4] != 0)
11473 geometry_info.psi=argument_list[4].real_reference;
11474 if (attribute_flag[5] != 0)
11475 channel=(ChannelType) argument_list[5].integer_reference;
11476 channel_mask=SetImageChannelMask(image,channel);
Cristy9b220db2018-08-05 18:02:28 -040011477 (void) RangeThresholdImage(image,geometry_info.rho,
11478 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
Cristy532b3382018-08-05 17:56:56 -040011479 if (image != (Image *) NULL)
11480 (void) SetImageChannelMask(image,channel_mask);
11481 break;
11482 }
Cristy9f252542018-11-21 19:13:46 -050011483 case 149: /* CLAHE */
11484 {
11485 if (attribute_flag[0] != 0)
Cristy768e9002019-01-08 07:35:16 -050011486 {
11487 flags=ParseGeometry(argument_list[0].string_reference,
11488 &geometry_info);
11489 flags=ParseRegionGeometry(image,argument_list[0].string_reference,
11490 &geometry,exception);
11491 }
Cristy9f252542018-11-21 19:13:46 -050011492 if (attribute_flag[1] != 0)
Cristy30263282018-12-11 16:40:25 -050011493 geometry.width=argument_list[1].integer_reference;
Cristy9f252542018-11-21 19:13:46 -050011494 if (attribute_flag[2] != 0)
Cristy30263282018-12-11 16:40:25 -050011495 geometry.height=argument_list[2].integer_reference;
Cristy9f252542018-11-21 19:13:46 -050011496 if (attribute_flag[3] != 0)
Cristy768e9002019-01-08 07:35:16 -050011497 geometry.x=argument_list[3].integer_reference;
Cristy9f252542018-11-21 19:13:46 -050011498 if (attribute_flag[4] != 0)
Cristy768e9002019-01-08 07:35:16 -050011499 geometry_info.psi=argument_list[4].real_reference;
Cristyd9b98812018-12-16 09:30:05 -050011500 (void) CLAHEImage(image,geometry.width,geometry.height,geometry.x,
Cristy768e9002019-01-08 07:35:16 -050011501 geometry_info.psi,exception);
Cristy9f252542018-11-21 19:13:46 -050011502 break;
11503 }
cristy4a3ce0a2013-08-03 20:06:59 +000011504 }
11505 if (next != (Image *) NULL)
11506 (void) CatchImageException(next);
Cristy7e567962018-02-03 12:42:20 -050011507 if ((region_info.width*region_info.height) != 0)
11508 (void) SetImageRegionMask(image,WritePixelMask,
11509 (const RectangleInfo *) NULL,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011510 if (image != (Image *) NULL)
11511 {
11512 number_images++;
11513 if (next && (next != image))
11514 {
11515 image->next=next->next;
11516 if (image->next != (Image *) NULL)
11517 image->next->previous=image;
11518 DeleteImageFromRegistry(*pv,next);
11519 }
11520 sv_setiv(*pv,PTR2IV(image));
11521 next=image;
11522 }
11523 if (*pv)
11524 pv++;
11525 }
11526
11527 PerlException:
11528 if (reference_vector)
11529 reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11530 InheritPerlException(exception,perl_exception);
11531 exception=DestroyExceptionInfo(exception);
11532 sv_setiv(perl_exception,(IV) number_images);
11533 SvPOK_on(perl_exception);
11534 ST(0)=sv_2mortal(perl_exception);
11535 XSRETURN(1);
11536 }
11537
11538#
11539###############################################################################
11540# #
11541# #
11542# #
11543# M o n t a g e #
11544# #
11545# #
11546# #
11547###############################################################################
11548#
11549#
11550void
11551Montage(ref,...)
11552 Image::Magick ref=NO_INIT
11553 ALIAS:
11554 MontageImage = 1
11555 montage = 2
11556 montageimage = 3
11557 PPCODE:
11558 {
11559 AV
11560 *av;
11561
11562 char
11563 *attribute;
11564
11565 ExceptionInfo
11566 *exception;
11567
11568 HV
11569 *hv;
11570
11571 Image
11572 *image,
11573 *next;
11574
11575 PixelInfo
11576 transparent_color;
11577
11578 MontageInfo
11579 *montage_info;
11580
11581 register ssize_t
11582 i;
11583
11584 ssize_t
11585 sp;
11586
11587 struct PackageInfo
11588 *info;
11589
11590 SV
11591 *av_reference,
11592 *perl_exception,
11593 *reference,
11594 *rv,
11595 *sv;
11596
11597 PERL_UNUSED_VAR(ref);
11598 PERL_UNUSED_VAR(ix);
11599 exception=AcquireExceptionInfo();
11600 perl_exception=newSVpv("",0);
11601 sv=NULL;
11602 attribute=NULL;
11603 if (sv_isobject(ST(0)) == 0)
11604 {
11605 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11606 PackageName);
11607 goto PerlException;
11608 }
11609 reference=SvRV(ST(0));
11610 hv=SvSTASH(reference);
11611 av=newAV();
11612 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11613 SvREFCNT_dec(av);
11614 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11615 if (image == (Image *) NULL)
11616 {
11617 ThrowPerlException(exception,OptionError,"NoImagesDefined",
11618 PackageName);
11619 goto PerlException;
11620 }
11621 /*
11622 Get options.
11623 */
11624 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11625 montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11626 (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11627 exception);
11628 for (i=2; i < items; i+=2)
11629 {
11630 attribute=(char *) SvPV(ST(i-1),na);
11631 switch (*attribute)
11632 {
11633 case 'B':
11634 case 'b':
11635 {
11636 if (LocaleCompare(attribute,"background") == 0)
11637 {
11638 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11639 &montage_info->background_color,exception);
11640 for (next=image; next; next=next->next)
11641 next->background_color=montage_info->background_color;
11642 break;
11643 }
11644 if (LocaleCompare(attribute,"border") == 0)
11645 {
11646 montage_info->border_width=SvIV(ST(i));
11647 break;
11648 }
11649 if (LocaleCompare(attribute,"bordercolor") == 0)
11650 {
11651 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11652 &montage_info->border_color,exception);
11653 for (next=image; next; next=next->next)
11654 next->border_color=montage_info->border_color;
11655 break;
11656 }
11657 if (LocaleCompare(attribute,"borderwidth") == 0)
11658 {
11659 montage_info->border_width=SvIV(ST(i));
11660 break;
11661 }
11662 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11663 attribute);
11664 break;
11665 }
11666 case 'C':
11667 case 'c':
11668 {
11669 if (LocaleCompare(attribute,"compose") == 0)
11670 {
11671 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11672 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11673 if (sp < 0)
11674 {
11675 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11676 SvPV(ST(i),na));
11677 break;
11678 }
11679 for (next=image; next; next=next->next)
11680 next->compose=(CompositeOperator) sp;
11681 break;
11682 }
11683 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11684 attribute);
11685 break;
11686 }
11687 case 'F':
11688 case 'f':
11689 {
11690 if (LocaleCompare(attribute,"fill") == 0)
11691 {
11692 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11693 &montage_info->fill,exception);
11694 break;
11695 }
11696 if (LocaleCompare(attribute,"font") == 0)
11697 {
11698 (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11699 break;
11700 }
11701 if (LocaleCompare(attribute,"frame") == 0)
11702 {
11703 char
11704 *p;
11705
11706 p=SvPV(ST(i),na);
11707 if (IsGeometry(p) == MagickFalse)
11708 {
11709 ThrowPerlException(exception,OptionError,"MissingGeometry",
11710 p);
11711 break;
11712 }
11713 (void) CloneString(&montage_info->frame,p);
11714 if (*p == '\0')
11715 montage_info->frame=(char *) NULL;
11716 break;
11717 }
11718 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11719 attribute);
11720 break;
11721 }
11722 case 'G':
11723 case 'g':
11724 {
11725 if (LocaleCompare(attribute,"geometry") == 0)
11726 {
11727 char
11728 *p;
11729
11730 p=SvPV(ST(i),na);
11731 if (IsGeometry(p) == MagickFalse)
11732 {
11733 ThrowPerlException(exception,OptionError,"MissingGeometry",
11734 p);
11735 break;
11736 }
11737 (void) CloneString(&montage_info->geometry,p);
11738 if (*p == '\0')
11739 montage_info->geometry=(char *) NULL;
11740 break;
11741 }
11742 if (LocaleCompare(attribute,"gravity") == 0)
11743 {
11744 ssize_t
11745 in;
11746
11747 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11748 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11749 if (in < 0)
11750 {
11751 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11752 SvPV(ST(i),na));
11753 return;
11754 }
11755 montage_info->gravity=(GravityType) in;
11756 for (next=image; next; next=next->next)
11757 next->gravity=(GravityType) in;
11758 break;
11759 }
11760 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11761 attribute);
11762 break;
11763 }
11764 case 'L':
11765 case 'l':
11766 {
11767 if (LocaleCompare(attribute,"label") == 0)
11768 {
11769 for (next=image; next; next=next->next)
Cristy935a4052017-03-31 17:45:37 -040011770 (void) SetImageProperty(next,"label",InterpretImageProperties(
cristy4a3ce0a2013-08-03 20:06:59 +000011771 info ? info->image_info : (ImageInfo *) NULL,next,
Cristy935a4052017-03-31 17:45:37 -040011772 SvPV(ST(i),na),exception),exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011773 break;
11774 }
11775 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11776 attribute);
11777 break;
11778 }
11779 case 'M':
11780 case 'm':
11781 {
11782 if (LocaleCompare(attribute,"mattecolor") == 0)
11783 {
11784 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
Cristy8645e042016-02-03 16:35:29 -050011785 &montage_info->alpha_color,exception);
cristy4a3ce0a2013-08-03 20:06:59 +000011786 for (next=image; next; next=next->next)
Cristy8645e042016-02-03 16:35:29 -050011787 next->alpha_color=montage_info->alpha_color;
cristy4a3ce0a2013-08-03 20:06:59 +000011788 break;
11789 }
11790 if (LocaleCompare(attribute,"mode") == 0)
11791 {
11792 ssize_t
11793 in;
11794
11795 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11796 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11797 switch (in)
11798 {
11799 default:
11800 {
11801 ThrowPerlException(exception,OptionError,
11802 "UnrecognizedModeType",SvPV(ST(i),na));
11803 break;
11804 }
11805 case FrameMode:
11806 {
11807 (void) CloneString(&montage_info->frame,"15x15+3+3");
11808 montage_info->shadow=MagickTrue;
11809 break;
11810 }
11811 case UnframeMode:
11812 {
11813 montage_info->frame=(char *) NULL;
11814 montage_info->shadow=MagickFalse;
11815 montage_info->border_width=0;
11816 break;
11817 }
11818 case ConcatenateMode:
11819 {
11820 montage_info->frame=(char *) NULL;
11821 montage_info->shadow=MagickFalse;
11822 (void) CloneString(&montage_info->geometry,"+0+0");
11823 montage_info->border_width=0;
11824 }
11825 }
11826 break;
11827 }
11828 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11829 attribute);
11830 break;
11831 }
11832 case 'P':
11833 case 'p':
11834 {
11835 if (LocaleCompare(attribute,"pointsize") == 0)
11836 {
11837 montage_info->pointsize=SvIV(ST(i));
11838 break;
11839 }
11840 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11841 attribute);
11842 break;
11843 }
11844 case 'S':
11845 case 's':
11846 {
11847 if (LocaleCompare(attribute,"shadow") == 0)
11848 {
11849 sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11850 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11851 if (sp < 0)
11852 {
11853 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11854 SvPV(ST(i),na));
11855 break;
11856 }
11857 montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11858 break;
11859 }
11860 if (LocaleCompare(attribute,"stroke") == 0)
11861 {
11862 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11863 &montage_info->stroke,exception);
11864 break;
11865 }
11866 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11867 attribute);
11868 break;
11869 }
11870 case 'T':
11871 case 't':
11872 {
11873 if (LocaleCompare(attribute,"texture") == 0)
11874 {
11875 (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11876 break;
11877 }
11878 if (LocaleCompare(attribute,"tile") == 0)
11879 {
11880 char *p=SvPV(ST(i),na);
11881 if (IsGeometry(p) == MagickFalse)
11882 {
11883 ThrowPerlException(exception,OptionError,"MissingGeometry",
11884 p);
11885 break;
11886 }
11887 (void) CloneString(&montage_info->tile,p);
11888 if (*p == '\0')
11889 montage_info->tile=(char *) NULL;
11890 break;
11891 }
11892 if (LocaleCompare(attribute,"title") == 0)
11893 {
11894 (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11895 break;
11896 }
11897 if (LocaleCompare(attribute,"transparent") == 0)
11898 {
11899 PixelInfo
11900 transparent_color;
11901
11902 QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11903 &transparent_color,exception);
11904 for (next=image; next; next=next->next)
11905 (void) TransparentPaintImage(next,&transparent_color,
11906 TransparentAlpha,MagickFalse,exception);
11907 break;
11908 }
11909 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11910 attribute);
11911 break;
11912 }
11913 default:
11914 {
11915 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11916 attribute);
11917 break;
11918 }
11919 }
11920 }
11921 image=MontageImageList(info->image_info,montage_info,image,exception);
11922 montage_info=DestroyMontageInfo(montage_info);
11923 if (image == (Image *) NULL)
11924 goto PerlException;
11925 if (transparent_color.alpha != TransparentAlpha)
11926 for (next=image; next; next=next->next)
11927 (void) TransparentPaintImage(next,&transparent_color,
11928 TransparentAlpha,MagickFalse,exception);
11929 for ( ; image; image=image->next)
11930 {
11931 AddImageToRegistry(sv,image);
11932 rv=newRV(sv);
11933 av_push(av,sv_bless(rv,hv));
11934 SvREFCNT_dec(sv);
11935 }
11936 exception=DestroyExceptionInfo(exception);
11937 ST(0)=av_reference;
11938 SvREFCNT_dec(perl_exception);
11939 XSRETURN(1);
11940
11941 PerlException:
11942 InheritPerlException(exception,perl_exception);
11943 exception=DestroyExceptionInfo(exception);
11944 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11945 SvPOK_on(perl_exception);
11946 ST(0)=sv_2mortal(perl_exception);
11947 XSRETURN(1);
11948 }
11949
11950#
11951###############################################################################
11952# #
11953# #
11954# #
11955# M o r p h #
11956# #
11957# #
11958# #
11959###############################################################################
11960#
11961#
11962void
11963Morph(ref,...)
11964 Image::Magick ref=NO_INIT
11965 ALIAS:
11966 MorphImage = 1
11967 morph = 2
11968 morphimage = 3
11969 PPCODE:
11970 {
11971 AV
11972 *av;
11973
11974 char
11975 *attribute;
11976
11977 ExceptionInfo
11978 *exception;
11979
11980 HV
11981 *hv;
11982
11983 Image
11984 *image;
11985
11986 register ssize_t
11987 i;
11988
11989 ssize_t
11990 number_frames;
11991
11992 struct PackageInfo
11993 *info;
11994
11995 SV
11996 *av_reference,
11997 *perl_exception,
11998 *reference,
11999 *rv,
12000 *sv;
12001
12002 PERL_UNUSED_VAR(ref);
12003 PERL_UNUSED_VAR(ix);
12004 exception=AcquireExceptionInfo();
12005 perl_exception=newSVpv("",0);
12006 sv=NULL;
12007 av=NULL;
12008 attribute=NULL;
12009 if (sv_isobject(ST(0)) == 0)
12010 {
12011 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12012 PackageName);
12013 goto PerlException;
12014 }
12015 reference=SvRV(ST(0));
12016 hv=SvSTASH(reference);
12017 av=newAV();
12018 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12019 SvREFCNT_dec(av);
12020 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12021 if (image == (Image *) NULL)
12022 {
12023 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12024 PackageName);
12025 goto PerlException;
12026 }
12027 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12028 /*
12029 Get attribute.
12030 */
12031 number_frames=30;
12032 for (i=2; i < items; i+=2)
12033 {
12034 attribute=(char *) SvPV(ST(i-1),na);
12035 switch (*attribute)
12036 {
12037 case 'F':
12038 case 'f':
12039 {
12040 if (LocaleCompare(attribute,"frames") == 0)
12041 {
12042 number_frames=SvIV(ST(i));
12043 break;
12044 }
12045 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12046 attribute);
12047 break;
12048 }
12049 default:
12050 {
12051 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12052 attribute);
12053 break;
12054 }
12055 }
12056 }
12057 image=MorphImages(image,number_frames,exception);
12058 if (image == (Image *) NULL)
12059 goto PerlException;
12060 for ( ; image; image=image->next)
12061 {
12062 AddImageToRegistry(sv,image);
12063 rv=newRV(sv);
12064 av_push(av,sv_bless(rv,hv));
12065 SvREFCNT_dec(sv);
12066 }
12067 exception=DestroyExceptionInfo(exception);
12068 ST(0)=av_reference;
12069 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12070 XSRETURN(1);
12071
12072 PerlException:
12073 InheritPerlException(exception,perl_exception);
12074 exception=DestroyExceptionInfo(exception);
12075 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12076 SvPOK_on(perl_exception);
12077 ST(0)=sv_2mortal(perl_exception);
12078 XSRETURN(1);
12079 }
12080
12081#
12082###############################################################################
12083# #
12084# #
12085# #
12086# M o s a i c #
12087# #
12088# #
12089# #
12090###############################################################################
12091#
12092#
12093void
12094Mosaic(ref)
12095 Image::Magick ref=NO_INIT
12096 ALIAS:
12097 MosaicImage = 1
12098 mosaic = 2
12099 mosaicimage = 3
12100 PPCODE:
12101 {
12102 AV
12103 *av;
12104
12105 ExceptionInfo
12106 *exception;
12107
12108 HV
12109 *hv;
12110
12111 Image
12112 *image;
12113
12114 struct PackageInfo
12115 *info;
12116
12117 SV
12118 *perl_exception,
12119 *reference,
12120 *rv,
12121 *sv;
12122
12123 PERL_UNUSED_VAR(ref);
12124 PERL_UNUSED_VAR(ix);
12125 exception=AcquireExceptionInfo();
12126 perl_exception=newSVpv("",0);
12127 sv=NULL;
12128 if (sv_isobject(ST(0)) == 0)
12129 {
12130 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12131 PackageName);
12132 goto PerlException;
12133 }
12134 reference=SvRV(ST(0));
12135 hv=SvSTASH(reference);
12136 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12137 if (image == (Image *) NULL)
12138 {
12139 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12140 PackageName);
12141 goto PerlException;
12142 }
12143 image=MergeImageLayers(image,MosaicLayer,exception);
12144 /*
12145 Create blessed Perl array for the returned image.
12146 */
12147 av=newAV();
12148 ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12149 SvREFCNT_dec(av);
12150 AddImageToRegistry(sv,image);
12151 rv=newRV(sv);
12152 av_push(av,sv_bless(rv,hv));
12153 SvREFCNT_dec(sv);
cristy4a3ce0a2013-08-03 20:06:59 +000012154 (void) CopyMagickString(info->image_info->filename,image->filename,
cristy151b66d2015-04-15 10:50:31 +000012155 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012156 SetImageInfo(info->image_info,0,exception);
12157 exception=DestroyExceptionInfo(exception);
12158 SvREFCNT_dec(perl_exception);
12159 XSRETURN(1);
12160
12161 PerlException:
12162 InheritPerlException(exception,perl_exception);
12163 exception=DestroyExceptionInfo(exception);
12164 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12165 SvPOK_on(perl_exception); /* return messages in string context */
12166 ST(0)=sv_2mortal(perl_exception);
12167 XSRETURN(1);
12168 }
12169
12170#
12171###############################################################################
12172# #
12173# #
12174# #
12175# P i n g #
12176# #
12177# #
12178# #
12179###############################################################################
12180#
12181#
12182void
12183Ping(ref,...)
12184 Image::Magick ref=NO_INIT
12185 ALIAS:
12186 PingImage = 1
12187 ping = 2
12188 pingimage = 3
12189 PPCODE:
12190 {
12191 AV
12192 *av;
12193
12194 char
12195 **keep,
12196 **list;
12197
12198 ExceptionInfo
12199 *exception;
12200
12201 Image
12202 *image,
12203 *next;
12204
12205 int
12206 n;
12207
12208 MagickBooleanType
12209 status;
12210
12211 register char
12212 **p;
12213
12214 register ssize_t
12215 i;
12216
12217 ssize_t
12218 ac;
12219
12220 STRLEN
12221 *length;
12222
12223 struct PackageInfo
12224 *info,
12225 *package_info;
12226
12227 SV
12228 *perl_exception,
12229 *reference;
12230
12231 size_t
12232 count;
12233
12234 PERL_UNUSED_VAR(ref);
12235 PERL_UNUSED_VAR(ix);
12236 exception=AcquireExceptionInfo();
12237 perl_exception=newSVpv("",0);
12238 package_info=(struct PackageInfo *) NULL;
12239 ac=(items < 2) ? 1 : items-1;
12240 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12241 keep=list;
12242 length=(STRLEN *) NULL;
12243 if (list == (char **) NULL)
12244 {
12245 ThrowPerlException(exception,ResourceLimitError,
12246 "MemoryAllocationFailed",PackageName);
12247 goto PerlException;
12248 }
12249 keep=list;
12250 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12251 if (length == (STRLEN *) NULL)
12252 {
12253 ThrowPerlException(exception,ResourceLimitError,
12254 "MemoryAllocationFailed",PackageName);
12255 goto PerlException;
12256 }
12257 if (sv_isobject(ST(0)) == 0)
12258 {
12259 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12260 PackageName);
12261 goto PerlException;
12262 }
12263 reference=SvRV(ST(0));
12264 if (SvTYPE(reference) != SVt_PVAV)
12265 {
12266 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12267 PackageName);
12268 goto PerlException;
12269 }
12270 av=(AV *) reference;
12271 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12272 exception);
12273 package_info=ClonePackageInfo(info,exception);
12274 n=1;
12275 if (items <= 1)
12276 *list=(char *) (*package_info->image_info->filename ?
12277 package_info->image_info->filename : "XC:black");
12278 else
12279 for (n=0, i=0; i < ac; i++)
12280 {
12281 list[n]=(char *) SvPV(ST(i+1),length[n]);
12282 if ((items >= 3) && strEQcase(list[n],"blob"))
12283 {
12284 void
12285 *blob;
12286
12287 i++;
12288 blob=(void *) (SvPV(ST(i+1),length[n]));
12289 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12290 }
12291 if ((items >= 3) && strEQcase(list[n],"filename"))
12292 continue;
12293 if ((items >= 3) && strEQcase(list[n],"file"))
12294 {
12295 FILE
12296 *file;
12297
12298 PerlIO
12299 *io_info;
12300
12301 i++;
12302 io_info=IoIFP(sv_2io(ST(i+1)));
12303 if (io_info == (PerlIO *) NULL)
12304 {
12305 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12306 PackageName);
12307 continue;
12308 }
12309 file=PerlIO_findFILE(io_info);
12310 if (file == (FILE *) NULL)
12311 {
12312 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12313 PackageName);
12314 continue;
12315 }
12316 SetImageInfoFile(package_info->image_info,file);
12317 }
12318 if ((items >= 3) && strEQcase(list[n],"magick"))
12319 continue;
12320 n++;
12321 }
12322 list[n]=(char *) NULL;
12323 keep=list;
12324 status=ExpandFilenames(&n,&list);
12325 if (status == MagickFalse)
12326 {
12327 ThrowPerlException(exception,ResourceLimitError,
12328 "MemoryAllocationFailed",PackageName);
12329 goto PerlException;
12330 }
12331 count=0;
12332 for (i=0; i < n; i++)
12333 {
12334 (void) CopyMagickString(package_info->image_info->filename,list[i],
cristy151b66d2015-04-15 10:50:31 +000012335 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000012336 image=PingImage(package_info->image_info,exception);
12337 if (image == (Image *) NULL)
12338 break;
12339 if ((package_info->image_info->file != (FILE *) NULL) ||
12340 (package_info->image_info->blob != (void *) NULL))
12341 DisassociateImageStream(image);
12342 count+=GetImageListLength(image);
12343 EXTEND(sp,4*count);
12344 for (next=image; next; next=next->next)
12345 {
12346 PUSHs(sv_2mortal(newSViv(next->columns)));
12347 PUSHs(sv_2mortal(newSViv(next->rows)));
12348 PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12349 PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12350 }
12351 image=DestroyImageList(image);
12352 }
12353 /*
12354 Free resources.
12355 */
12356 for (i=0; i < n; i++)
12357 if (list[i] != (char *) NULL)
12358 for (p=keep; list[i] != *p++; )
12359 if (*p == NULL)
12360 {
12361 list[i]=(char *) RelinquishMagickMemory(list[i]);
12362 break;
12363 }
12364
12365 PerlException:
12366 if (package_info != (struct PackageInfo *) NULL)
12367 DestroyPackageInfo(package_info);
12368 if (list && (list != keep))
12369 list=(char **) RelinquishMagickMemory(list);
12370 if (keep)
12371 keep=(char **) RelinquishMagickMemory(keep);
12372 if (length)
12373 length=(STRLEN *) RelinquishMagickMemory(length);
12374 InheritPerlException(exception,perl_exception);
12375 exception=DestroyExceptionInfo(exception);
12376 SvREFCNT_dec(perl_exception); /* throw away all errors */
12377 }
12378
12379#
12380###############################################################################
12381# #
12382# #
12383# #
12384# P r e v i e w #
12385# #
12386# #
12387# #
12388###############################################################################
12389#
12390#
12391void
12392Preview(ref,...)
12393 Image::Magick ref=NO_INIT
12394 ALIAS:
12395 PreviewImage = 1
12396 preview = 2
12397 previewimage = 3
12398 PPCODE:
12399 {
12400 AV
12401 *av;
12402
12403 ExceptionInfo
12404 *exception;
12405
12406 HV
12407 *hv;
12408
12409 Image
12410 *image,
12411 *preview_image;
12412
12413 PreviewType
12414 preview_type;
12415
12416 struct PackageInfo
12417 *info;
12418
12419 SV
12420 *av_reference,
12421 *perl_exception,
12422 *reference,
12423 *rv,
12424 *sv;
12425
12426 PERL_UNUSED_VAR(ref);
12427 PERL_UNUSED_VAR(ix);
12428 exception=AcquireExceptionInfo();
12429 perl_exception=newSVpv("",0);
12430 sv=NULL;
12431 av=NULL;
12432 if (sv_isobject(ST(0)) == 0)
12433 {
12434 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12435 PackageName);
12436 goto PerlException;
12437 }
12438 reference=SvRV(ST(0));
12439 hv=SvSTASH(reference);
12440 av=newAV();
12441 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12442 SvREFCNT_dec(av);
12443 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12444 if (image == (Image *) NULL)
12445 {
12446 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12447 PackageName);
12448 goto PerlException;
12449 }
12450 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12451 preview_type=GammaPreview;
12452 if (items > 1)
12453 preview_type=(PreviewType)
12454 ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12455 for ( ; image; image=image->next)
12456 {
12457 preview_image=PreviewImage(image,preview_type,exception);
12458 if (preview_image == (Image *) NULL)
12459 goto PerlException;
12460 AddImageToRegistry(sv,preview_image);
12461 rv=newRV(sv);
12462 av_push(av,sv_bless(rv,hv));
12463 SvREFCNT_dec(sv);
12464 }
12465 exception=DestroyExceptionInfo(exception);
12466 ST(0)=av_reference;
12467 SvREFCNT_dec(perl_exception); /* can't return warning messages */
12468 XSRETURN(1);
12469
12470 PerlException:
12471 InheritPerlException(exception,perl_exception);
12472 exception=DestroyExceptionInfo(exception);
12473 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12474 SvPOK_on(perl_exception);
12475 ST(0)=sv_2mortal(perl_exception);
12476 XSRETURN(1);
12477 }
12478
12479#
12480###############################################################################
12481# #
12482# #
12483# #
12484# Q u e r y C o l o r #
12485# #
12486# #
12487# #
12488###############################################################################
12489#
12490#
12491void
12492QueryColor(ref,...)
12493 Image::Magick ref=NO_INIT
12494 ALIAS:
12495 querycolor = 1
12496 PPCODE:
12497 {
12498 char
12499 *name;
12500
12501 ExceptionInfo
12502 *exception;
12503
12504 PixelInfo
12505 color;
12506
12507 register ssize_t
12508 i;
12509
12510 SV
12511 *perl_exception;
12512
12513 PERL_UNUSED_VAR(ref);
12514 PERL_UNUSED_VAR(ix);
12515 exception=AcquireExceptionInfo();
12516 perl_exception=newSVpv("",0);
12517 if (items == 1)
12518 {
12519 const ColorInfo
12520 **colorlist;
12521
12522 size_t
12523 colors;
12524
12525 colorlist=GetColorInfoList("*",&colors,exception);
12526 EXTEND(sp,colors);
12527 for (i=0; i < (ssize_t) colors; i++)
12528 {
12529 PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12530 }
12531 colorlist=(const ColorInfo **)
12532 RelinquishMagickMemory((ColorInfo **) colorlist);
12533 goto PerlException;
12534 }
12535 EXTEND(sp,5*items);
12536 for (i=1; i < items; i++)
12537 {
12538 name=(char *) SvPV(ST(i),na);
12539 if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12540 {
12541 PUSHs(&sv_undef);
12542 continue;
12543 }
12544 PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12545 PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12546 PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12547 if (color.colorspace == CMYKColorspace)
12548 PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
cristy17f11b02014-12-20 19:37:04 +000012549 if (color.alpha_trait != UndefinedPixelTrait)
cristy4a3ce0a2013-08-03 20:06:59 +000012550 PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12551 }
12552
12553 PerlException:
12554 InheritPerlException(exception,perl_exception);
12555 exception=DestroyExceptionInfo(exception);
12556 SvREFCNT_dec(perl_exception);
12557 }
12558
12559#
12560###############################################################################
12561# #
12562# #
12563# #
12564# Q u e r y C o l o r N a m e #
12565# #
12566# #
12567# #
12568###############################################################################
12569#
12570#
12571void
12572QueryColorname(ref,...)
12573 Image::Magick ref=NO_INIT
12574 ALIAS:
12575 querycolorname = 1
12576 PPCODE:
12577 {
12578 AV
12579 *av;
12580
12581 char
cristy151b66d2015-04-15 10:50:31 +000012582 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012583
12584 ExceptionInfo
12585 *exception;
12586
12587 Image
12588 *image;
12589
12590 PixelInfo
12591 target_color;
12592
12593 register ssize_t
12594 i;
12595
12596 struct PackageInfo
12597 *info;
12598
12599 SV
12600 *perl_exception,
12601 *reference; /* reference is the SV* of ref=SvIV(reference) */
12602
12603 PERL_UNUSED_VAR(ref);
12604 PERL_UNUSED_VAR(ix);
12605 exception=AcquireExceptionInfo();
12606 perl_exception=newSVpv("",0);
12607 reference=SvRV(ST(0));
12608 av=(AV *) reference;
12609 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12610 exception);
12611 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12612 if (image == (Image *) NULL)
12613 {
12614 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12615 PackageName);
12616 goto PerlException;
12617 }
12618 EXTEND(sp,items);
12619 for (i=1; i < items; i++)
12620 {
12621 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12622 exception);
12623 (void) QueryColorname(image,&target_color,SVGCompliance,message,
12624 exception);
12625 PUSHs(sv_2mortal(newSVpv(message,0)));
12626 }
12627
12628 PerlException:
12629 InheritPerlException(exception,perl_exception);
12630 exception=DestroyExceptionInfo(exception);
12631 SvREFCNT_dec(perl_exception);
12632 }
12633
12634#
12635###############################################################################
12636# #
12637# #
12638# #
12639# Q u e r y F o n t #
12640# #
12641# #
12642# #
12643###############################################################################
12644#
12645#
12646void
12647QueryFont(ref,...)
12648 Image::Magick ref=NO_INIT
12649 ALIAS:
12650 queryfont = 1
12651 PPCODE:
12652 {
12653 char
12654 *name,
cristy151b66d2015-04-15 10:50:31 +000012655 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000012656
12657 ExceptionInfo
12658 *exception;
12659
12660 register ssize_t
12661 i;
12662
12663 SV
12664 *perl_exception;
12665
12666 volatile const TypeInfo
12667 *type_info;
12668
12669 PERL_UNUSED_VAR(ref);
12670 PERL_UNUSED_VAR(ix);
12671 exception=AcquireExceptionInfo();
12672 perl_exception=newSVpv("",0);
12673 if (items == 1)
12674 {
12675 const TypeInfo
12676 **typelist;
12677
12678 size_t
12679 types;
12680
12681 typelist=GetTypeInfoList("*",&types,exception);
12682 EXTEND(sp,types);
12683 for (i=0; i < (ssize_t) types; i++)
12684 {
12685 PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12686 }
12687 typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12688 typelist);
12689 goto PerlException;
12690 }
12691 EXTEND(sp,10*items);
12692 for (i=1; i < items; i++)
12693 {
12694 name=(char *) SvPV(ST(i),na);
12695 type_info=GetTypeInfo(name,exception);
12696 if (type_info == (TypeInfo *) NULL)
12697 {
12698 PUSHs(&sv_undef);
12699 continue;
12700 }
12701 if (type_info->name == (char *) NULL)
12702 PUSHs(&sv_undef);
12703 else
12704 PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12705 if (type_info->description == (char *) NULL)
12706 PUSHs(&sv_undef);
12707 else
12708 PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12709 if (type_info->family == (char *) NULL)
12710 PUSHs(&sv_undef);
12711 else
12712 PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12713 if (type_info->style == UndefinedStyle)
12714 PUSHs(&sv_undef);
12715 else
12716 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12717 type_info->style),0)));
12718 if (type_info->stretch == UndefinedStretch)
12719 PUSHs(&sv_undef);
12720 else
12721 PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12722 type_info->stretch),0)));
cristy151b66d2015-04-15 10:50:31 +000012723 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
cristy4a3ce0a2013-08-03 20:06:59 +000012724 type_info->weight);
12725 PUSHs(sv_2mortal(newSVpv(message,0)));
12726 if (type_info->encoding == (char *) NULL)
12727 PUSHs(&sv_undef);
12728 else
12729 PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12730 if (type_info->foundry == (char *) NULL)
12731 PUSHs(&sv_undef);
12732 else
12733 PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12734 if (type_info->format == (char *) NULL)
12735 PUSHs(&sv_undef);
12736 else
12737 PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12738 if (type_info->metrics == (char *) NULL)
12739 PUSHs(&sv_undef);
12740 else
12741 PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12742 if (type_info->glyphs == (char *) NULL)
12743 PUSHs(&sv_undef);
12744 else
12745 PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12746 }
12747
12748 PerlException:
12749 InheritPerlException(exception,perl_exception);
12750 exception=DestroyExceptionInfo(exception);
12751 SvREFCNT_dec(perl_exception);
12752 }
12753
12754#
12755###############################################################################
12756# #
12757# #
12758# #
12759# Q u e r y F o n t M e t r i c s #
12760# #
12761# #
12762# #
12763###############################################################################
12764#
12765#
12766void
12767QueryFontMetrics(ref,...)
12768 Image::Magick ref=NO_INIT
12769 ALIAS:
12770 queryfontmetrics = 1
12771 PPCODE:
12772 {
12773 AffineMatrix
12774 affine,
12775 current;
12776
12777 AV
12778 *av;
12779
12780 char
12781 *attribute;
12782
12783 double
12784 x,
12785 y;
12786
12787 DrawInfo
12788 *draw_info;
12789
12790 ExceptionInfo
12791 *exception;
12792
12793 GeometryInfo
12794 geometry_info;
12795
12796 Image
12797 *image;
12798
12799 MagickBooleanType
12800 status;
12801
12802 MagickStatusType
12803 flags;
12804
12805 register ssize_t
12806 i;
12807
12808 ssize_t
12809 type;
12810
12811 struct PackageInfo
12812 *info,
12813 *package_info;
12814
12815 SV
12816 *perl_exception,
12817 *reference; /* reference is the SV* of ref=SvIV(reference) */
12818
12819 TypeMetric
12820 metrics;
12821
12822 PERL_UNUSED_VAR(ref);
12823 PERL_UNUSED_VAR(ix);
12824 exception=AcquireExceptionInfo();
12825 package_info=(struct PackageInfo *) NULL;
12826 perl_exception=newSVpv("",0);
12827 reference=SvRV(ST(0));
12828 av=(AV *) reference;
12829 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12830 exception);
12831 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12832 if (image == (Image *) NULL)
12833 {
12834 ThrowPerlException(exception,OptionError,"NoImagesDefined",
12835 PackageName);
12836 goto PerlException;
12837 }
12838 package_info=ClonePackageInfo(info,exception);
12839 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12840 CloneString(&draw_info->text,"");
12841 current=draw_info->affine;
12842 GetAffineMatrix(&affine);
12843 x=0.0;
12844 y=0.0;
12845 EXTEND(sp,7*items);
12846 for (i=2; i < items; i+=2)
12847 {
12848 attribute=(char *) SvPV(ST(i-1),na);
12849 switch (*attribute)
12850 {
12851 case 'A':
12852 case 'a':
12853 {
12854 if (LocaleCompare(attribute,"antialias") == 0)
12855 {
12856 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12857 SvPV(ST(i),na));
12858 if (type < 0)
12859 {
12860 ThrowPerlException(exception,OptionError,"UnrecognizedType",
12861 SvPV(ST(i),na));
12862 break;
12863 }
12864 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12865 break;
12866 }
12867 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12868 attribute);
12869 break;
12870 }
12871 case 'd':
12872 case 'D':
12873 {
12874 if (LocaleCompare(attribute,"density") == 0)
12875 {
12876 CloneString(&draw_info->density,SvPV(ST(i),na));
12877 break;
12878 }
12879 if (LocaleCompare(attribute,"direction") == 0)
12880 {
12881 draw_info->direction=(DirectionType) ParseCommandOption(
12882 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12883 break;
12884 }
12885 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12886 attribute);
12887 break;
12888 }
12889 case 'e':
12890 case 'E':
12891 {
12892 if (LocaleCompare(attribute,"encoding") == 0)
12893 {
12894 CloneString(&draw_info->encoding,SvPV(ST(i),na));
12895 break;
12896 }
12897 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12898 attribute);
12899 break;
12900 }
12901 case 'f':
12902 case 'F':
12903 {
12904 if (LocaleCompare(attribute,"family") == 0)
12905 {
12906 CloneString(&draw_info->family,SvPV(ST(i),na));
12907 break;
12908 }
12909 if (LocaleCompare(attribute,"fill") == 0)
12910 {
12911 if (info)
12912 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12913 &draw_info->fill,exception);
12914 break;
12915 }
12916 if (LocaleCompare(attribute,"font") == 0)
12917 {
12918 CloneString(&draw_info->font,SvPV(ST(i),na));
12919 break;
12920 }
12921 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12922 attribute);
12923 break;
12924 }
12925 case 'g':
12926 case 'G':
12927 {
12928 if (LocaleCompare(attribute,"geometry") == 0)
12929 {
12930 CloneString(&draw_info->geometry,SvPV(ST(i),na));
12931 break;
12932 }
12933 if (LocaleCompare(attribute,"gravity") == 0)
12934 {
12935 draw_info->gravity=(GravityType) ParseCommandOption(
12936 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12937 break;
12938 }
12939 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12940 attribute);
12941 break;
12942 }
12943 case 'i':
12944 case 'I':
12945 {
12946 if (LocaleCompare(attribute,"interline-spacing") == 0)
12947 {
12948 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12949 draw_info->interline_spacing=geometry_info.rho;
12950 break;
12951 }
12952 if (LocaleCompare(attribute,"interword-spacing") == 0)
12953 {
12954 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12955 draw_info->interword_spacing=geometry_info.rho;
12956 break;
12957 }
12958 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12959 attribute);
12960 break;
12961 }
12962 case 'k':
12963 case 'K':
12964 {
12965 if (LocaleCompare(attribute,"kerning") == 0)
12966 {
12967 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12968 draw_info->kerning=geometry_info.rho;
12969 break;
12970 }
12971 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12972 attribute);
12973 break;
12974 }
12975 case 'p':
12976 case 'P':
12977 {
12978 if (LocaleCompare(attribute,"pointsize") == 0)
12979 {
12980 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12981 draw_info->pointsize=geometry_info.rho;
12982 break;
12983 }
12984 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12985 attribute);
12986 break;
12987 }
12988 case 'r':
12989 case 'R':
12990 {
12991 if (LocaleCompare(attribute,"rotate") == 0)
12992 {
12993 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12994 affine.rx=geometry_info.rho;
12995 affine.ry=geometry_info.sigma;
12996 if ((flags & SigmaValue) == 0)
12997 affine.ry=affine.rx;
12998 break;
12999 }
13000 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13001 attribute);
13002 break;
13003 }
13004 case 's':
13005 case 'S':
13006 {
13007 if (LocaleCompare(attribute,"scale") == 0)
13008 {
13009 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13010 affine.sx=geometry_info.rho;
13011 affine.sy=geometry_info.sigma;
13012 if ((flags & SigmaValue) == 0)
13013 affine.sy=affine.sx;
13014 break;
13015 }
13016 if (LocaleCompare(attribute,"skew") == 0)
13017 {
13018 double
13019 x_angle,
13020 y_angle;
13021
13022 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13023 x_angle=geometry_info.rho;
13024 y_angle=geometry_info.sigma;
13025 if ((flags & SigmaValue) == 0)
13026 y_angle=x_angle;
13027 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13028 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13029 break;
13030 }
13031 if (LocaleCompare(attribute,"stroke") == 0)
13032 {
13033 if (info)
13034 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13035 &draw_info->stroke,exception);
13036 break;
13037 }
13038 if (LocaleCompare(attribute,"style") == 0)
13039 {
13040 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13041 SvPV(ST(i),na));
13042 if (type < 0)
13043 {
13044 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13045 SvPV(ST(i),na));
13046 break;
13047 }
13048 draw_info->style=(StyleType) type;
13049 break;
13050 }
13051 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13052 attribute);
13053 break;
13054 }
13055 case 't':
13056 case 'T':
13057 {
13058 if (LocaleCompare(attribute,"text") == 0)
13059 {
13060 CloneString(&draw_info->text,SvPV(ST(i),na));
13061 break;
13062 }
13063 if (LocaleCompare(attribute,"translate") == 0)
13064 {
13065 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13066 affine.tx=geometry_info.rho;
13067 affine.ty=geometry_info.sigma;
13068 if ((flags & SigmaValue) == 0)
13069 affine.ty=affine.tx;
13070 break;
13071 }
13072 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13073 attribute);
13074 break;
13075 }
13076 case 'w':
13077 case 'W':
13078 {
13079 if (LocaleCompare(attribute,"weight") == 0)
13080 {
13081 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13082 draw_info->weight=(size_t) geometry_info.rho;
13083 break;
13084 }
13085 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13086 attribute);
13087 break;
13088 }
13089 case 'x':
13090 case 'X':
13091 {
13092 if (LocaleCompare(attribute,"x") == 0)
13093 {
13094 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13095 x=geometry_info.rho;
13096 break;
13097 }
13098 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13099 attribute);
13100 break;
13101 }
13102 case 'y':
13103 case 'Y':
13104 {
13105 if (LocaleCompare(attribute,"y") == 0)
13106 {
13107 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13108 y=geometry_info.rho;
13109 break;
13110 }
13111 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13112 attribute);
13113 break;
13114 }
13115 default:
13116 {
13117 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13118 attribute);
13119 break;
13120 }
13121 }
13122 }
13123 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13124 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13125 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13126 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13127 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13128 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13129 if (draw_info->geometry == (char *) NULL)
13130 {
13131 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013132 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013133 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013134 }
13135 status=GetTypeMetrics(image,draw_info,&metrics,exception);
13136 (void) CatchImageException(image);
13137 if (status == MagickFalse)
13138 PUSHs(&sv_undef);
13139 else
13140 {
13141 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13142 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13143 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13144 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13145 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13146 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13147 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13148 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13149 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13150 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13151 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13152 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13153 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13154 }
13155 draw_info=DestroyDrawInfo(draw_info);
13156
13157 PerlException:
13158 if (package_info != (struct PackageInfo *) NULL)
13159 DestroyPackageInfo(package_info);
13160 InheritPerlException(exception,perl_exception);
13161 exception=DestroyExceptionInfo(exception);
13162 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13163 }
13164
13165#
13166###############################################################################
13167# #
13168# #
13169# #
13170# 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 #
13171# #
13172# #
13173# #
13174###############################################################################
13175#
13176#
13177void
13178QueryMultilineFontMetrics(ref,...)
13179 Image::Magick ref=NO_INIT
13180 ALIAS:
13181 querymultilinefontmetrics = 1
13182 PPCODE:
13183 {
13184 AffineMatrix
13185 affine,
13186 current;
13187
13188 AV
13189 *av;
13190
13191 char
13192 *attribute;
13193
13194 double
13195 x,
13196 y;
13197
13198 DrawInfo
13199 *draw_info;
13200
13201 ExceptionInfo
13202 *exception;
13203
13204 GeometryInfo
13205 geometry_info;
13206
13207 Image
13208 *image;
13209
13210 MagickBooleanType
13211 status;
13212
13213 MagickStatusType
13214 flags;
13215
13216 register ssize_t
13217 i;
13218
13219 ssize_t
13220 type;
13221
13222 struct PackageInfo
13223 *info,
13224 *package_info;
13225
13226 SV
13227 *perl_exception,
13228 *reference; /* reference is the SV* of ref=SvIV(reference) */
13229
13230 TypeMetric
13231 metrics;
13232
13233 PERL_UNUSED_VAR(ref);
13234 PERL_UNUSED_VAR(ix);
13235 exception=AcquireExceptionInfo();
13236 package_info=(struct PackageInfo *) NULL;
13237 perl_exception=newSVpv("",0);
13238 reference=SvRV(ST(0));
13239 av=(AV *) reference;
13240 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13241 exception);
13242 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13243 if (image == (Image *) NULL)
13244 {
13245 ThrowPerlException(exception,OptionError,"NoImagesDefined",
13246 PackageName);
13247 goto PerlException;
13248 }
13249 package_info=ClonePackageInfo(info,exception);
13250 draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13251 CloneString(&draw_info->text,"");
13252 current=draw_info->affine;
13253 GetAffineMatrix(&affine);
13254 x=0.0;
13255 y=0.0;
13256 EXTEND(sp,7*items);
13257 for (i=2; i < items; i+=2)
13258 {
13259 attribute=(char *) SvPV(ST(i-1),na);
13260 switch (*attribute)
13261 {
13262 case 'A':
13263 case 'a':
13264 {
13265 if (LocaleCompare(attribute,"antialias") == 0)
13266 {
13267 type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13268 SvPV(ST(i),na));
13269 if (type < 0)
13270 {
13271 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13272 SvPV(ST(i),na));
13273 break;
13274 }
13275 draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13276 break;
13277 }
13278 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13279 attribute);
13280 break;
13281 }
13282 case 'd':
13283 case 'D':
13284 {
13285 if (LocaleCompare(attribute,"density") == 0)
13286 {
13287 CloneString(&draw_info->density,SvPV(ST(i),na));
13288 break;
13289 }
13290 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13291 attribute);
13292 break;
13293 }
13294 case 'e':
13295 case 'E':
13296 {
13297 if (LocaleCompare(attribute,"encoding") == 0)
13298 {
13299 CloneString(&draw_info->encoding,SvPV(ST(i),na));
13300 break;
13301 }
13302 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13303 attribute);
13304 break;
13305 }
13306 case 'f':
13307 case 'F':
13308 {
13309 if (LocaleCompare(attribute,"family") == 0)
13310 {
13311 CloneString(&draw_info->family,SvPV(ST(i),na));
13312 break;
13313 }
13314 if (LocaleCompare(attribute,"fill") == 0)
13315 {
13316 if (info)
13317 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13318 &draw_info->fill,exception);
13319 break;
13320 }
13321 if (LocaleCompare(attribute,"font") == 0)
13322 {
13323 CloneString(&draw_info->font,SvPV(ST(i),na));
13324 break;
13325 }
13326 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13327 attribute);
13328 break;
13329 }
13330 case 'g':
13331 case 'G':
13332 {
13333 if (LocaleCompare(attribute,"geometry") == 0)
13334 {
13335 CloneString(&draw_info->geometry,SvPV(ST(i),na));
13336 break;
13337 }
13338 if (LocaleCompare(attribute,"gravity") == 0)
13339 {
13340 draw_info->gravity=(GravityType) ParseCommandOption(
13341 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13342 break;
13343 }
13344 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13345 attribute);
13346 break;
13347 }
13348 case 'p':
13349 case 'P':
13350 {
13351 if (LocaleCompare(attribute,"pointsize") == 0)
13352 {
13353 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13354 draw_info->pointsize=geometry_info.rho;
13355 break;
13356 }
13357 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13358 attribute);
13359 break;
13360 }
13361 case 'r':
13362 case 'R':
13363 {
13364 if (LocaleCompare(attribute,"rotate") == 0)
13365 {
13366 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13367 affine.rx=geometry_info.rho;
13368 affine.ry=geometry_info.sigma;
13369 if ((flags & SigmaValue) == 0)
13370 affine.ry=affine.rx;
13371 break;
13372 }
13373 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13374 attribute);
13375 break;
13376 }
13377 case 's':
13378 case 'S':
13379 {
13380 if (LocaleCompare(attribute,"scale") == 0)
13381 {
13382 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13383 affine.sx=geometry_info.rho;
13384 affine.sy=geometry_info.sigma;
13385 if ((flags & SigmaValue) == 0)
13386 affine.sy=affine.sx;
13387 break;
13388 }
13389 if (LocaleCompare(attribute,"skew") == 0)
13390 {
13391 double
13392 x_angle,
13393 y_angle;
13394
13395 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13396 x_angle=geometry_info.rho;
13397 y_angle=geometry_info.sigma;
13398 if ((flags & SigmaValue) == 0)
13399 y_angle=x_angle;
13400 affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13401 affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13402 break;
13403 }
13404 if (LocaleCompare(attribute,"stroke") == 0)
13405 {
13406 if (info)
13407 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13408 &draw_info->stroke,exception);
13409 break;
13410 }
13411 if (LocaleCompare(attribute,"style") == 0)
13412 {
13413 type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13414 SvPV(ST(i),na));
13415 if (type < 0)
13416 {
13417 ThrowPerlException(exception,OptionError,"UnrecognizedType",
13418 SvPV(ST(i),na));
13419 break;
13420 }
13421 draw_info->style=(StyleType) type;
13422 break;
13423 }
13424 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13425 attribute);
13426 break;
13427 }
13428 case 't':
13429 case 'T':
13430 {
13431 if (LocaleCompare(attribute,"text") == 0)
13432 {
13433 CloneString(&draw_info->text,SvPV(ST(i),na));
13434 break;
13435 }
13436 if (LocaleCompare(attribute,"translate") == 0)
13437 {
13438 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13439 affine.tx=geometry_info.rho;
13440 affine.ty=geometry_info.sigma;
13441 if ((flags & SigmaValue) == 0)
13442 affine.ty=affine.tx;
13443 break;
13444 }
13445 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13446 attribute);
13447 break;
13448 }
13449 case 'w':
13450 case 'W':
13451 {
13452 if (LocaleCompare(attribute,"weight") == 0)
13453 {
13454 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13455 draw_info->weight=(size_t) geometry_info.rho;
13456 break;
13457 }
13458 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13459 attribute);
13460 break;
13461 }
13462 case 'x':
13463 case 'X':
13464 {
13465 if (LocaleCompare(attribute,"x") == 0)
13466 {
13467 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13468 x=geometry_info.rho;
13469 break;
13470 }
13471 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13472 attribute);
13473 break;
13474 }
13475 case 'y':
13476 case 'Y':
13477 {
13478 if (LocaleCompare(attribute,"y") == 0)
13479 {
13480 flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13481 y=geometry_info.rho;
13482 break;
13483 }
13484 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13485 attribute);
13486 break;
13487 }
13488 default:
13489 {
13490 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13491 attribute);
13492 break;
13493 }
13494 }
13495 }
13496 draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13497 draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13498 draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13499 draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13500 draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13501 draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13502 if (draw_info->geometry == (char *) NULL)
13503 {
13504 draw_info->geometry=AcquireString((char *) NULL);
cristy151b66d2015-04-15 10:50:31 +000013505 (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
Cristyb1710fe2017-02-11 13:51:48 -050013506 "%.20g,%.20g",x,y);
cristy4a3ce0a2013-08-03 20:06:59 +000013507 }
13508 status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13509 (void) CatchException(exception);
13510 if (status == MagickFalse)
13511 PUSHs(&sv_undef);
13512 else
13513 {
13514 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13515 PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13516 PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13517 PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13518 PUSHs(sv_2mortal(newSVnv(metrics.width)));
13519 PUSHs(sv_2mortal(newSVnv(metrics.height)));
13520 PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13521 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13522 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13523 PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13524 PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13525 PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13526 PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13527 }
13528 draw_info=DestroyDrawInfo(draw_info);
13529
13530 PerlException:
13531 if (package_info != (struct PackageInfo *) NULL)
13532 DestroyPackageInfo(package_info);
13533 InheritPerlException(exception,perl_exception);
13534 exception=DestroyExceptionInfo(exception);
13535 SvREFCNT_dec(perl_exception); /* can't return warning messages */
13536 }
13537
13538#
13539###############################################################################
13540# #
13541# #
13542# #
13543# Q u e r y F o r m a t #
13544# #
13545# #
13546# #
13547###############################################################################
13548#
13549#
13550void
13551QueryFormat(ref,...)
13552 Image::Magick ref=NO_INIT
13553 ALIAS:
13554 queryformat = 1
13555 PPCODE:
13556 {
13557 char
13558 *name;
13559
13560 ExceptionInfo
13561 *exception;
13562
13563 register ssize_t
13564 i;
13565
13566 SV
13567 *perl_exception;
13568
13569 volatile const MagickInfo
13570 *magick_info;
13571
13572 PERL_UNUSED_VAR(ref);
13573 PERL_UNUSED_VAR(ix);
13574 exception=AcquireExceptionInfo();
13575 perl_exception=newSVpv("",0);
13576 if (items == 1)
13577 {
13578 char
cristy151b66d2015-04-15 10:50:31 +000013579 format[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000013580
13581 const MagickInfo
13582 **format_list;
13583
13584 size_t
13585 types;
13586
13587 format_list=GetMagickInfoList("*",&types,exception);
13588 EXTEND(sp,types);
13589 for (i=0; i < (ssize_t) types; i++)
13590 {
cristy151b66d2015-04-15 10:50:31 +000013591 (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000013592 LocaleLower(format);
13593 PUSHs(sv_2mortal(newSVpv(format,0)));
13594 }
13595 format_list=(const MagickInfo **)
13596 RelinquishMagickMemory((MagickInfo *) format_list);
13597 goto PerlException;
13598 }
13599 EXTEND(sp,8*items);
13600 for (i=1; i < items; i++)
13601 {
13602 name=(char *) SvPV(ST(i),na);
13603 magick_info=GetMagickInfo(name,exception);
13604 if (magick_info == (const MagickInfo *) NULL)
13605 {
13606 PUSHs(&sv_undef);
13607 continue;
13608 }
cristy4a3ce0a2013-08-03 20:06:59 +000013609 if (magick_info->description == (char *) NULL)
13610 PUSHs(&sv_undef);
13611 else
13612 PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
Cristy31756212019-07-31 15:55:08 -040013613 if (magick_info->magick_module == (char *) NULL)
cristy4a3ce0a2013-08-03 20:06:59 +000013614 PUSHs(&sv_undef);
13615 else
Cristy31756212019-07-31 15:55:08 -040013616 PUSHs(sv_2mortal(newSVpv(magick_info->magick_module,0)));
cristy4a3ce0a2013-08-03 20:06:59 +000013617 }
13618
13619 PerlException:
13620 InheritPerlException(exception,perl_exception);
13621 exception=DestroyExceptionInfo(exception);
13622 SvREFCNT_dec(perl_exception);
13623 }
13624
13625#
13626###############################################################################
13627# #
13628# #
13629# #
13630# Q u e r y O p t i o n #
13631# #
13632# #
13633# #
13634###############################################################################
13635#
13636#
13637void
13638QueryOption(ref,...)
13639 Image::Magick ref=NO_INIT
13640 ALIAS:
13641 queryoption = 1
13642 PPCODE:
13643 {
13644 char
13645 **options;
13646
13647 ExceptionInfo
13648 *exception;
13649
13650 register ssize_t
13651 i;
13652
13653 ssize_t
13654 j,
13655 option;
13656
13657 SV
13658 *perl_exception;
13659
13660 PERL_UNUSED_VAR(ref);
13661 PERL_UNUSED_VAR(ix);
13662 exception=AcquireExceptionInfo();
13663 perl_exception=newSVpv("",0);
13664 EXTEND(sp,8*items);
13665 for (i=1; i < items; i++)
13666 {
13667 option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13668 SvPV(ST(i),na));
13669 options=GetCommandOptions((CommandOption) option);
13670 if (options == (char **) NULL)
13671 PUSHs(&sv_undef);
13672 else
13673 {
13674 for (j=0; options[j] != (char *) NULL; j++)
13675 PUSHs(sv_2mortal(newSVpv(options[j],0)));
13676 options=DestroyStringList(options);
13677 }
13678 }
13679
13680 InheritPerlException(exception,perl_exception);
13681 exception=DestroyExceptionInfo(exception);
13682 SvREFCNT_dec(perl_exception);
13683 }
13684
13685#
13686###############################################################################
13687# #
13688# #
13689# #
13690# R e a d #
13691# #
13692# #
13693# #
13694###############################################################################
13695#
13696#
13697void
13698Read(ref,...)
13699 Image::Magick ref=NO_INIT
13700 ALIAS:
13701 ReadImage = 1
13702 read = 2
13703 readimage = 3
13704 PPCODE:
13705 {
13706 AV
13707 *av;
13708
13709 char
13710 **keep,
13711 **list;
13712
13713 ExceptionInfo
13714 *exception;
13715
13716 HV
13717 *hv;
13718
13719 Image
13720 *image;
13721
13722 int
13723 n;
13724
13725 MagickBooleanType
13726 status;
13727
13728 register char
13729 **p;
13730
13731 register ssize_t
13732 i;
13733
13734 ssize_t
13735 ac,
13736 number_images;
13737
13738 STRLEN
13739 *length;
13740
13741 struct PackageInfo
13742 *info,
13743 *package_info;
13744
13745 SV
13746 *perl_exception, /* Perl variable for storing messages */
13747 *reference,
13748 *rv,
13749 *sv;
13750
13751 PERL_UNUSED_VAR(ref);
13752 PERL_UNUSED_VAR(ix);
13753 exception=AcquireExceptionInfo();
13754 perl_exception=newSVpv("",0);
13755 sv=NULL;
13756 package_info=(struct PackageInfo *) NULL;
13757 number_images=0;
13758 ac=(items < 2) ? 1 : items-1;
13759 list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13760 keep=list;
13761 length=(STRLEN *) NULL;
13762 if (list == (char **) NULL)
13763 {
13764 ThrowPerlException(exception,ResourceLimitError,
13765 "MemoryAllocationFailed",PackageName);
13766 goto PerlException;
13767 }
13768 length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13769 if (length == (STRLEN *) NULL)
13770 {
13771 ThrowPerlException(exception,ResourceLimitError,
13772 "MemoryAllocationFailed",PackageName);
13773 goto PerlException;
13774 }
13775 if (sv_isobject(ST(0)) == 0)
13776 {
13777 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13778 PackageName);
13779 goto PerlException;
13780 }
13781 reference=SvRV(ST(0));
13782 hv=SvSTASH(reference);
13783 if (SvTYPE(reference) != SVt_PVAV)
13784 {
13785 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13786 PackageName);
13787 goto PerlException;
13788 }
13789 av=(AV *) reference;
13790 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13791 exception);
13792 package_info=ClonePackageInfo(info,exception);
13793 n=1;
13794 if (items <= 1)
13795 *list=(char *) (*package_info->image_info->filename ?
13796 package_info->image_info->filename : "XC:black");
13797 else
13798 for (n=0, i=0; i < ac; i++)
13799 {
13800 list[n]=(char *) SvPV(ST(i+1),length[n]);
13801 if ((items >= 3) && strEQcase(list[n],"blob"))
13802 {
13803 void
13804 *blob;
13805
13806 i++;
13807 blob=(void *) (SvPV(ST(i+1),length[n]));
13808 SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13809 }
13810 if ((items >= 3) && strEQcase(list[n],"filename"))
13811 continue;
13812 if ((items >= 3) && strEQcase(list[n],"file"))
13813 {
13814 FILE
13815 *file;
13816
13817 PerlIO
13818 *io_info;
13819
13820 i++;
13821 io_info=IoIFP(sv_2io(ST(i+1)));
13822 if (io_info == (PerlIO *) NULL)
13823 {
13824 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13825 PackageName);
13826 continue;
13827 }
13828 file=PerlIO_findFILE(io_info);
13829 if (file == (FILE *) NULL)
13830 {
13831 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13832 PackageName);
13833 continue;
13834 }
13835 SetImageInfoFile(package_info->image_info,file);
13836 }
13837 if ((items >= 3) && strEQcase(list[n],"magick"))
13838 continue;
13839 n++;
13840 }
13841 list[n]=(char *) NULL;
13842 keep=list;
13843 status=ExpandFilenames(&n,&list);
13844 if (status == MagickFalse)
13845 {
13846 ThrowPerlException(exception,ResourceLimitError,
13847 "MemoryAllocationFailed",PackageName);
13848 goto PerlException;
13849 }
13850 number_images=0;
13851 for (i=0; i < n; i++)
13852 {
13853 if ((package_info->image_info->file == (FILE *) NULL) &&
13854 (package_info->image_info->blob == (void *) NULL))
13855 image=ReadImages(package_info->image_info,list[i],exception);
13856 else
13857 {
13858 image=ReadImages(package_info->image_info,
13859 package_info->image_info->filename,exception);
13860 if (image != (Image *) NULL)
13861 DisassociateImageStream(image);
13862 }
13863 if (image == (Image *) NULL)
13864 break;
13865 for ( ; image; image=image->next)
13866 {
13867 AddImageToRegistry(sv,image);
13868 rv=newRV(sv);
13869 av_push(av,sv_bless(rv,hv));
13870 SvREFCNT_dec(sv);
13871 number_images++;
13872 }
13873 }
13874 /*
13875 Free resources.
13876 */
13877 for (i=0; i < n; i++)
13878 if (list[i] != (char *) NULL)
13879 for (p=keep; list[i] != *p++; )
13880 if (*p == (char *) NULL)
13881 {
13882 list[i]=(char *) RelinquishMagickMemory(list[i]);
13883 break;
13884 }
13885
13886 PerlException:
13887 if (package_info != (struct PackageInfo *) NULL)
13888 DestroyPackageInfo(package_info);
13889 if (list && (list != keep))
13890 list=(char **) RelinquishMagickMemory(list);
13891 if (keep)
13892 keep=(char **) RelinquishMagickMemory(keep);
13893 if (length)
13894 length=(STRLEN *) RelinquishMagickMemory(length);
13895 InheritPerlException(exception,perl_exception);
13896 exception=DestroyExceptionInfo(exception);
13897 sv_setiv(perl_exception,(IV) number_images);
13898 SvPOK_on(perl_exception);
13899 ST(0)=sv_2mortal(perl_exception);
13900 XSRETURN(1);
13901 }
13902
13903#
13904###############################################################################
13905# #
13906# #
13907# #
13908# R e m o t e #
13909# #
13910# #
13911# #
13912###############################################################################
13913#
13914#
13915void
13916Remote(ref,...)
13917 Image::Magick ref=NO_INIT
13918 ALIAS:
13919 RemoteCommand = 1
13920 remote = 2
13921 remoteCommand = 3
13922 PPCODE:
13923 {
13924 AV
13925 *av;
13926
13927 ExceptionInfo
13928 *exception;
13929
13930 register ssize_t
13931 i;
13932
13933 SV
13934 *perl_exception,
13935 *reference;
13936
13937 struct PackageInfo
13938 *info;
13939
13940 PERL_UNUSED_VAR(ref);
13941 PERL_UNUSED_VAR(ix);
13942 exception=AcquireExceptionInfo();
13943 perl_exception=newSVpv("",0);
13944 reference=SvRV(ST(0));
13945 av=(AV *) reference;
13946 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13947 exception);
13948 for (i=1; i < items; i++)
13949 (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13950 SvPV(ST(i),na),exception);
13951 InheritPerlException(exception,perl_exception);
13952 exception=DestroyExceptionInfo(exception);
13953 SvREFCNT_dec(perl_exception); /* throw away all errors */
13954 }
13955
13956#
13957###############################################################################
13958# #
13959# #
13960# #
13961# S e t #
13962# #
13963# #
13964# #
13965###############################################################################
13966#
13967#
13968void
13969Set(ref,...)
13970 Image::Magick ref=NO_INIT
13971 ALIAS:
13972 SetAttributes = 1
13973 SetAttribute = 2
13974 set = 3
13975 setattributes = 4
13976 setattribute = 5
13977 PPCODE:
13978 {
13979 ExceptionInfo
13980 *exception;
13981
13982 Image
13983 *image;
13984
13985 register ssize_t
13986 i;
13987
13988 struct PackageInfo
13989 *info;
13990
13991 SV
13992 *perl_exception,
13993 *reference; /* reference is the SV* of ref=SvIV(reference) */
13994
13995 PERL_UNUSED_VAR(ref);
13996 PERL_UNUSED_VAR(ix);
13997 exception=AcquireExceptionInfo();
13998 perl_exception=newSVpv("",0);
13999 if (sv_isobject(ST(0)) == 0)
14000 {
14001 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14002 PackageName);
14003 goto PerlException;
14004 }
14005 reference=SvRV(ST(0));
14006 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14007 if (items == 2)
14008 SetAttribute(aTHX_ info,image,"size",ST(1),exception);
14009 else
14010 for (i=2; i < items; i+=2)
14011 SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
14012
14013 PerlException:
14014 InheritPerlException(exception,perl_exception);
14015 exception=DestroyExceptionInfo(exception);
14016 sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
14017 SvPOK_on(perl_exception);
14018 ST(0)=sv_2mortal(perl_exception);
14019 XSRETURN(1);
14020 }
14021
14022#
14023###############################################################################
14024# #
14025# #
14026# #
14027# S e t P i x e l #
14028# #
14029# #
14030# #
14031###############################################################################
14032#
14033#
14034void
14035SetPixel(ref,...)
14036 Image::Magick ref=NO_INIT
14037 ALIAS:
14038 setpixel = 1
14039 setPixel = 2
14040 PPCODE:
14041 {
14042 AV
14043 *av;
14044
14045 char
14046 *attribute;
14047
14048 ChannelType
14049 channel,
14050 channel_mask;
14051
14052 ExceptionInfo
14053 *exception;
14054
14055 Image
14056 *image;
14057
14058 MagickBooleanType
14059 normalize;
14060
14061 RectangleInfo
14062 region;
14063
14064 register ssize_t
14065 i;
14066
14067 register Quantum
14068 *q;
14069
14070 ssize_t
14071 option;
14072
14073 struct PackageInfo
14074 *info;
14075
14076 SV
14077 *perl_exception,
14078 *reference; /* reference is the SV* of ref=SvIV(reference) */
14079
14080 PERL_UNUSED_VAR(ref);
14081 PERL_UNUSED_VAR(ix);
14082 exception=AcquireExceptionInfo();
14083 perl_exception=newSVpv("",0);
14084 reference=SvRV(ST(0));
14085 av=(AV *) reference;
14086 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14087 exception);
14088 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14089 if (image == (Image *) NULL)
14090 {
14091 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14092 PackageName);
14093 goto PerlException;
14094 }
14095 av=(AV *) NULL;
14096 normalize=MagickTrue;
14097 region.x=0;
14098 region.y=0;
14099 region.width=image->columns;
14100 region.height=1;
14101 if (items == 1)
14102 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14103 channel=DefaultChannels;
14104 for (i=2; i < items; i+=2)
14105 {
14106 attribute=(char *) SvPV(ST(i-1),na);
14107 switch (*attribute)
14108 {
14109 case 'C':
14110 case 'c':
14111 {
14112 if (LocaleCompare(attribute,"channel") == 0)
14113 {
14114 ssize_t
14115 option;
14116
14117 option=ParseChannelOption(SvPV(ST(i),na));
14118 if (option < 0)
14119 {
14120 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14121 SvPV(ST(i),na));
14122 return;
14123 }
14124 channel=(ChannelType) option;
14125 break;
14126 }
14127 if (LocaleCompare(attribute,"color") == 0)
14128 {
14129 if (SvTYPE(ST(i)) != SVt_RV)
14130 {
14131 char
cristy151b66d2015-04-15 10:50:31 +000014132 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014133
cristy151b66d2015-04-15 10:50:31 +000014134 (void) FormatLocaleString(message,MagickPathExtent,
cristy4a3ce0a2013-08-03 20:06:59 +000014135 "invalid %.60s value",attribute);
14136 ThrowPerlException(exception,OptionError,message,
14137 SvPV(ST(i),na));
14138 }
14139 av=(AV *) SvRV(ST(i));
14140 break;
14141 }
14142 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14143 attribute);
14144 break;
14145 }
14146 case 'g':
14147 case 'G':
14148 {
14149 if (LocaleCompare(attribute,"geometry") == 0)
14150 {
14151 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14152 break;
14153 }
14154 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14155 attribute);
14156 break;
14157 }
14158 case 'N':
14159 case 'n':
14160 {
14161 if (LocaleCompare(attribute,"normalize") == 0)
14162 {
14163 option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14164 SvPV(ST(i),na));
14165 if (option < 0)
14166 {
14167 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14168 SvPV(ST(i),na));
14169 break;
14170 }
14171 normalize=option != 0 ? MagickTrue : MagickFalse;
14172 break;
14173 }
14174 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14175 attribute);
14176 break;
14177 }
14178 case 'x':
14179 case 'X':
14180 {
14181 if (LocaleCompare(attribute,"x") == 0)
14182 {
14183 region.x=SvIV(ST(i));
14184 break;
14185 }
14186 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14187 attribute);
14188 break;
14189 }
14190 case 'y':
14191 case 'Y':
14192 {
14193 if (LocaleCompare(attribute,"y") == 0)
14194 {
14195 region.y=SvIV(ST(i));
14196 break;
14197 }
14198 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14199 attribute);
14200 break;
14201 }
14202 default:
14203 {
14204 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14205 attribute);
14206 break;
14207 }
14208 }
14209 }
14210 (void) SetImageStorageClass(image,DirectClass,exception);
14211 channel_mask=SetImageChannelMask(image,channel);
14212 q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14213 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14214 (SvTYPE(av) != SVt_PVAV))
14215 PUSHs(&sv_undef);
14216 else
14217 {
14218 double
14219 scale;
14220
14221 register ssize_t
14222 i;
14223
14224 i=0;
14225 scale=1.0;
14226 if (normalize != MagickFalse)
14227 scale=QuantumRange;
14228 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14229 (i <= av_len(av)))
14230 {
14231 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14232 av_fetch(av,i,0)))),q);
14233 i++;
14234 }
14235 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14236 (i <= av_len(av)))
14237 {
14238 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14239 av_fetch(av,i,0)))),q);
14240 i++;
14241 }
14242 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14243 (i <= av_len(av)))
14244 {
14245 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14246 av_fetch(av,i,0)))),q);
14247 i++;
14248 }
14249 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14250 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14251 {
14252 SetPixelBlack(image,ClampToQuantum(scale*
14253 SvNV(*(av_fetch(av,i,0)))),q);
14254 i++;
14255 }
14256 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14257 (i <= av_len(av)))
14258 {
14259 SetPixelAlpha(image,ClampToQuantum(scale*
14260 SvNV(*(av_fetch(av,i,0)))),q);
14261 i++;
14262 }
14263 (void) SyncAuthenticPixels(image,exception);
14264 }
14265 (void) SetImageChannelMask(image,channel_mask);
14266
14267 PerlException:
14268 InheritPerlException(exception,perl_exception);
14269 exception=DestroyExceptionInfo(exception);
14270 SvREFCNT_dec(perl_exception);
14271 }
14272
14273#
14274###############################################################################
14275# #
14276# #
14277# #
Cristybba545b2018-07-04 15:00:12 -040014278# S e t P i x e l s #
14279# #
14280# #
14281# #
14282###############################################################################
14283#
14284#
14285void
14286SetPixels(ref,...)
14287 Image::Magick ref=NO_INIT
14288 ALIAS:
14289 setpixels = 1
14290 setPixels = 2
14291 PPCODE:
14292 {
14293 AV
14294 *av;
14295
14296 char
14297 *attribute;
14298
14299 ChannelType
14300 channel,
14301 channel_mask;
14302
14303 ExceptionInfo
14304 *exception;
14305
14306 Image
14307 *image;
14308
14309 RectangleInfo
14310 region;
14311
14312 register ssize_t
14313 i;
14314
14315 register Quantum
14316 *q;
14317
14318 struct PackageInfo
14319 *info;
14320
14321 SV
14322 *perl_exception,
14323 *reference; /* reference is the SV* of ref=SvIV(reference) */
14324
14325 PERL_UNUSED_VAR(ref);
14326 PERL_UNUSED_VAR(ix);
14327 exception=AcquireExceptionInfo();
14328 perl_exception=newSVpv("",0);
14329 reference=SvRV(ST(0));
14330 av=(AV *) reference;
14331 info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14332 exception);
14333 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14334 if (image == (Image *) NULL)
14335 {
14336 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14337 PackageName);
14338 goto PerlException;
14339 }
14340 av=(AV *) NULL;
14341 region.x=0;
14342 region.y=0;
14343 region.width=image->columns;
14344 region.height=1;
14345 if (items == 1)
14346 (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14347 channel=DefaultChannels;
14348 for (i=2; i < items; i+=2)
14349 {
14350 attribute=(char *) SvPV(ST(i-1),na);
14351 switch (*attribute)
14352 {
14353 case 'C':
14354 case 'c':
14355 {
14356 if (LocaleCompare(attribute,"channel") == 0)
14357 {
14358 ssize_t
14359 option;
14360
14361 option=ParseChannelOption(SvPV(ST(i),na));
14362 if (option < 0)
14363 {
14364 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14365 SvPV(ST(i),na));
14366 return;
14367 }
14368 channel=(ChannelType) option;
14369 break;
14370 }
14371 if (LocaleCompare(attribute,"color") == 0)
14372 {
14373 if (SvTYPE(ST(i)) != SVt_RV)
14374 {
14375 char
14376 message[MagickPathExtent];
14377
14378 (void) FormatLocaleString(message,MagickPathExtent,
14379 "invalid %.60s value",attribute);
14380 ThrowPerlException(exception,OptionError,message,
14381 SvPV(ST(i),na));
14382 }
14383 av=(AV *) SvRV(ST(i));
14384 break;
14385 }
14386 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14387 attribute);
14388 break;
14389 }
14390 case 'g':
14391 case 'G':
14392 {
14393 if (LocaleCompare(attribute,"geometry") == 0)
14394 {
14395 (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14396 break;
14397 }
14398 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14399 attribute);
14400 break;
14401 }
14402 case 'h':
14403 case 'H':
14404 {
14405 if (LocaleCompare(attribute,"height") == 0)
14406 {
14407 region.height=SvIV(ST(i));
14408 break;
14409 }
14410 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14411 attribute);
14412 break;
14413 }
14414 case 'w':
14415 case 'W':
14416 {
14417 if (LocaleCompare(attribute,"width") == 0)
14418 {
14419 region.width=SvIV(ST(i));
14420 break;
14421 }
14422 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14423 attribute);
14424 break;
14425 }
14426 case 'x':
14427 case 'X':
14428 {
14429 if (LocaleCompare(attribute,"x") == 0)
14430 {
14431 region.x=SvIV(ST(i));
14432 break;
14433 }
14434 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14435 attribute);
14436 break;
14437 }
14438 case 'y':
14439 case 'Y':
14440 {
14441 if (LocaleCompare(attribute,"y") == 0)
14442 {
14443 region.y=SvIV(ST(i));
14444 break;
14445 }
14446 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14447 attribute);
14448 break;
14449 }
14450 default:
14451 {
14452 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14453 attribute);
14454 break;
14455 }
14456 }
14457 }
14458 (void) SetImageStorageClass(image,DirectClass,exception);
14459 channel_mask=SetImageChannelMask(image,channel);
14460 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
14461 exception);
14462 if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14463 (SvTYPE(av) != SVt_PVAV))
14464 PUSHs(&sv_undef);
14465 else
14466 {
14467 double
14468 scale;
14469
14470 register ssize_t
14471 i,
14472 n,
14473 number_pixels;
14474
14475 i=0;
14476 n=0;
14477 scale=(double) QuantumRange;
14478 number_pixels=region.width*region.height;
14479 while ((n < number_pixels) && (i < av_len(av)))
14480 {
14481 if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14482 (i <= av_len(av)))
14483 {
14484 SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14485 av_fetch(av,i,0)))),q);
14486 i++;
14487 }
14488 if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14489 (i <= av_len(av)))
14490 {
14491 SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14492 av_fetch(av,i,0)))),q);
14493 i++;
14494 }
14495 if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14496 (i <= av_len(av)))
14497 {
14498 SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14499 av_fetch(av,i,0)))),q);
14500 i++;
14501 }
14502 if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14503 (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14504 {
14505 SetPixelBlack(image,ClampToQuantum(scale*
14506 SvNV(*(av_fetch(av,i,0)))),q);
14507 i++;
14508 }
14509 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14510 (i <= av_len(av)))
14511 {
14512 SetPixelAlpha(image,ClampToQuantum(scale*
14513 SvNV(*(av_fetch(av,i,0)))),q);
14514 i++;
14515 }
14516 n++;
14517 q+=image->number_channels;
14518 }
14519 (void) SyncAuthenticPixels(image,exception);
14520 }
14521 (void) SetImageChannelMask(image,channel_mask);
14522
14523 PerlException:
14524 InheritPerlException(exception,perl_exception);
14525 exception=DestroyExceptionInfo(exception);
14526 SvREFCNT_dec(perl_exception);
14527 }
14528
14529#
14530###############################################################################
14531# #
14532# #
14533# #
cristy4a3ce0a2013-08-03 20:06:59 +000014534# S m u s h #
14535# #
14536# #
14537# #
14538###############################################################################
14539#
14540#
14541void
14542Smush(ref,...)
14543 Image::Magick ref=NO_INIT
14544 ALIAS:
14545 SmushImage = 1
14546 smush = 2
14547 smushimage = 3
14548 PPCODE:
14549 {
14550 AV
14551 *av;
14552
14553 char
14554 *attribute;
14555
14556 ExceptionInfo
14557 *exception;
14558
14559 HV
14560 *hv;
14561
14562 Image
14563 *image;
14564
14565 register ssize_t
14566 i;
14567
14568 ssize_t
14569 offset,
14570 stack;
14571
14572 struct PackageInfo
14573 *info;
14574
14575 SV
14576 *av_reference,
14577 *perl_exception,
14578 *reference,
14579 *rv,
14580 *sv;
14581
14582 PERL_UNUSED_VAR(ref);
14583 PERL_UNUSED_VAR(ix);
14584 exception=AcquireExceptionInfo();
14585 perl_exception=newSVpv("",0);
14586 sv=NULL;
14587 attribute=NULL;
14588 av=NULL;
14589 if (sv_isobject(ST(0)) == 0)
14590 {
14591 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14592 PackageName);
14593 goto PerlException;
14594 }
14595 reference=SvRV(ST(0));
14596 hv=SvSTASH(reference);
14597 av=newAV();
14598 av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14599 SvREFCNT_dec(av);
14600 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14601 if (image == (Image *) NULL)
14602 {
14603 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14604 PackageName);
14605 goto PerlException;
14606 }
14607 info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14608 /*
14609 Get options.
14610 */
14611 offset=0;
14612 stack=MagickTrue;
14613 for (i=2; i < items; i+=2)
14614 {
14615 attribute=(char *) SvPV(ST(i-1),na);
14616 switch (*attribute)
14617 {
14618 case 'O':
14619 case 'o':
14620 {
14621 if (LocaleCompare(attribute,"offset") == 0)
14622 {
14623 offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14624 break;
14625 }
14626 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14627 attribute);
14628 break;
14629 }
14630 case 'S':
14631 case 's':
14632 {
14633 if (LocaleCompare(attribute,"stack") == 0)
14634 {
14635 stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14636 SvPV(ST(i),na));
14637 if (stack < 0)
14638 {
14639 ThrowPerlException(exception,OptionError,"UnrecognizedType",
14640 SvPV(ST(i),na));
14641 return;
14642 }
14643 break;
14644 }
14645 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14646 attribute);
14647 break;
14648 }
14649 default:
14650 {
14651 ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14652 attribute);
14653 break;
14654 }
14655 }
14656 }
14657 image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14658 exception);
14659 if (image == (Image *) NULL)
14660 goto PerlException;
14661 for ( ; image; image=image->next)
14662 {
14663 AddImageToRegistry(sv,image);
14664 rv=newRV(sv);
14665 av_push(av,sv_bless(rv,hv));
14666 SvREFCNT_dec(sv);
14667 }
14668 exception=DestroyExceptionInfo(exception);
14669 ST(0)=av_reference;
14670 SvREFCNT_dec(perl_exception);
14671 XSRETURN(1);
14672
14673 PerlException:
14674 InheritPerlException(exception,perl_exception);
14675 exception=DestroyExceptionInfo(exception);
14676 sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14677 SvPOK_on(perl_exception);
14678 ST(0)=sv_2mortal(perl_exception);
14679 XSRETURN(1);
14680 }
14681
14682#
14683###############################################################################
14684# #
14685# #
14686# #
14687# S t a t i s t i c s #
14688# #
14689# #
14690# #
14691###############################################################################
14692#
14693#
14694void
14695Statistics(ref,...)
14696 Image::Magick ref=NO_INIT
14697 ALIAS:
14698 StatisticsImage = 1
14699 statistics = 2
14700 statisticsimage = 3
14701 PPCODE:
14702 {
14703#define ChannelStatistics(channel) \
14704{ \
cristy151b66d2015-04-15 10:50:31 +000014705 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014706 (double) channel_statistics[channel].depth); \
14707 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014708 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014709 channel_statistics[channel].minima/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014710 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014711 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014712 channel_statistics[channel].maxima/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014713 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014714 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014715 channel_statistics[channel].mean/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014716 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014717 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
Cristy5a854dc2017-02-11 15:43:46 -050014718 channel_statistics[channel].standard_deviation/QuantumRange); \
cristy4a3ce0a2013-08-03 20:06:59 +000014719 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014720 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014721 channel_statistics[channel].kurtosis); \
14722 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014723 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy4a3ce0a2013-08-03 20:06:59 +000014724 channel_statistics[channel].skewness); \
14725 PUSHs(sv_2mortal(newSVpv(message,0))); \
Cristyb1710fe2017-02-11 13:51:48 -050014726 (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
cristy275bdd92014-11-08 23:45:03 +000014727 channel_statistics[channel].entropy); \
14728 PUSHs(sv_2mortal(newSVpv(message,0))); \
cristy4a3ce0a2013-08-03 20:06:59 +000014729}
14730
14731 AV
14732 *av;
14733
14734 char
cristy151b66d2015-04-15 10:50:31 +000014735 message[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014736
14737 ChannelStatistics
14738 *channel_statistics;
14739
cristy4a3ce0a2013-08-03 20:06:59 +000014740 ExceptionInfo
14741 *exception;
14742
14743 Image
14744 *image;
14745
14746 ssize_t
14747 count;
14748
14749 struct PackageInfo
14750 *info;
14751
14752 SV
14753 *perl_exception,
14754 *reference;
14755
14756 PERL_UNUSED_VAR(ref);
14757 PERL_UNUSED_VAR(ix);
14758 exception=AcquireExceptionInfo();
14759 perl_exception=newSVpv("",0);
14760 av=NULL;
14761 if (sv_isobject(ST(0)) == 0)
14762 {
14763 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14764 PackageName);
14765 goto PerlException;
14766 }
14767 reference=SvRV(ST(0));
14768 av=newAV();
14769 SvREFCNT_dec(av);
14770 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14771 if (image == (Image *) NULL)
14772 {
14773 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14774 PackageName);
14775 goto PerlException;
14776 }
cristy4a3ce0a2013-08-03 20:06:59 +000014777 count=0;
14778 for ( ; image; image=image->next)
14779 {
Cristyb1710fe2017-02-11 13:51:48 -050014780 register size_t
14781 i;
14782
cristy4a3ce0a2013-08-03 20:06:59 +000014783 channel_statistics=GetImageStatistics(image,exception);
14784 if (channel_statistics == (ChannelStatistics *) NULL)
14785 continue;
14786 count++;
Cristyb1710fe2017-02-11 13:51:48 -050014787 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
14788 {
14789 PixelChannel channel=GetPixelChannelChannel(image,i);
14790 PixelTrait traits=GetPixelChannelTraits(image,channel);
Cristy5a854dc2017-02-11 15:43:46 -050014791 if (traits == UndefinedPixelTrait)
Cristyb1710fe2017-02-11 13:51:48 -050014792 continue;
Cristy5a854dc2017-02-11 15:43:46 -050014793 EXTEND(sp,8*(i+1)*count);
Cristyb1710fe2017-02-11 13:51:48 -050014794 ChannelStatistics(channel);
14795 }
Cristy25813902017-02-11 15:47:52 -050014796 EXTEND(sp,8*(i+1)*count);
14797 ChannelStatistics(CompositePixelChannel);
cristy4a3ce0a2013-08-03 20:06:59 +000014798 channel_statistics=(ChannelStatistics *)
14799 RelinquishMagickMemory(channel_statistics);
14800 }
14801
14802 PerlException:
14803 InheritPerlException(exception,perl_exception);
14804 exception=DestroyExceptionInfo(exception);
14805 SvREFCNT_dec(perl_exception);
14806 }
14807
14808#
14809###############################################################################
14810# #
14811# #
14812# #
14813# S y n c A u t h e n t i c P i x e l s #
14814# #
14815# #
14816# #
14817###############################################################################
14818#
14819#
14820void
14821SyncAuthenticPixels(ref,...)
14822 Image::Magick ref = NO_INIT
14823 ALIAS:
14824 Syncauthenticpixels = 1
14825 SyncImagePixels = 2
14826 syncimagepixels = 3
14827 CODE:
14828 {
14829 ExceptionInfo
14830 *exception;
14831
14832 Image
14833 *image;
14834
14835 MagickBooleanType
14836 status;
14837
14838 struct PackageInfo
14839 *info;
14840
14841 SV
14842 *perl_exception,
14843 *reference;
14844
14845 PERL_UNUSED_VAR(ref);
14846 PERL_UNUSED_VAR(ix);
14847 exception=AcquireExceptionInfo();
14848 perl_exception=newSVpv("",0);
14849 if (sv_isobject(ST(0)) == 0)
14850 {
14851 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14852 PackageName);
14853 goto PerlException;
14854 }
14855
14856 reference=SvRV(ST(0));
14857 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14858 if (image == (Image *) NULL)
14859 {
14860 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14861 PackageName);
14862 goto PerlException;
14863 }
14864
14865 status=SyncAuthenticPixels(image,exception);
14866 if (status != MagickFalse)
14867 return;
14868
14869 PerlException:
14870 InheritPerlException(exception,perl_exception);
14871 exception=DestroyExceptionInfo(exception);
14872 SvREFCNT_dec(perl_exception); /* throw away all errors */
14873 }
14874
14875#
14876###############################################################################
14877# #
14878# #
14879# #
cristy4a3ce0a2013-08-03 20:06:59 +000014880# W r i t e #
14881# #
14882# #
14883# #
14884###############################################################################
14885#
14886#
14887void
14888Write(ref,...)
14889 Image::Magick ref=NO_INIT
14890 ALIAS:
14891 WriteImage = 1
14892 write = 2
14893 writeimage = 3
14894 PPCODE:
14895 {
14896 char
cristy151b66d2015-04-15 10:50:31 +000014897 filename[MagickPathExtent];
cristy4a3ce0a2013-08-03 20:06:59 +000014898
14899 ExceptionInfo
14900 *exception;
14901
14902 Image
14903 *image,
14904 *next;
14905
14906 register ssize_t
14907 i;
14908
14909 ssize_t
14910 number_images,
14911 scene;
14912
14913 struct PackageInfo
14914 *info,
14915 *package_info;
14916
14917 SV
14918 *perl_exception,
14919 *reference;
14920
14921 PERL_UNUSED_VAR(ref);
14922 PERL_UNUSED_VAR(ix);
14923 exception=AcquireExceptionInfo();
14924 perl_exception=newSVpv("",0);
14925 number_images=0;
14926 package_info=(struct PackageInfo *) NULL;
14927 if (sv_isobject(ST(0)) == 0)
14928 {
14929 ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14930 PackageName);
14931 goto PerlException;
14932 }
14933 reference=SvRV(ST(0));
14934 image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14935 if (image == (Image *) NULL)
14936 {
14937 ThrowPerlException(exception,OptionError,"NoImagesDefined",
14938 PackageName);
14939 goto PerlException;
14940 }
Cristyb4ee45c2017-09-27 17:58:55 -040014941 scene=0;
14942 for (next=image; next; next=next->next)
14943 next->scene=scene++;
cristy4a3ce0a2013-08-03 20:06:59 +000014944 package_info=ClonePackageInfo(info,exception);
14945 if (items == 2)
14946 SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14947 else
14948 if (items > 2)
14949 for (i=2; i < items; i+=2)
14950 SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14951 exception);
14952 (void) CopyMagickString(filename,package_info->image_info->filename,
cristy151b66d2015-04-15 10:50:31 +000014953 MagickPathExtent);
cristy4a3ce0a2013-08-03 20:06:59 +000014954 for (next=image; next; next=next->next)
cristy151b66d2015-04-15 10:50:31 +000014955 (void) CopyMagickString(next->filename,filename,MagickPathExtent);
cristy68bd79a2015-02-25 12:23:36 +000014956 *package_info->image_info->magick='\0';
cristy4a3ce0a2013-08-03 20:06:59 +000014957 SetImageInfo(package_info->image_info,(unsigned int)
14958 GetImageListLength(image),exception);
14959 for (next=image; next; next=next->next)
14960 {
14961 (void) WriteImage(package_info->image_info,next,exception);
14962 number_images++;
14963 if (package_info->image_info->adjoin)
14964 break;
14965 }
14966
14967 PerlException:
14968 if (package_info != (struct PackageInfo *) NULL)
14969 DestroyPackageInfo(package_info);
14970 InheritPerlException(exception,perl_exception);
14971 exception=DestroyExceptionInfo(exception);
14972 sv_setiv(perl_exception,(IV) number_images);
14973 SvPOK_on(perl_exception);
14974 ST(0)=sv_2mortal(perl_exception);
14975 XSRETURN(1);
14976 }