blob: 3f9845b06a91cd9ce1c686a029f7b3ddc7eafca9 [file] [log] [blame]
anthony805a2d42011-09-25 08:25:12 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
anthony8b10b462012-02-08 12:32:44 +00006% OOO PPPP EEEE RRRR AA TTTTT III OOO N N %
7% O O P P E R R A A T I O O NN N %
8% O O PPPP EEE RRRR AAAA T I O O N N N %
9% O O P E R R A A T I O O N NN %
10% OOO P EEEE R RR A A T III OOO N N %
anthony805a2d42011-09-25 08:25:12 +000011% %
12% %
anthony8b10b462012-02-08 12:32:44 +000013% CLI Magick Option Methods %
anthony805a2d42011-09-25 08:25:12 +000014% %
anthony8b10b462012-02-08 12:32:44 +000015% Dragon Computing %
cristy9e58efd2012-01-30 14:27:34 +000016% Anthony Thyssen %
cristy0a0ca4f2011-09-28 01:15:28 +000017% September 2011 %
anthony805a2d42011-09-25 08:25:12 +000018% %
19% %
cristy45ef08f2012-12-07 13:13:34 +000020% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
anthony805a2d42011-09-25 08:25:12 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% Apply the given options (settings, and simple, or sequence operations) to
anthony8b10b462012-02-08 12:32:44 +000037% the given image(s) according to the current "image_info", "draw_info", and
38% "quantize_info" settings, stored in a special CLI Image Wand.
anthony805a2d42011-09-25 08:25:12 +000039%
40% The final goal is to allow the execution in a strict one option at a time
41% manner that is needed for 'pipelining and file scripting' of options in
42% IMv7.
43%
anthony8b10b462012-02-08 12:32:44 +000044% Anthony Thyssen, September 2011
anthony805a2d42011-09-25 08:25:12 +000045*/
46
47/*
48 Include declarations.
49*/
50#include "MagickWand/studio.h"
51#include "MagickWand/MagickWand.h"
anthony72feaa62012-01-17 06:46:23 +000052#include "MagickWand/magick-wand-private.h"
anthony43f425d2012-02-26 12:58:58 +000053#include "MagickWand/wand.h"
anthony756cd0d2012-04-08 12:41:44 +000054#include "MagickWand/wandcli.h"
55#include "MagickWand/wandcli-private.h"
56#include "MagickWand/operation.h"
anthony805a2d42011-09-25 08:25:12 +000057#include "MagickCore/monitor-private.h"
58#include "MagickCore/thread-private.h"
59#include "MagickCore/string-private.h"
anthony7a4d6102012-07-01 09:48:25 +000060#include "MagickCore/pixel-private.h"
anthony805a2d42011-09-25 08:25:12 +000061
62/*
63 Define declarations.
64*/
anthonyc7994672012-11-17 05:33:27 +000065#define USE_WAND_METHODS 1
anthonyafa3dfc2012-03-03 11:31:30 +000066#define MAX_STACK_DEPTH 32
67#define UNDEFINED_COMPRESSION_QUALITY 0UL
68
anthonyb1d483a2012-04-14 12:53:56 +000069/* FUTURE: why is this default so specific? */
70#define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
71
anthony805a2d42011-09-25 08:25:12 +000072/*
73 Constant declaration. (temporary exports)
74*/
75static const char
76 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000077 BorderColor[] = "#dfdfdf", /* sRGB gray */
78 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony22de2722012-04-19 14:43:00 +000079
80/* For Debugging Geometry Input */
81#define ReportGeometry(flags,info) \
82 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
83 flags, info.rho, info.sigma, info.xi, info.psi )
anthony805a2d42011-09-25 08:25:12 +000084
85/*
86** Function to report on the progress of image operations
87*/
88static MagickBooleanType MonitorProgress(const char *text,
89 const MagickOffsetType offset,const MagickSizeType extent,
anthony43f425d2012-02-26 12:58:58 +000090 void *wand_unused(cli_wandent_data))
anthony805a2d42011-09-25 08:25:12 +000091{
92 char
93 message[MaxTextExtent],
94 tag[MaxTextExtent];
95
96 const char
97 *locale_message;
98
99 register char
100 *p;
101
102 if (extent < 2)
103 return(MagickTrue);
104 (void) CopyMagickMemory(tag,text,MaxTextExtent);
105 p=strrchr(tag,'/');
106 if (p != (char *) NULL)
107 *p='\0';
108 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
109 locale_message=GetLocaleMessage(message);
110 if (locale_message == message)
111 locale_message=tag;
112 if (p == (char *) NULL)
113 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
114 locale_message,(long) offset,(unsigned long) extent,(long)
115 (100L*offset/(extent-1)));
116 else
117 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
118 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
119 (100L*offset/(extent-1)));
120 if (offset == (MagickOffsetType) (extent-1))
121 (void) FormatLocaleFile(stderr,"\n");
122 (void) fflush(stderr);
123 return(MagickTrue);
124}
125
126/*
127** GetImageCache() will read an image into a image cache if not already
128** present then return the image that is in the cache under that filename.
129*/
130static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
131 ExceptionInfo *exception)
132{
133 char
134 key[MaxTextExtent];
135
136 ExceptionInfo
137 *sans_exception;
138
139 Image
140 *image;
141
142 ImageInfo
143 *read_info;
144
145 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
146 sans_exception=AcquireExceptionInfo();
147 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
148 sans_exception=DestroyExceptionInfo(sans_exception);
149 if (image != (Image *) NULL)
150 return(image);
151 read_info=CloneImageInfo(image_info);
152 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
153 image=ReadImage(read_info,exception);
154 read_info=DestroyImageInfo(read_info);
155 if (image != (Image *) NULL)
156 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
157 return(image);
158}
159
anthony756cd0d2012-04-08 12:41:44 +0000160/*
anthonya89dd172011-10-04 13:29:35 +0000161 SparseColorOption() parse the complex -sparse-color argument into an
162 an array of floating point values than call SparseColorImage().
163 Argument is a complex mix of floating-point pixel coodinates, and color
164 specifications (or direct floating point numbers). The number of floats
165 needed to represent a color varies depending on teh current channel
166 setting.
anthony43f425d2012-02-26 12:58:58 +0000167
168 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000169*/
170static Image *SparseColorOption(const Image *image,
cristyab943592013-03-29 16:47:23 +0000171 const SparseColorMethod method,const char *arguments,ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000172{
173 char
174 token[MaxTextExtent];
175
176 const char
177 *p;
178
179 double
180 *sparse_arguments;
181
182 Image
183 *sparse_image;
184
185 PixelInfo
186 color;
187
188 MagickBooleanType
189 error;
190
191 register size_t
192 x;
193
194 size_t
195 number_arguments,
196 number_colors;
197
198 assert(image != (Image *) NULL);
199 assert(image->signature == MagickSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000200 if (IfMagickTrue(image->debug))
anthony805a2d42011-09-25 08:25:12 +0000201 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
202 assert(exception != (ExceptionInfo *) NULL);
203 assert(exception->signature == MagickSignature);
204 /*
anthonyb1d483a2012-04-14 12:53:56 +0000205 Limit channels according to image
206 add up number of values needed per color.
anthony805a2d42011-09-25 08:25:12 +0000207 */
208 number_colors=0;
209 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
210 number_colors++;
211 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
212 number_colors++;
213 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
214 number_colors++;
215 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
216 (image->colorspace == CMYKColorspace))
217 number_colors++;
218 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy8a46d822012-08-28 23:32:39 +0000219 image->alpha_trait == BlendPixelTrait)
anthony805a2d42011-09-25 08:25:12 +0000220 number_colors++;
221
222 /*
223 Read string, to determine number of arguments needed,
224 */
225 p=arguments;
226 x=0;
227 while( *p != '\0' )
228 {
229 GetMagickToken(p,&p,token);
230 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000231 if ( isalpha((int) token[0]) || token[0] == '#' )
232 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000233 else
anthony805a2d42011-09-25 08:25:12 +0000234 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000235 }
anthony31f1bf72012-01-30 12:37:22 +0000236 /* control points and color values */
anthony7bcfe7f2012-03-30 14:01:22 +0000237 error = IsMagickTrue( x % (2+number_colors) );
anthony31f1bf72012-01-30 12:37:22 +0000238 number_arguments=x;
anthony7bcfe7f2012-03-30 14:01:22 +0000239 if ( IfMagickTrue(error) ) {
anthony805a2d42011-09-25 08:25:12 +0000240 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000241 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000242 "Invalid number of Arguments");
243 return( (Image *)NULL);
244 }
245
246 /* Allocate and fill in the floating point arguments */
247 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
248 sizeof(*sparse_arguments));
249 if (sparse_arguments == (double *) NULL) {
250 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
251 "MemoryAllocationFailed","%s","SparseColorOption");
252 return( (Image *)NULL);
253 }
254 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
255 sizeof(*sparse_arguments));
256 p=arguments;
257 x=0;
258 while( *p != '\0' && x < number_arguments ) {
259 /* X coordinate */
260 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
261 if ( token[0] == '\0' ) break;
262 if ( isalpha((int) token[0]) || token[0] == '#' ) {
263 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000264 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000265 "Color found, instead of X-coord");
266 error = MagickTrue;
267 break;
268 }
cristydbdd0e32011-11-04 23:29:40 +0000269 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000270 /* Y coordinate */
271 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
272 if ( token[0] == '\0' ) break;
273 if ( isalpha((int) token[0]) || token[0] == '#' ) {
274 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000275 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000276 "Color found, instead of Y-coord");
277 error = MagickTrue;
278 break;
279 }
cristydbdd0e32011-11-04 23:29:40 +0000280 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000281 /* color name or function given in string argument */
282 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
283 if ( token[0] == '\0' ) break;
284 if ( isalpha((int) token[0]) || token[0] == '#' ) {
285 /* Color string given */
286 (void) QueryColorCompliance(token,AllCompliance,&color,
287 exception);
288 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
289 sparse_arguments[x++] = QuantumScale*color.red;
290 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
291 sparse_arguments[x++] = QuantumScale*color.green;
292 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
293 sparse_arguments[x++] = QuantumScale*color.blue;
294 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
295 (image->colorspace == CMYKColorspace))
296 sparse_arguments[x++] = QuantumScale*color.black;
297 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy8a46d822012-08-28 23:32:39 +0000298 image->alpha_trait == BlendPixelTrait)
anthony31f1bf72012-01-30 12:37:22 +0000299 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000300 }
anthony31f1bf72012-01-30 12:37:22 +0000301 else {
302 /* Colors given as a set of floating point values - experimental */
303 /* NB: token contains the first floating point value to use! */
304 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
305 {
306 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
307 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
308 break;
309 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
310 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000311 }
anthony31f1bf72012-01-30 12:37:22 +0000312 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
313 {
314 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
315 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
316 break;
317 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
318 token[0] = ','; /* used this token - get another */
319 }
320 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
321 {
322 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324 break;
325 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
326 token[0] = ','; /* used this token - get another */
327 }
328 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
329 (image->colorspace == CMYKColorspace))
330 {
331 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
332 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
333 break;
334 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
335 token[0] = ','; /* used this token - get another */
336 }
337 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy8a46d822012-08-28 23:32:39 +0000338 image->alpha_trait == BlendPixelTrait)
anthony31f1bf72012-01-30 12:37:22 +0000339 {
340 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
341 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
342 break;
343 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
344 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000345 }
346 }
347 }
348 if ( number_arguments != x && !error ) {
349 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000350 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000351 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
352 return( (Image *)NULL);
353 }
354 if ( error )
355 return( (Image *)NULL);
356
anthony31f1bf72012-01-30 12:37:22 +0000357 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000358 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
359 exception);
360 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
361 return( sparse_image );
362}
363
364/*
365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366% %
367% %
368% %
anthony464f1c42012-04-22 08:51:01 +0000369% C L I S e t t i n g O p t i o n I n f o %
anthony43f425d2012-02-26 12:58:58 +0000370% %
371% %
372% %
373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374%
375% CLISettingOptionInfo() applies a single settings option into a CLI wand
376% holding the image_info, draw_info, quantize_info structures that will be
377% used when processing the images.
378%
379% These options do no require images to be present in the CLI wand for them
380% to be able to be set, in which case they will generally be applied to image
381% that are read in later
anthony80c37752012-01-16 01:03:11 +0000382%
383% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000384% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000385%
anthony2052d272012-02-28 12:48:29 +0000386% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000387%
anthonyafa3dfc2012-03-03 11:31:30 +0000388% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000389% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000390%
391% A description of each parameter follows:
392%
anthony43f425d2012-02-26 12:58:58 +0000393% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000394%
anthonydcf510d2011-10-30 13:51:40 +0000395% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000396%
anthonye5fcd362012-04-09 04:02:09 +0000397% o arg1, arg2: optional argument strings to the operation
398% arg2 is currently only used by "-limit"
anthonydcf510d2011-10-30 13:51:40 +0000399%
anthony805a2d42011-09-25 08:25:12 +0000400*/
cristyfe831852013-02-12 14:56:07 +0000401WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonya322a832013-04-27 06:28:03 +0000402 const char *option,const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +0000403{
anthony30b912a2012-03-22 01:20:28 +0000404 ssize_t
405 parse; /* option argument parsing (string to value table lookup) */
406
anthonya322a832013-04-27 06:28:03 +0000407 const char /* percent escaped versions of the args */
408 *arg1,
409 *arg2;
anthony1afdc7a2011-10-05 11:54:28 +0000410
anthony2e4501b2012-03-30 04:41:54 +0000411#define _image_info (cli_wand->wand.image_info)
anthonya322a832013-04-27 06:28:03 +0000412#define _image (cli_wand->wand.images)
anthony2e4501b2012-03-30 04:41:54 +0000413#define _exception (cli_wand->wand.exception)
414#define _draw_info (cli_wand->draw_info)
415#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000416#define IfSetOption (*option=='-')
anthony7bcfe7f2012-03-30 14:01:22 +0000417#define ArgBoolean IsMagickTrue(IfSetOption)
418#define ArgBooleanNot IsMagickFalse(IfSetOption)
anthony24aa8822012-03-11 00:56:06 +0000419#define ArgBooleanString (IfSetOption?"true":"false")
420#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000421
anthonya322a832013-04-27 06:28:03 +0000422 assert(cli_wand != (MagickCLI *) NULL);
423 assert(cli_wand->signature == WandSignature);
424 assert(cli_wand->wand.signature == WandSignature);
anthony4837ac22012-05-18 23:39:48 +0000425
anthonya322a832013-04-27 06:28:03 +0000426 if (IfMagickTrue(cli_wand->wand.debug))
427 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
428 "- Setting Option: %s \"%s\" \"%s\"", option,arg1n,arg2n);
429
430 arg1 = arg1n,
431 arg2 = arg2n;
432
433#if 1
anthony4837ac22012-05-18 23:39:48 +0000434#define _process_flags (cli_wand->process_flags)
435#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
436 /* Interpret Percent Escapes in Arguments - using first image */
anthony4837ac22012-05-18 23:39:48 +0000437 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
438 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
439 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
440 /* Interpret Percent escapes in argument 1 */
441 if (arg1n != (char *) NULL) {
442 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
443 if (arg1 == (char *) NULL) {
444 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
445 arg1=arg1n; /* use the given argument as is */
446 }
447 }
448 if (arg2n != (char *) NULL) {
449 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
450 if (arg2 == (char *) NULL) {
451 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
452 arg2=arg2n; /* use the given argument as is */
453 }
454 }
455 }
456#undef _process_flags
457#undef _option_type
458#endif
459
anthonyafa3dfc2012-03-03 11:31:30 +0000460 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000461 {
462 case 'a':
463 {
anthonyafa3dfc2012-03-03 11:31:30 +0000464 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000465 {
anthony92c93bd2012-03-19 14:02:47 +0000466 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000467 break;
468 }
anthonyafa3dfc2012-03-03 11:31:30 +0000469 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000470 {
anthony464f1c42012-04-22 08:51:01 +0000471 CLIWandWarnReplaced("-draw 'affine ...'");
anthony74b1cfc2011-10-06 12:44:16 +0000472 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000473 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000474 else
anthony92c93bd2012-03-19 14:02:47 +0000475 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000476 break;
477 }
anthonyafa3dfc2012-03-03 11:31:30 +0000478 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000479 {
anthony92c93bd2012-03-19 14:02:47 +0000480 _image_info->antialias =
481 _draw_info->stroke_antialias =
482 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000483 break;
484 }
anthony31f1bf72012-01-30 12:37:22 +0000485 if (LocaleCompare("attenuate",option+1) == 0)
486 {
anthony7bcfe7f2012-03-30 14:01:22 +0000487 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +0000488 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
489 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000490 break;
491 }
anthonyafa3dfc2012-03-03 11:31:30 +0000492 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000493 {
anthony92c93bd2012-03-19 14:02:47 +0000494 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000495 break;
496 }
anthonyebb73a22012-03-22 14:25:52 +0000497 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000498 }
499 case 'b':
500 {
anthonyafa3dfc2012-03-03 11:31:30 +0000501 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000502 {
anthony92c93bd2012-03-19 14:02:47 +0000503 /* FUTURE: both _image_info attribute & ImageOption in use!
504 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000505 SyncImageSettings() used to set per-image attribute.
506
anthony92c93bd2012-03-19 14:02:47 +0000507 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000508 we should fall back to per-image background_color
509
510 At this time -background will 'wipe out' the per-image
511 background color!
512
513 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000514 */
anthony92c93bd2012-03-19 14:02:47 +0000515 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000516 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000517 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000518 break;
519 }
anthonyafa3dfc2012-03-03 11:31:30 +0000520 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000521 {
anthony52bef752012-03-27 13:54:47 +0000522 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000523 as it is actually rarely used except in direct convolve operations
524 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000525
526 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000527 */
anthony7bcfe7f2012-03-30 14:01:22 +0000528 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000529 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000530 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000531 break;
532 }
anthonyafa3dfc2012-03-03 11:31:30 +0000533 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000534 {
anthony72feaa62012-01-17 06:46:23 +0000535 /* Used as a image chromaticity setting
536 SyncImageSettings() used to set per-image attribute.
537 */
anthony92c93bd2012-03-19 14:02:47 +0000538 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000539 break;
540 }
anthonyafa3dfc2012-03-03 11:31:30 +0000541 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000542 {
anthonyafbaed72011-10-26 12:05:04 +0000543 /* Image chromaticity X,Y NB: Y=X if Y not defined
544 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000545 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000546 */
anthonyf42014d2012-03-25 09:53:06 +0000547 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000548 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000549 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000550 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000551 break;
552 }
anthonyafa3dfc2012-03-03 11:31:30 +0000553 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000554 {
anthony92c93bd2012-03-19 14:02:47 +0000555 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000556 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000557 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000558 */
anthony74b1cfc2011-10-06 12:44:16 +0000559 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000560 {
anthony92c93bd2012-03-19 14:02:47 +0000561 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000562 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000563 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000564 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000565 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000566 break;
567 }
anthony92c93bd2012-03-19 14:02:47 +0000568 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000569 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000570 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000571 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000572 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000573 break;
574 }
anthonyafa3dfc2012-03-03 11:31:30 +0000575 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000576 {
anthony464f1c42012-04-22 08:51:01 +0000577 CLIWandWarnReplaced("-undercolor");
anthony975a8d72012-04-12 13:54:36 +0000578 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
anthonyfd706f92012-01-19 04:22:02 +0000579 break;
anthony805a2d42011-09-25 08:25:12 +0000580 }
anthonyebb73a22012-03-22 14:25:52 +0000581 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000582 }
583 case 'c':
584 {
anthonyafa3dfc2012-03-03 11:31:30 +0000585 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000586 {
587 MagickSizeType
588 limit;
589
anthony7bcfe7f2012-03-30 14:01:22 +0000590 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000591 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000592 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000593 if (LocaleCompare("unlimited",arg1) != 0)
594 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000595 (void) SetMagickResourceLimit(MemoryResource,limit);
596 (void) SetMagickResourceLimit(MapResource,2*limit);
597 break;
598 }
anthonyafa3dfc2012-03-03 11:31:30 +0000599 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000600 {
anthony92c93bd2012-03-19 14:02:47 +0000601 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000602 break;
603 }
anthonyafa3dfc2012-03-03 11:31:30 +0000604 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000605 {
anthony30b912a2012-03-22 01:20:28 +0000606 arg1=ArgOption("default");
607 parse=ParseChannelOption(arg1);
608 if (parse < 0)
609 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
610 option,arg1);
611 _image_info->channel=(ChannelType) parse;
612 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000613 break;
614 }
anthonyafa3dfc2012-03-03 11:31:30 +0000615 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000616 {
anthonyafbaed72011-10-26 12:05:04 +0000617 /* Setting used for new images via AquireImage()
618 But also used as a SimpleImageOperator
619 Undefined colorspace means don't modify images on
620 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000621 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
622 ArgOption("undefined"));
623 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000624 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
625 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000626 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000627 break;
628 }
anthonyafa3dfc2012-03-03 11:31:30 +0000629 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000630 {
anthony92c93bd2012-03-19 14:02:47 +0000631 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000632 break;
633 }
anthonyafa3dfc2012-03-03 11:31:30 +0000634 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000635 {
anthony92c93bd2012-03-19 14:02:47 +0000636 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000637 SyncImageSettings() used to set per-image attribute. - REMOVE
638
anthonyafbaed72011-10-26 12:05:04 +0000639 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000640 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000641 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000642 */
anthonyebb73a22012-03-22 14:25:52 +0000643 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
644 ArgOption("undefined"));
645 if (parse < 0)
646 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
647 option,arg1);
648 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000649 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000650 break;
651 }
anthonyafa3dfc2012-03-03 11:31:30 +0000652 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000653 {
anthony92c93bd2012-03-19 14:02:47 +0000654 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000655 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000656 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000657
anthony92c93bd2012-03-19 14:02:47 +0000658 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000659 however the image attribute (for save) is set from the
660 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000661
662 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000663 */
anthonyebb73a22012-03-22 14:25:52 +0000664 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
665 ArgOption("undefined"));
666 if (parse < 0)
667 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
668 option,arg1);
669 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000670 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000671 break;
672 }
anthonyebb73a22012-03-22 14:25:52 +0000673 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000674 }
675 case 'd':
676 {
anthonyafa3dfc2012-03-03 11:31:30 +0000677 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000678 {
anthony72feaa62012-01-17 06:46:23 +0000679 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000680 arg1=ArgOption("none");
681 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
682 if (parse < 0)
683 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
684 option,arg1);
685 (void) SetLogEventMask(arg1);
686 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000687 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000688 break;
689 }
anthonyafa3dfc2012-03-03 11:31:30 +0000690 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000691 {
anthony24aa8822012-03-11 00:56:06 +0000692 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000693 {
anthony5f867ae2011-10-09 10:28:34 +0000694 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000695 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000696 else
anthony24aa8822012-03-11 00:56:06 +0000697 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000698 break;
699 }
anthony24aa8822012-03-11 00:56:06 +0000700 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000701 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000702 (void) DefineImageOption(_image_info,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +0000703 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000704 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000705 break;
706 }
anthonyafa3dfc2012-03-03 11:31:30 +0000707 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000708 {
anthonyafbaed72011-10-26 12:05:04 +0000709 /* Only used for new images via AcquireImage()
710 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000711 */
anthonyebb73a22012-03-22 14:25:52 +0000712 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000713 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000714 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
715 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000716 break;
717 }
anthonyafa3dfc2012-03-03 11:31:30 +0000718 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000719 {
anthony92c93bd2012-03-19 14:02:47 +0000720 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000721 Basically as density can be in a XxY form!
722
723 SyncImageSettings() used to set per-image attribute.
724 */
anthony7bcfe7f2012-03-30 14:01:22 +0000725 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000726 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000727 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
728 (void) CloneString(&_image_info->density,ArgOption(NULL));
729 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000730 break;
731 }
anthonyafa3dfc2012-03-03 11:31:30 +0000732 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000733 {
anthony72feaa62012-01-17 06:46:23 +0000734 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
735 SyncImageSettings() used to set per-image attribute.
736 */
anthony7bcfe7f2012-03-30 14:01:22 +0000737 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000738 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000739 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000740 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000741 break;
742 }
anthonyafa3dfc2012-03-03 11:31:30 +0000743 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000744 {
anthony92c93bd2012-03-19 14:02:47 +0000745 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000746 arg1=ArgOption("undefined");
747 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
748 if (parse < 0)
749 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
750 option,arg1);
751 _draw_info->direction=(DirectionType) parse;
752 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000753 break;
754 }
anthonyafa3dfc2012-03-03 11:31:30 +0000755 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000756 {
anthony92c93bd2012-03-19 14:02:47 +0000757 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
758 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000759 break;
760 }
anthonyafa3dfc2012-03-03 11:31:30 +0000761 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000762 {
anthony72feaa62012-01-17 06:46:23 +0000763 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000764 arg1=ArgOption("undefined");
765 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
766 if (parse < 0)
767 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
768 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000769 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000770 break;
771 }
anthonyb1d483a2012-04-14 12:53:56 +0000772 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
773 {
774 /* FUTURE: this is only used by CompareImages() which is used
775 only by the "compare" CLI program at this time. */
776 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
777 if (IfMagickFalse(IsGeometry(arg1)))
778 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
779 (void) SetImageOption(_image_info,option+1,arg1);
780 break;
781 }
anthonyafa3dfc2012-03-03 11:31:30 +0000782 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000783 {
anthony92c93bd2012-03-19 14:02:47 +0000784 /* _image_info attr (on/off), _quantize_info attr (on/off)
785 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000786 FUTURE: merge the duality of the dithering options
787 */
cristycbda6112012-05-27 20:57:16 +0000788 _image_info->dither = ArgBoolean;
anthony92c93bd2012-03-19 14:02:47 +0000789 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
790 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
cristycbda6112012-05-27 20:57:16 +0000791 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000792 if (_quantize_info->dither_method == NoDitherMethod)
cristycbda6112012-05-27 20:57:16 +0000793 _image_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000794 break;
795 }
anthonyebb73a22012-03-22 14:25:52 +0000796 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000797 }
798 case 'e':
799 {
anthonyafa3dfc2012-03-03 11:31:30 +0000800 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000801 {
anthony92c93bd2012-03-19 14:02:47 +0000802 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
803 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000804 break;
805 }
anthonyafa3dfc2012-03-03 11:31:30 +0000806 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000807 {
anthony92c93bd2012-03-19 14:02:47 +0000808 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000809 arg1 = ArgOption("undefined");
810 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
811 if (parse < 0)
812 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
813 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000814 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000815 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000816 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000817 break;
818 }
anthonyafa3dfc2012-03-03 11:31:30 +0000819 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000820 {
anthony92c93bd2012-03-19 14:02:47 +0000821 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000822 break;
823 }
anthonyebb73a22012-03-22 14:25:52 +0000824 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000825 }
826 case 'f':
827 {
anthonyafa3dfc2012-03-03 11:31:30 +0000828 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000829 {
anthony92c93bd2012-03-19 14:02:47 +0000830 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000831 break;
832 }
anthonya322a832013-04-27 06:28:03 +0000833 if (LocaleCompare("features",option+1) == 0)
834 {
835 (void) SetImageOption(_image_info,"identify:features",
836 ArgBooleanString);
837 if (IfSetOption)
838 (void) SetImageArtifact(_image,"verbose","true");
839 break;
840 }
anthonyafa3dfc2012-03-03 11:31:30 +0000841 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000842 {
anthony92c93bd2012-03-19 14:02:47 +0000843 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000844 The original fill color is preserved if a fill-pattern is given.
845 That way it does not effect other operations that directly using
846 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000847 */
anthony72feaa62012-01-17 06:46:23 +0000848 MagickBooleanType
849 status;
anthony6dc09cd2011-10-12 08:56:49 +0000850
851 ExceptionInfo
852 *sans;
853
anthonyfd706f92012-01-19 04:22:02 +0000854 PixelInfo
855 color;
856
anthony2a0ec8c2012-03-24 04:35:56 +0000857 arg1 = ArgOption("none"); /* +fill turns it off! */
858 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000859 if (_draw_info->fill_pattern != (Image *) NULL)
860 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000861
862 /* is it a color or a image? -- ignore exceptions */
863 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +0000864 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000865 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000866
anthony7bcfe7f2012-03-30 14:01:22 +0000867 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +0000868 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000869 else
anthony92c93bd2012-03-19 14:02:47 +0000870 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000871 break;
872 }
anthonyafa3dfc2012-03-03 11:31:30 +0000873 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000874 {
anthony72feaa62012-01-17 06:46:23 +0000875 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +0000876 arg1 = ArgOption("undefined");
877 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
878 if (parse < 0)
879 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
880 option,arg1);
881 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000882 break;
883 }
anthonyafa3dfc2012-03-03 11:31:30 +0000884 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000885 {
anthony92c93bd2012-03-19 14:02:47 +0000886 (void) CloneString(&_draw_info->font,ArgOption(NULL));
887 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000888 break;
889 }
anthonyafa3dfc2012-03-03 11:31:30 +0000890 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000891 {
anthonydcf510d2011-10-30 13:51:40 +0000892 /* FUTURE: why the ping test, you could set ping after this! */
893 /*
anthony805a2d42011-09-25 08:25:12 +0000894 register const char
895 *q;
896
anthony24aa8822012-03-11 00:56:06 +0000897 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000898 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +0000899 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000900 */
anthony92c93bd2012-03-19 14:02:47 +0000901 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000902 break;
903 }
anthonyafa3dfc2012-03-03 11:31:30 +0000904 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000905 {
anthony72feaa62012-01-17 06:46:23 +0000906 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000907 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000908 SyncImageSettings() used to set per-image attribute.
909
anthony2a0ec8c2012-03-24 04:35:56 +0000910 FUTURE: Can't find anything else using _image_info->fuzz directly!
anthonya322a832013-04-27 06:28:03 +0000911 convert structure attribute to 'option' string
anthony6613bf32011-10-15 07:24:44 +0000912 */
anthony2a0ec8c2012-03-24 04:35:56 +0000913 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000914 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +0000915 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
916 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +0000917 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +0000918 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000919 break;
920 }
anthonyebb73a22012-03-22 14:25:52 +0000921 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000922 }
923 case 'g':
924 {
anthonyafa3dfc2012-03-03 11:31:30 +0000925 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000926 {
anthony72feaa62012-01-17 06:46:23 +0000927 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000928 arg1 = ArgOption("none");
929 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
930 if (parse < 0)
931 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
932 option,arg1);
anthonyfe1aa782012-03-24 13:43:04 +0000933 _draw_info->gravity=(GravityType) parse;
anthonye8490972012-04-03 13:16:01 +0000934 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000935 break;
936 }
anthonyafa3dfc2012-03-03 11:31:30 +0000937 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000938 {
anthonydcf510d2011-10-30 13:51:40 +0000939 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000940 SyncImageSettings() used to set per-image attribute.
941 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000942 */
anthonyf42014d2012-03-25 09:53:06 +0000943 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000944 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000945 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000946 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000947 break;
948 }
anthonyebb73a22012-03-22 14:25:52 +0000949 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000950 }
anthonyb1d483a2012-04-14 12:53:56 +0000951 case 'h':
952 {
953 if (LocaleCompare("highlight-color",option+1) == 0)
954 {
955 /* FUTURE: this is only used by CompareImages() which is used
956 only by the "compare" CLI program at this time. */
957 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
958 break;
959 }
960 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
961 }
anthony805a2d42011-09-25 08:25:12 +0000962 case 'i':
963 {
cristy70e9f682013-03-12 22:31:22 +0000964 if (LocaleCompare("intensity",option+1) == 0)
965 {
966 arg1 = ArgOption("undefined");
cristy8f84fdd2013-03-28 17:52:55 +0000967 parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,
968 arg1);
cristy70e9f682013-03-12 22:31:22 +0000969 if (parse < 0)
cristy8f84fdd2013-03-28 17:52:55 +0000970 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityType",
971 option,arg1);
cristy70e9f682013-03-12 22:31:22 +0000972 (void) SetImageOption(_image_info,option+1,arg1);
973 break;
974 }
anthonyafa3dfc2012-03-03 11:31:30 +0000975 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000976 {
anthony72feaa62012-01-17 06:46:23 +0000977 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000978 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000979 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000980 */
cristy70e9f682013-03-12 22:31:22 +0000981 arg1 = ArgOption("undefined");
anthonyfe1aa782012-03-24 13:43:04 +0000982 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
983 if (parse < 0)
984 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
985 option,arg1);
986 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000987 break;
988 }
anthonyafa3dfc2012-03-03 11:31:30 +0000989 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000990 {
anthony92c93bd2012-03-19 14:02:47 +0000991 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +0000992 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000993 */
anthonyfe1aa782012-03-24 13:43:04 +0000994 arg1 = ArgOption("undefined");
995 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
996 if (parse < 0)
997 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
998 option,arg1);
999 _image_info->interlace=(InterlaceType) parse;
1000 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001001 break;
1002 }
anthonyafa3dfc2012-03-03 11:31:30 +00001003 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001004 {
anthony7bcfe7f2012-03-30 14:01:22 +00001005 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001006 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001007 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1008 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001009 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001010 break;
1011 }
anthonyafa3dfc2012-03-03 11:31:30 +00001012 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001013 {
anthonyfd706f92012-01-19 04:22:02 +00001014 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001015 arg1 = ArgOption("undefined");
1016 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1017 if (parse < 0)
1018 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1019 option,arg1);
1020 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001021 break;
1022 }
anthonyafa3dfc2012-03-03 11:31:30 +00001023 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001024 {
anthony7bcfe7f2012-03-30 14:01:22 +00001025 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001026 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001027 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1028 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001029 break;
1030 }
anthonyebb73a22012-03-22 14:25:52 +00001031 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001032 }
1033 case 'k':
1034 {
anthonyafa3dfc2012-03-03 11:31:30 +00001035 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001036 {
anthony7bcfe7f2012-03-30 14:01:22 +00001037 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001038 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001039 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1040 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001041 break;
1042 }
anthonyebb73a22012-03-22 14:25:52 +00001043 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001044 }
1045 case 'l':
1046 {
anthonyafa3dfc2012-03-03 11:31:30 +00001047 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001048 {
anthony72feaa62012-01-17 06:46:23 +00001049 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001050 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001051 break;
1052 }
anthony756cd0d2012-04-08 12:41:44 +00001053 if (LocaleCompare("limit",option+1) == 0)
1054 {
1055 MagickSizeType
1056 limit;
1057
1058 limit=MagickResourceInfinity;
1059 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1060 if ( parse < 0 )
1061 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1062 option,arg1);
1063 if (LocaleCompare("unlimited",arg2) != 0)
1064 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1065 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1066 break;
1067 }
anthonyafa3dfc2012-03-03 11:31:30 +00001068 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001069 {
anthonyfe1aa782012-03-24 13:43:04 +00001070 if (IfSetOption) {
1071 if ((strchr(arg1,'%') == (char *) NULL))
1072 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001073 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001074 }
anthony805a2d42011-09-25 08:25:12 +00001075 break;
1076 }
anthony975a8d72012-04-12 13:54:36 +00001077 if (LocaleCompare("lowlight-color",option+1) == 0)
1078 {
anthonyb1d483a2012-04-14 12:53:56 +00001079 /* FUTURE: this is only used by CompareImages() which is used
1080 only by the "compare" CLI program at this time. */
anthony975a8d72012-04-12 13:54:36 +00001081 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1082 break;
1083 }
anthonyafa3dfc2012-03-03 11:31:30 +00001084 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001085 {
anthony72feaa62012-01-17 06:46:23 +00001086 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001087 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001088 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001089 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1090 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001091 break;
1092 }
anthonyebb73a22012-03-22 14:25:52 +00001093 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001094 }
1095 case 'm':
1096 {
anthonyafa3dfc2012-03-03 11:31:30 +00001097 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001098 {
anthony72feaa62012-01-17 06:46:23 +00001099 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001100 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001101 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001102 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001103 break;
anthonycd358fc2012-04-16 13:59:03 +00001104 }
anthonyb1d483a2012-04-14 12:53:56 +00001105 if (LocaleCompare("metric",option+1) == 0)
1106 {
1107 /* FUTURE: this is only used by CompareImages() which is used
1108 only by the "compare" CLI program at this time. */
1109 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1110 if ( parse < 0 )
1111 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1112 option,arg1);
1113 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthonycd358fc2012-04-16 13:59:03 +00001114 break;
anthony805a2d42011-09-25 08:25:12 +00001115 }
anthonyafa3dfc2012-03-03 11:31:30 +00001116 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001117 {
anthony92c93bd2012-03-19 14:02:47 +00001118 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001119 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001120 break;
1121 }
anthonyafa3dfc2012-03-03 11:31:30 +00001122 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001123 {
anthony24aa8822012-03-11 00:56:06 +00001124 /* Setting (used by some input coders!) -- why?
1125 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001126 */
anthony92c93bd2012-03-19 14:02:47 +00001127 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001128 break;
1129 }
anthonyebb73a22012-03-22 14:25:52 +00001130 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001131 }
1132 case 'o':
1133 {
anthonyafa3dfc2012-03-03 11:31:30 +00001134 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001135 {
anthony72feaa62012-01-17 06:46:23 +00001136 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001137 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001138 FUTURE: make set meta-data operator instead.
1139 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001140 */
anthony7bc87992012-03-25 02:32:51 +00001141 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1142 ArgOption("undefined"));
1143 if (parse < 0)
1144 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1145 option,arg1);
1146 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001147 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001148 break;
1149 }
anthonyebb73a22012-03-22 14:25:52 +00001150 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001151 }
1152 case 'p':
1153 {
anthonyafa3dfc2012-03-03 11:31:30 +00001154 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001155 {
anthony7bc87992012-03-25 02:32:51 +00001156 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001157 SyncImageSettings() used to set per-image attribute. ?????
1158 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001159 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001160 */
anthony805a2d42011-09-25 08:25:12 +00001161 char
1162 *canonical_page,
1163 page[MaxTextExtent];
1164
1165 const char
1166 *image_option;
1167
1168 MagickStatusType
1169 flags;
1170
1171 RectangleInfo
1172 geometry;
1173
anthonydcf510d2011-10-30 13:51:40 +00001174 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001175 {
anthony92c93bd2012-03-19 14:02:47 +00001176 (void) DeleteImageOption(_image_info,option+1);
1177 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001178 break;
1179 }
1180 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001181 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001182 if (image_option != (const char *) NULL)
1183 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001184 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001185 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1186 canonical_page=DestroyString(canonical_page);
1187 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1188 (unsigned long) geometry.width,(unsigned long) geometry.height);
1189 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1190 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1191 (unsigned long) geometry.width,(unsigned long) geometry.height,
1192 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001193 (void) SetImageOption(_image_info,option+1,page);
1194 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001195 break;
1196 }
anthonyafa3dfc2012-03-03 11:31:30 +00001197 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001198 {
anthony92c93bd2012-03-19 14:02:47 +00001199 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001200 break;
1201 }
anthonyafa3dfc2012-03-03 11:31:30 +00001202 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001203 {
anthonyf42014d2012-03-25 09:53:06 +00001204 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001205 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001206 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1207 _image_info->pointsize =
1208 _draw_info->pointsize =
1209 StringToDouble(arg1,(char **) NULL);
1210 }
1211 else {
1212 _image_info->pointsize=0.0; /* unset pointsize */
1213 _draw_info->pointsize=12.0;
1214 }
anthony805a2d42011-09-25 08:25:12 +00001215 break;
1216 }
anthonyafa3dfc2012-03-03 11:31:30 +00001217 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001218 {
anthonyf42014d2012-03-25 09:53:06 +00001219 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001220 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001221 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1222 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001223 break;
1224 }
anthonydcf510d2011-10-30 13:51:40 +00001225 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001226 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001227 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001228 {
anthony92c93bd2012-03-19 14:02:47 +00001229 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001230 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001231 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001232 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001233 break;
1234 }
anthonydcf510d2011-10-30 13:51:40 +00001235 */
anthonyebb73a22012-03-22 14:25:52 +00001236 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001237 }
1238 case 'q':
1239 {
anthonyafa3dfc2012-03-03 11:31:30 +00001240 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001241 {
anthony7bcfe7f2012-03-30 14:01:22 +00001242 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001243 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001244 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1245 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001246 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001247 break;
1248 }
anthonyafa3dfc2012-03-03 11:31:30 +00001249 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001250 {
anthony92c93bd2012-03-19 14:02:47 +00001251 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001252 arg1=ArgOption("undefined");
1253 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1254 if (parse < 0)
1255 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1256 option,arg1);
1257 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001258 break;
1259 }
anthonyafa3dfc2012-03-03 11:31:30 +00001260 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001261 {
anthonyf42014d2012-03-25 09:53:06 +00001262 /* FUTURE: if two -quiet is performed you can not do +quiet!
1263 This needs to be checked over thoughly.
1264 */
anthony805a2d42011-09-25 08:25:12 +00001265 static WarningHandler
1266 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001267
anthonyafbaed72011-10-26 12:05:04 +00001268 WarningHandler
1269 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001270
anthonyafbaed72011-10-26 12:05:04 +00001271 if ( tmp != (WarningHandler) NULL)
1272 warning_handler = tmp; /* remember the old handler */
1273 if (!IfSetOption) /* set the old handler */
1274 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001275 break;
1276 }
anthonyebb73a22012-03-22 14:25:52 +00001277 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001278 }
1279 case 'r':
1280 {
anthonyafa3dfc2012-03-03 11:31:30 +00001281 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001282 {
anthonydcf510d2011-10-30 13:51:40 +00001283 /* Image chromaticity X,Y NB: Y=X if Y not defined
1284 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001285 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001286 */
anthonyf42014d2012-03-25 09:53:06 +00001287 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001288 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001289 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001290 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001291 break;
1292 }
cristyb0f7a182012-04-06 23:33:11 +00001293 if (LocaleCompare("regard-warnings",option+1) == 0)
anthonye5fcd362012-04-09 04:02:09 +00001294 /* FUTURE: to be replaced by a 'fatal-level' type setting */
cristyb0f7a182012-04-06 23:33:11 +00001295 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001296 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001297 {
anthony92c93bd2012-03-19 14:02:47 +00001298 /* _draw_info only setting */
1299 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001300 break;
1301 }
anthony756cd0d2012-04-08 12:41:44 +00001302 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1303 {
1304 /* link image and setting stacks - option is itself saved on stack! */
1305 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1306 break;
1307 }
anthonyebb73a22012-03-22 14:25:52 +00001308 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001309 }
1310 case 's':
1311 {
anthonyafa3dfc2012-03-03 11:31:30 +00001312 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001313 {
anthonyafbaed72011-10-26 12:05:04 +00001314 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001315 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001316 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001317 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001318 break;
1319 }
anthonyafa3dfc2012-03-03 11:31:30 +00001320 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001321 {
anthonyf42014d2012-03-25 09:53:06 +00001322 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001323 What ??? Why ????
1324 */
anthony7bcfe7f2012-03-30 14:01:22 +00001325 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001326 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001327 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1328 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001329 break;
1330 }
anthonyafa3dfc2012-03-03 11:31:30 +00001331 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001332 {
anthony7bcfe7f2012-03-30 14:01:22 +00001333 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001334 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyd7761bb2012-04-14 01:42:05 +00001335 SetRandomSecretKey(
cristya30f8e62013-02-19 15:03:45 +00001336 IfSetOption ? (unsigned long) StringToUnsignedLong(arg1)
1337 : (unsigned long) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001338 break;
1339 }
anthonyafa3dfc2012-03-03 11:31:30 +00001340 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001341 {
anthony92c93bd2012-03-19 14:02:47 +00001342 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001343 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001344 */
anthony92c93bd2012-03-19 14:02:47 +00001345 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001346 break;
1347 }
anthonyafa3dfc2012-03-03 11:31:30 +00001348 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001349 {
anthonyf42014d2012-03-25 09:53:06 +00001350 arg1=ArgOption("undefined");
1351 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1352 if (parse < 0)
1353 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1354 option,arg1);
1355 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001356 break;
1357 }
anthonyafa3dfc2012-03-03 11:31:30 +00001358 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001359 {
anthonyafbaed72011-10-26 12:05:04 +00001360 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001361 UPDATE: ensure stroke color is not destroyed is a pattern
1362 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001363 */
anthony72feaa62012-01-17 06:46:23 +00001364 MagickBooleanType
1365 status;
anthonyafbaed72011-10-26 12:05:04 +00001366
1367 ExceptionInfo
1368 *sans;
1369
anthonyfd706f92012-01-19 04:22:02 +00001370 PixelInfo
1371 color;
1372
anthony2a0ec8c2012-03-24 04:35:56 +00001373 arg1 = ArgOption("none"); /* +fill turns it off! */
1374 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001375 if (_draw_info->stroke_pattern != (Image *) NULL)
1376 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001377
1378 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001379 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001380 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001381 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001382
anthony7bcfe7f2012-03-30 14:01:22 +00001383 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001384 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001385 else
anthony92c93bd2012-03-19 14:02:47 +00001386 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001387 break;
1388 }
anthonyafa3dfc2012-03-03 11:31:30 +00001389 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001390 {
anthony7bcfe7f2012-03-30 14:01:22 +00001391 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001392 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001393 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1394 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001395 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001396 break;
1397 }
anthonyafa3dfc2012-03-03 11:31:30 +00001398 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001399 {
anthonyf42014d2012-03-25 09:53:06 +00001400 arg1=ArgOption("undefined");
1401 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1402 if (parse < 0)
1403 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1404 option,arg1);
1405 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001406 break;
1407 }
anthonycd358fc2012-04-16 13:59:03 +00001408#if 0
anthonyb1d483a2012-04-14 12:53:56 +00001409 if (LocaleCompare("subimage-search",option+1) == 0)
1410 {
1411 /* FUTURE: this is only used by CompareImages() which is used
1412 only by the "compare" CLI program at this time. */
1413 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1414 break;
1415 }
anthonycd358fc2012-04-16 13:59:03 +00001416#endif
anthonyafa3dfc2012-03-03 11:31:30 +00001417 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001418 {
anthonyf42014d2012-03-25 09:53:06 +00001419 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001420 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001421 break;
1422 }
anthonyebb73a22012-03-22 14:25:52 +00001423 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001424 }
1425 case 't':
1426 {
anthonyafa3dfc2012-03-03 11:31:30 +00001427 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001428 {
anthony72feaa62012-01-17 06:46:23 +00001429 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001430 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001431 break;
1432 }
anthonyafa3dfc2012-03-03 11:31:30 +00001433 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001434 {
anthony4837ac22012-05-18 23:39:48 +00001435 /* Note: arguments do not have percent escapes expanded */
anthony52bef752012-03-27 13:54:47 +00001436 /* FUTURE: move _image_info string to option splay-tree
1437 Other than "montage" what uses "texture" ????
1438 */
anthony92c93bd2012-03-19 14:02:47 +00001439 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001440 break;
1441 }
anthonyafa3dfc2012-03-03 11:31:30 +00001442 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001443 {
anthony4837ac22012-05-18 23:39:48 +00001444 /* Note: arguments do not have percent escapes expanded */
anthony92c93bd2012-03-19 14:02:47 +00001445 _draw_info->fill_pattern=IfSetOption
1446 ?GetImageCache(_image_info,arg1,_exception)
1447 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001448 break;
1449 }
anthonyafa3dfc2012-03-03 11:31:30 +00001450 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001451 {
anthony72feaa62012-01-17 06:46:23 +00001452 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001453 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001454 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001455 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1456 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001457 break;
1458 }
anthonyafa3dfc2012-03-03 11:31:30 +00001459 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001460 {
anthony92c93bd2012-03-19 14:02:47 +00001461 /* FUTURE: both _image_info attribute & ImageOption in use!
1462 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001463 SyncImageSettings() used to set per-image attribute.
1464
anthonyafbaed72011-10-26 12:05:04 +00001465 Note that +transparent-color, means fall-back to image
1466 attribute so ImageOption is deleted, not set to a default.
1467 */
anthony7bcfe7f2012-03-30 14:01:22 +00001468 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001469 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001470 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001471 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001472 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001473 break;
1474 }
anthonyafa3dfc2012-03-03 11:31:30 +00001475 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001476 {
anthony92c93bd2012-03-19 14:02:47 +00001477 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1478 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001479 break;
1480 }
anthonyafa3dfc2012-03-03 11:31:30 +00001481 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001482 {
anthony72feaa62012-01-17 06:46:23 +00001483 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001484 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1485 ArgOption("undefined"));
1486 if (parse < 0)
1487 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1488 option,arg1);
1489 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001490 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001491 break;
1492 }
anthonyebb73a22012-03-22 14:25:52 +00001493 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001494 }
1495 case 'u':
1496 {
anthonyafa3dfc2012-03-03 11:31:30 +00001497 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001498 {
anthony92c93bd2012-03-19 14:02:47 +00001499 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001500 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001501 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001502 break;
1503 }
anthonyafa3dfc2012-03-03 11:31:30 +00001504 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001505 {
anthony72feaa62012-01-17 06:46:23 +00001506 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001507 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001508 FUTURE: this probably should be part of the density setting
1509 */
anthony52bef752012-03-27 13:54:47 +00001510 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1511 ArgOption("undefined"));
1512 if (parse < 0)
1513 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1514 option,arg1);
1515 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001516 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001517 break;
1518 }
anthonyebb73a22012-03-22 14:25:52 +00001519 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001520 }
1521 case 'v':
1522 {
anthonyafa3dfc2012-03-03 11:31:30 +00001523 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001524 {
anthony24aa8822012-03-11 00:56:06 +00001525 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001526 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001527 */
anthony92c93bd2012-03-19 14:02:47 +00001528 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1529 _image_info->verbose= ArgBoolean;
1530 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001531 break;
1532 }
anthonyafa3dfc2012-03-03 11:31:30 +00001533 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001534 {
anthony92c93bd2012-03-19 14:02:47 +00001535 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001536 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001537 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001538 */
anthony92c93bd2012-03-19 14:02:47 +00001539 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001540 break;
1541 }
anthonyafa3dfc2012-03-03 11:31:30 +00001542 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001543 {
anthonyfd706f92012-01-19 04:22:02 +00001544 /* SyncImageSettings() used to set per-image attribute.
1545 This is VERY deep in the image caching structure.
1546 */
anthony52bef752012-03-27 13:54:47 +00001547 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1548 ArgOption("undefined"));
1549 if (parse < 0)
1550 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1551 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001552 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001553 break;
1554 }
anthonyebb73a22012-03-22 14:25:52 +00001555 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001556 }
1557 case 'w':
1558 {
anthonyafa3dfc2012-03-03 11:31:30 +00001559 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001560 {
anthony72feaa62012-01-17 06:46:23 +00001561 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001562 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001563 */
anthony52bef752012-03-27 13:54:47 +00001564 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001565 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001566 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001567 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001568 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001569 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001570 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001571 if (_draw_info->weight <= 800)
1572 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001573 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001574 if (_draw_info->weight >= 100)
1575 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001576 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001577 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001578 break;
1579 }
anthonyafa3dfc2012-03-03 11:31:30 +00001580 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001581 {
anthony72feaa62012-01-17 06:46:23 +00001582 /* Used as a image chromaticity setting
1583 SyncImageSettings() used to set per-image attribute.
1584 */
anthony52bef752012-03-27 13:54:47 +00001585 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001586 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1588 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001589 break;
1590 }
anthonyebb73a22012-03-22 14:25:52 +00001591 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001592 }
1593 default:
anthonyebb73a22012-03-22 14:25:52 +00001594 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001595 }
anthony24aa8822012-03-11 00:56:06 +00001596
anthony4837ac22012-05-18 23:39:48 +00001597 /* clean up percent escape interpreted strings */
1598 if (arg1 != arg1n )
1599 arg1=DestroyString((char *)arg1);
1600 if (arg2 != arg2n )
1601 arg2=DestroyString((char *)arg2);
anthony4837ac22012-05-18 23:39:48 +00001602
anthony92c93bd2012-03-19 14:02:47 +00001603#undef _image_info
1604#undef _exception
1605#undef _draw_info
1606#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001607#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001608#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001609#undef ArgBooleanNot
1610#undef ArgBooleanString
1611#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001612
anthony31f1bf72012-01-30 12:37:22 +00001613 return;
anthony805a2d42011-09-25 08:25:12 +00001614}
1615
1616/*
1617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1618% %
1619% %
1620% %
anthony43f425d2012-02-26 12:58:58 +00001621+ C L I S i m p l e O p e r a t o r I m a g e s %
anthony805a2d42011-09-25 08:25:12 +00001622% %
1623% %
1624% %
1625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1626%
anthonyc7994672012-11-17 05:33:27 +00001627% CLISimpleOperatorImages() applys one simple image operation given to all
1628% the images in the CLI wand, using any per-image or global settings that was
1629% previously saved in the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001630%
anthonyc7994672012-11-17 05:33:27 +00001631% It is assumed that any such settings are up-to-date.
anthony805a2d42011-09-25 08:25:12 +00001632%
anthony7a4d6102012-07-01 09:48:25 +00001633% The format of the WandSimpleOperatorImages method is:
anthony805a2d42011-09-25 08:25:12 +00001634%
anthony43f425d2012-02-26 12:58:58 +00001635% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001636% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001637%
1638% A description of each parameter follows:
1639%
anthony43f425d2012-02-26 12:58:58 +00001640% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001641%
anthonyfd706f92012-01-19 04:22:02 +00001642% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001643%
anthonyfd706f92012-01-19 04:22:02 +00001644% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001645%
anthony805a2d42011-09-25 08:25:12 +00001646*/
anthony31f1bf72012-01-30 12:37:22 +00001647
1648/*
anthonyc7994672012-11-17 05:33:27 +00001649 CLISimpleOperatorImage() is an Internal subrountine to apply one simple
1650 image operation to the current image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001651
1652 The image in the list may be modified in three different ways...
1653 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1654 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1655 * one image replace by a list of images (-separate and -crop only!)
1656
anthonyafa3dfc2012-03-03 11:31:30 +00001657 In each case the result replaces the single original image in the list, as
1658 well as the pointer to the modified image (last image added if replaced by a
1659 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001660
1661 As the image pointed to may be replaced, the first image in the list may
1662 also change. GetFirstImageInList() should be used by caller if they wish
1663 return the Image pointer to the first image in list.
1664*/
cristyfe831852013-02-12 14:56:07 +00001665static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
anthony964d28e2012-05-17 23:39:46 +00001666 const char *option, const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00001667{
1668 Image *
1669 new_image;
1670
anthony805a2d42011-09-25 08:25:12 +00001671 GeometryInfo
1672 geometry_info;
1673
1674 RectangleInfo
1675 geometry;
1676
1677 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001678 flags;
1679
anthony92c93bd2012-03-19 14:02:47 +00001680 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001681 parse;
anthony92c93bd2012-03-19 14:02:47 +00001682
anthonya322a832013-04-27 06:28:03 +00001683 const char /* percent escaped versions of the args */
anthony964d28e2012-05-17 23:39:46 +00001684 *arg1,
1685 *arg2;
1686
anthonya322a832013-04-27 06:28:03 +00001687#define _image_info (cli_wand->wand.image_info)
1688#define _image (cli_wand->wand.images)
1689#define _exception (cli_wand->wand.exception)
1690#define _draw_info (cli_wand->draw_info)
1691#define _quantize_info (cli_wand->quantize_info)
1692#define _process_flags (cli_wand->process_flags)
1693#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
1694#define IfNormalOp (*option=='-')
1695#define IfPlusOp (*option!='-')
1696#define IsNormalOp IsMagickTrue(IfNormalOp)
1697#define IsPlusOp IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001698
anthony43f425d2012-02-26 12:58:58 +00001699 assert(cli_wand != (MagickCLI *) NULL);
1700 assert(cli_wand->signature == WandSignature);
1701 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001702 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001703 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001704 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001705
anthony964d28e2012-05-17 23:39:46 +00001706 arg1 = arg1n,
1707 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00001708
1709 /* Interpret Percent Escapes in Arguments - using first image */
anthony964d28e2012-05-17 23:39:46 +00001710 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1711 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1712 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1713 /* Interpret Percent escapes in argument 1 */
1714 if (arg1n != (char *) NULL) {
1715 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1716 if (arg1 == (char *) NULL) {
1717 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1718 arg1=arg1n; /* use the given argument as is */
1719 }
1720 }
1721 if (arg2n != (char *) NULL) {
1722 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1723 if (arg2 == (char *) NULL) {
1724 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1725 arg2=arg2n; /* use the given argument as is */
1726 }
1727 }
1728 }
anthony4837ac22012-05-18 23:39:48 +00001729#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00001730#undef _option_type
1731
1732#if 0
1733 (void) FormatLocaleFile(stderr,
1734 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1735#endif
anthony805a2d42011-09-25 08:25:12 +00001736
anthony5330ae02012-03-20 14:17:01 +00001737 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony964d28e2012-05-17 23:39:46 +00001738 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001739
anthonyafa3dfc2012-03-03 11:31:30 +00001740 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001741 {
1742 case 'a':
1743 {
anthonyafa3dfc2012-03-03 11:31:30 +00001744 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001745 {
anthonyfd706f92012-01-19 04:22:02 +00001746 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001747 if ((flags & (RhoValue|SigmaValue)) == 0)
1748 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001749 if ((flags & SigmaValue) == 0)
1750 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001751 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001752 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001753 break;
1754 }
anthonyafa3dfc2012-03-03 11:31:30 +00001755 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001756 {
anthonyfe1aa782012-03-24 13:43:04 +00001757 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001758 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001759 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1760 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1761 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001762 _exception);
anthony805a2d42011-09-25 08:25:12 +00001763 break;
1764 }
anthonyafa3dfc2012-03-03 11:31:30 +00001765 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001766 {
anthonyfd706f92012-01-19 04:22:02 +00001767 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001768 if ((flags & (RhoValue|SigmaValue)) == 0)
1769 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001770 if ((flags & SigmaValue) == 0)
1771 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001772 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001773 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001774 break;
1775 }
anthonyafa3dfc2012-03-03 11:31:30 +00001776 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001777 {
cristy288a3532012-08-28 00:19:44 +00001778 parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001779 if (parse < 0)
cristyb15b06c2012-08-28 11:36:48 +00001780 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
anthony92c93bd2012-03-19 14:02:47 +00001781 option,arg1);
cristyb15b06c2012-08-28 11:36:48 +00001782 (void) SetImageAlphaChannel(_image,(AlphaChannelOption)parse,
anthony2a0ec8c2012-03-24 04:35:56 +00001783 _exception);
anthony805a2d42011-09-25 08:25:12 +00001784 break;
1785 }
anthonyafa3dfc2012-03-03 11:31:30 +00001786 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001787 {
1788 char
anthony805a2d42011-09-25 08:25:12 +00001789 geometry[MaxTextExtent];
1790
anthony805a2d42011-09-25 08:25:12 +00001791 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001792 flags=ParseGeometry(arg1,&geometry_info);
cristy8592b052013-02-07 01:24:54 +00001793 if (flags == 0)
anthony22de2722012-04-19 14:43:00 +00001794 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001795 if ((flags & SigmaValue) == 0)
1796 geometry_info.sigma=geometry_info.rho;
anthony964d28e2012-05-17 23:39:46 +00001797 (void) CloneString(&_draw_info->text,arg2);
anthony805a2d42011-09-25 08:25:12 +00001798 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1799 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001800 (void) CloneString(&_draw_info->geometry,geometry);
1801 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001802 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001803 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001804 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001805 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001806 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001807 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001808 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001809 (void) AnnotateImage(_image,_draw_info,_exception);
1810 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001811 break;
1812 }
anthonyafa3dfc2012-03-03 11:31:30 +00001813 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001814 {
anthony92c93bd2012-03-19 14:02:47 +00001815 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001816 break;
1817 }
anthonyafa3dfc2012-03-03 11:31:30 +00001818 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001819 {
anthony92c93bd2012-03-19 14:02:47 +00001820 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001821 break;
1822 }
anthonyafa3dfc2012-03-03 11:31:30 +00001823 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001824 {
cristyfa5f6c72013-01-01 14:37:35 +00001825 new_image=AutoOrientImage(_image,_image->orientation,_exception);
anthony805a2d42011-09-25 08:25:12 +00001826 break;
1827 }
anthonyebb73a22012-03-22 14:25:52 +00001828 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001829 }
1830 case 'b':
1831 {
anthonyafa3dfc2012-03-03 11:31:30 +00001832 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001833 {
anthony7bcfe7f2012-03-30 14:01:22 +00001834 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001835 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001836 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001837 break;
1838 }
anthonyafa3dfc2012-03-03 11:31:30 +00001839 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001840 {
anthony805a2d42011-09-25 08:25:12 +00001841 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001842 if (IfNormalOp) {
anthonyfd706f92012-01-19 04:22:02 +00001843 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001844 if ((flags & RhoValue) == 0)
1845 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony5330ae02012-03-20 14:17:01 +00001846 }
anthony92c93bd2012-03-19 14:02:47 +00001847 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001848 break;
1849 }
anthonyafa3dfc2012-03-03 11:31:30 +00001850 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001851 {
anthonyfd706f92012-01-19 04:22:02 +00001852 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001853 if ((flags & (RhoValue|SigmaValue)) == 0)
1854 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001855 if ((flags & SigmaValue) == 0)
1856 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001857 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1858 _exception);
anthony805a2d42011-09-25 08:25:12 +00001859 break;
1860 }
anthonyafa3dfc2012-03-03 11:31:30 +00001861 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001862 {
anthony31f1bf72012-01-30 12:37:22 +00001863 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001864 compose;
1865
1866 const char*
anthony5f867ae2011-10-09 10:28:34 +00001867 value;
1868
anthony22de2722012-04-19 14:43:00 +00001869 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
cristy64ad8f92012-08-03 00:58:24 +00001870 if ((flags & (WidthValue | HeightValue)) == 0)
anthony5330ae02012-03-20 14:17:01 +00001871 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy64ad8f92012-08-03 00:58:24 +00001872 compose=OverCompositeOp;
anthony92c93bd2012-03-19 14:02:47 +00001873 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001874 if (value != (const char *) NULL)
cristy64ad8f92012-08-03 00:58:24 +00001875 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
1876 MagickFalse,value);
anthony92c93bd2012-03-19 14:02:47 +00001877 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001878 break;
1879 }
anthonyafa3dfc2012-03-03 11:31:30 +00001880 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001881 {
1882 double
1883 brightness,
1884 contrast;
1885
1886 GeometryInfo
1887 geometry_info;
1888
1889 MagickStatusType
1890 flags;
1891
anthonyfd706f92012-01-19 04:22:02 +00001892 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001893 if ((flags & RhoValue) == 0)
1894 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001895 brightness=geometry_info.rho;
1896 contrast=0.0;
1897 if ((flags & SigmaValue) != 0)
1898 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001899 (void) BrightnessContrastImage(_image,brightness,contrast,
1900 _exception);
anthony805a2d42011-09-25 08:25:12 +00001901 break;
1902 }
anthonyebb73a22012-03-22 14:25:52 +00001903 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001904 }
1905 case 'c':
1906 {
anthonyafa3dfc2012-03-03 11:31:30 +00001907 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001908 {
anthony4837ac22012-05-18 23:39:48 +00001909 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001910 char
1911 *color_correction_collection;
1912
1913 /*
1914 Color correct with a color decision list.
1915 */
anthony92c93bd2012-03-19 14:02:47 +00001916 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001917 if (color_correction_collection == (char *) NULL)
1918 break;
anthony92c93bd2012-03-19 14:02:47 +00001919 (void) ColorDecisionListImage(_image,color_correction_collection,
1920 _exception);
anthony805a2d42011-09-25 08:25:12 +00001921 break;
1922 }
anthonyafa3dfc2012-03-03 11:31:30 +00001923 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001924 {
anthonyfd706f92012-01-19 04:22:02 +00001925 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001926 if ((flags & (RhoValue|SigmaValue)) == 0)
1927 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001928 if ((flags & SigmaValue) == 0)
1929 geometry_info.sigma=1.0;
1930 if ((flags & XiValue) == 0)
1931 geometry_info.xi=1.0;
cristyee3f7522012-12-21 19:27:44 +00001932 new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
1933 _exception);
anthony805a2d42011-09-25 08:25:12 +00001934 break;
1935 }
anthonyafa3dfc2012-03-03 11:31:30 +00001936 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001937 {
anthony7bcfe7f2012-03-30 14:01:22 +00001938 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001939 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001940 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1941 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001942 break;
1943 }
anthonyafa3dfc2012-03-03 11:31:30 +00001944 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001945 {
anthony92c93bd2012-03-19 14:02:47 +00001946 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001947 break;
1948 }
anthonyafa3dfc2012-03-03 11:31:30 +00001949 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001950 {
anthonyafa3dfc2012-03-03 11:31:30 +00001951 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001952 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001953 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001954 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001955 break;
1956 }
anthonyafa3dfc2012-03-03 11:31:30 +00001957 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001958 {
anthony4837ac22012-05-18 23:39:48 +00001959 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001960 CacheView
1961 *mask_view;
1962
1963 Image
1964 *mask_image;
1965
1966 register Quantum
1967 *restrict q;
1968
1969 register ssize_t
1970 x;
1971
1972 ssize_t
1973 y;
1974
anthonyafa3dfc2012-03-03 11:31:30 +00001975 if (IfPlusOp) {
anthony4837ac22012-05-18 23:39:48 +00001976 /* use "+clip-mask" Remove the write mask for -clip-path */
anthony92c93bd2012-03-19 14:02:47 +00001977 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00001978 break;
1979 }
anthony92c93bd2012-03-19 14:02:47 +00001980 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001981 if (mask_image == (Image *) NULL)
1982 break;
anthony7bcfe7f2012-03-30 14:01:22 +00001983 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00001984 break;
anthony5330ae02012-03-20 14:17:01 +00001985 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00001986 /* FUTURE: use Alpha operations instead and create a Grey Image */
cristy46ff2672012-12-14 15:32:26 +00001987 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001988 for (y=0; y < (ssize_t) mask_image->rows; y++)
1989 {
1990 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00001991 _exception);
anthony805a2d42011-09-25 08:25:12 +00001992 if (q == (Quantum *) NULL)
1993 break;
1994 for (x=0; x < (ssize_t) mask_image->columns; x++)
1995 {
cristydc2d3272013-02-12 14:00:44 +00001996 if (mask_image->alpha_trait != BlendPixelTrait)
anthony805a2d42011-09-25 08:25:12 +00001997 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
cristy81ac7972013-03-31 19:25:23 +00001998 SetPixelGray(mask_image,GetPixelAlpha(mask_image,q),q);
anthony805a2d42011-09-25 08:25:12 +00001999 q+=GetPixelChannels(mask_image);
2000 }
anthony7bcfe7f2012-03-30 14:01:22 +00002001 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00002002 break;
2003 }
anthonyfd706f92012-01-19 04:22:02 +00002004 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002005 mask_view=DestroyCacheView(mask_view);
cristy8a46d822012-08-28 23:32:39 +00002006 mask_image->alpha_trait=BlendPixelTrait;
cristy81ac7972013-03-31 19:25:23 +00002007 (void) SetImageColorspace(_image,GRAYColorspace,_exception);
anthony92c93bd2012-03-19 14:02:47 +00002008 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002009 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002010 break;
2011 }
anthonyafa3dfc2012-03-03 11:31:30 +00002012 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002013 {
anthonya322a832013-04-27 06:28:03 +00002014 (void) ClipImagePath(_image,arg1,IsNormalOp,_exception);
anthony4837ac22012-05-18 23:39:48 +00002015 /* Note: Use "+clip-mask" remove the write mask added */
anthony805a2d42011-09-25 08:25:12 +00002016 break;
2017 }
anthonyafa3dfc2012-03-03 11:31:30 +00002018 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002019 {
anthony7bcfe7f2012-03-30 14:01:22 +00002020 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002021 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002022 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002023 break;
2024 }
anthonyafa3dfc2012-03-03 11:31:30 +00002025 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002026 {
2027 KernelInfo
2028 *kernel;
2029
anthonyfd706f92012-01-19 04:22:02 +00002030 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002031 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002032 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002033 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002034 kernel=DestroyKernelInfo(kernel);
2035 break;
2036 }
anthonyafa3dfc2012-03-03 11:31:30 +00002037 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002038 {
anthony5330ae02012-03-20 14:17:01 +00002039 /* Reduce the number of colors in the image.
2040 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002041 */
anthony92c93bd2012-03-19 14:02:47 +00002042 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2043 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002044 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002045 if ((_image->storage_class == DirectClass) ||
2046 _image->colors > _quantize_info->number_colors)
2047 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002048 else
anthony92c93bd2012-03-19 14:02:47 +00002049 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002050 break;
2051 }
anthonyafa3dfc2012-03-03 11:31:30 +00002052 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002053 {
anthony5330ae02012-03-20 14:17:01 +00002054 /* WARNING: this is both a image_info setting (already done)
2055 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002056
2057 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002058 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002059
anthonyd2cdc862011-10-07 14:07:17 +00002060 Note that +colorspace sets "undefined" or no effect on
2061 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002062 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002063 */
anthony92c93bd2012-03-19 14:02:47 +00002064 (void) TransformImageColorspace(_image,
cristye0b9b8f2013-03-28 12:39:39 +00002065 IfNormalOp ? _image_info->colorspace : sRGBColorspace,
anthony92c93bd2012-03-19 14:02:47 +00002066 _exception);
anthony805a2d42011-09-25 08:25:12 +00002067 break;
2068 }
anthonyafa3dfc2012-03-03 11:31:30 +00002069 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002070 {
anthonya322a832013-04-27 06:28:03 +00002071 CLIWandWarnReplaced(IfNormalOp?"-level":"+level");
2072 (void) ContrastImage(_image,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002073 break;
2074 }
anthonyafa3dfc2012-03-03 11:31:30 +00002075 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002076 {
2077 double
2078 black_point,
2079 white_point;
2080
2081 MagickStatusType
2082 flags;
2083
anthonyfd706f92012-01-19 04:22:02 +00002084 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002085 if ((flags & RhoValue) == 0)
2086 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002087 black_point=geometry_info.rho;
2088 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2089 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002090 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002091 black_point*=(double) _image->columns*_image->rows/100.0;
2092 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002093 }
cristya19f1d72012-08-07 18:24:38 +00002094 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002095 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002096 (void) ContrastStretchImage(_image,black_point,white_point,
2097 _exception);
anthony805a2d42011-09-25 08:25:12 +00002098 break;
2099 }
anthonyafa3dfc2012-03-03 11:31:30 +00002100 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002101 {
2102 KernelInfo
2103 *kernel_info;
2104
anthonyfd706f92012-01-19 04:22:02 +00002105 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002106 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002107 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristya12d8ba2012-04-29 16:33:41 +00002108 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2109 _exception);
anthony805a2d42011-09-25 08:25:12 +00002110 kernel_info=DestroyKernelInfo(kernel_info);
2111 break;
2112 }
anthonyafa3dfc2012-03-03 11:31:30 +00002113 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002114 {
anthony31f1bf72012-01-30 12:37:22 +00002115 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002116 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002117 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002118 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002119 break;
2120 }
anthonyafa3dfc2012-03-03 11:31:30 +00002121 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002122 {
anthony7bcfe7f2012-03-30 14:01:22 +00002123 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002124 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002125 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2126 _exception);
anthony805a2d42011-09-25 08:25:12 +00002127 break;
2128 }
anthonyebb73a22012-03-22 14:25:52 +00002129 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002130 }
2131 case 'd':
2132 {
anthonyafa3dfc2012-03-03 11:31:30 +00002133 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002134 {
anthony4837ac22012-05-18 23:39:48 +00002135 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002136 StringInfo
2137 *passkey;
2138
anthony92c93bd2012-03-19 14:02:47 +00002139 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002140 if (passkey == (StringInfo *) NULL)
2141 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2142
2143 (void) PasskeyDecipherImage(_image,passkey,_exception);
2144 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002145 break;
2146 }
anthonyafa3dfc2012-03-03 11:31:30 +00002147 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002148 {
anthony92c93bd2012-03-19 14:02:47 +00002149 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002150 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002151
anthonydcf510d2011-10-30 13:51:40 +00002152 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2153 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002154
anthonyfd706f92012-01-19 04:22:02 +00002155 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002156 */
anthony92c93bd2012-03-19 14:02:47 +00002157 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002158 break;
2159 }
anthonyafa3dfc2012-03-03 11:31:30 +00002160 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002161 {
2162 double
2163 threshold;
2164
anthonyebb73a22012-03-22 14:25:52 +00002165 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002166 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002167 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002168 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002169 }
anthonyafa3dfc2012-03-03 11:31:30 +00002170 else
2171 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002172 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002173 break;
2174 }
anthonyafa3dfc2012-03-03 11:31:30 +00002175 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002176 {
anthony92c93bd2012-03-19 14:02:47 +00002177 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002178 break;
2179 }
anthonyafa3dfc2012-03-03 11:31:30 +00002180 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002181 {
anthony805a2d42011-09-25 08:25:12 +00002182 double
anthonyb1d483a2012-04-14 12:53:56 +00002183 *args;
anthony805a2d42011-09-25 08:25:12 +00002184
anthonyb1d483a2012-04-14 12:53:56 +00002185 ssize_t
2186 count;
anthony805a2d42011-09-25 08:25:12 +00002187
anthony2a0ec8c2012-03-24 04:35:56 +00002188 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2189 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002190 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2191 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002192 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002193 {
anthony80c37752012-01-16 01:03:11 +00002194 double
2195 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002196 /* Special Case - Argument is actually a resize geometry!
2197 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002198 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002199 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002200 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002201 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2202 option,arg2);
2203 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002204 resize_args[0]=(double) geometry.width;
2205 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002206 new_image=DistortImage(_image,(DistortImageMethod) parse,
2207 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002208 break;
2209 }
anthonyb1d483a2012-04-14 12:53:56 +00002210 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002211 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002212 if (args == (double *)NULL )
2213 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2214
2215 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
anthonya322a832013-04-27 06:28:03 +00002216 IsPlusOp,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002217 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002218 break;
2219 }
anthonyafa3dfc2012-03-03 11:31:30 +00002220 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002221 {
anthony92c93bd2012-03-19 14:02:47 +00002222 (void) CloneString(&_draw_info->primitive,arg1);
2223 (void) DrawImage(_image,_draw_info,_exception);
2224 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002225 break;
2226 }
anthonyebb73a22012-03-22 14:25:52 +00002227 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002228 }
2229 case 'e':
2230 {
anthonyafa3dfc2012-03-03 11:31:30 +00002231 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002232 {
anthonyfd706f92012-01-19 04:22:02 +00002233 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002234 if ((flags & (RhoValue|SigmaValue)) == 0)
2235 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy9dc4c512013-03-24 01:38:00 +00002236 new_image=EdgeImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002237 break;
2238 }
anthonyafa3dfc2012-03-03 11:31:30 +00002239 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002240 {
anthonyfd706f92012-01-19 04:22:02 +00002241 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002242 if ((flags & (RhoValue|SigmaValue)) == 0)
2243 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002244 if ((flags & SigmaValue) == 0)
2245 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002246 new_image=EmbossImage(_image,geometry_info.rho,
2247 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002248 break;
2249 }
anthonyafa3dfc2012-03-03 11:31:30 +00002250 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002251 {
anthony4837ac22012-05-18 23:39:48 +00002252 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002253 StringInfo
2254 *passkey;
2255
anthony92c93bd2012-03-19 14:02:47 +00002256 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002257 if (passkey != (StringInfo *) NULL)
2258 {
anthony92c93bd2012-03-19 14:02:47 +00002259 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002260 passkey=DestroyStringInfo(passkey);
2261 }
2262 break;
2263 }
anthonyafa3dfc2012-03-03 11:31:30 +00002264 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002265 {
anthony92c93bd2012-03-19 14:02:47 +00002266 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002267 break;
2268 }
anthonyafa3dfc2012-03-03 11:31:30 +00002269 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002270 {
anthony92c93bd2012-03-19 14:02:47 +00002271 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002272 break;
2273 }
anthonyafa3dfc2012-03-03 11:31:30 +00002274 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002275 {
2276 double
2277 constant;
2278
anthony2a0ec8c2012-03-24 04:35:56 +00002279 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2280 if ( parse < 0 )
2281 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2282 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002283 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002284 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002285 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002286 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2287 _exception);
anthony805a2d42011-09-25 08:25:12 +00002288 break;
2289 }
anthonyafa3dfc2012-03-03 11:31:30 +00002290 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002291 {
anthony7bcfe7f2012-03-30 14:01:22 +00002292 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002293 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002294 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002295 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002296 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002297 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002298 geometry.height=_image->rows;
2299 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002300 break;
2301 }
anthonyebb73a22012-03-22 14:25:52 +00002302 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002303 }
2304 case 'f':
2305 {
anthonyafa3dfc2012-03-03 11:31:30 +00002306 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002307 {
anthony92c93bd2012-03-19 14:02:47 +00002308 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002309 break;
2310 }
anthonyafa3dfc2012-03-03 11:31:30 +00002311 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002312 {
anthony92c93bd2012-03-19 14:02:47 +00002313 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002314 break;
2315 }
anthonyafa3dfc2012-03-03 11:31:30 +00002316 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002317 {
2318 PixelInfo
2319 target;
2320
anthony7bcfe7f2012-03-30 14:01:22 +00002321 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002322 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002323 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2324 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2325 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
anthonya322a832013-04-27 06:28:03 +00002326 geometry.y,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002327 break;
2328 }
anthonyafa3dfc2012-03-03 11:31:30 +00002329 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002330 {
2331 FrameInfo
2332 frame_info;
2333
anthony31f1bf72012-01-30 12:37:22 +00002334 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002335 compose;
2336
2337 const char*
2338 value;
2339
anthony92c93bd2012-03-19 14:02:47 +00002340 value=GetImageOption(_image_info,"compose");
anthony92c93bd2012-03-19 14:02:47 +00002341 compose=OverCompositeOp; /* use Over not _image->compose */
cristy4b892612012-08-03 19:31:31 +00002342 if (value != (const char *) NULL)
2343 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2344 MagickFalse,value);
anthony7bcfe7f2012-03-30 14:01:22 +00002345 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002346 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002347 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002348 frame_info.width=geometry.width;
2349 frame_info.height=geometry.height;
anthony805a2d42011-09-25 08:25:12 +00002350 frame_info.outer_bevel=geometry.x;
2351 frame_info.inner_bevel=geometry.y;
2352 frame_info.x=(ssize_t) frame_info.width;
2353 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002354 frame_info.width=_image->columns+2*frame_info.width;
2355 frame_info.height=_image->rows+2*frame_info.height;
2356 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002357 break;
2358 }
anthonyafa3dfc2012-03-03 11:31:30 +00002359 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002360 {
anthony805a2d42011-09-25 08:25:12 +00002361 double
anthonyb1d483a2012-04-14 12:53:56 +00002362 *args;
anthony805a2d42011-09-25 08:25:12 +00002363
anthonyb1d483a2012-04-14 12:53:56 +00002364 ssize_t
2365 count;
anthony805a2d42011-09-25 08:25:12 +00002366
anthony2a0ec8c2012-03-24 04:35:56 +00002367 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2368 if ( parse < 0 )
2369 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2370 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002371 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002372 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002373 if (args == (double *)NULL )
2374 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2375
2376 (void) FunctionImage(_image,(MagickFunction)parse,count,args,
2377 _exception);
2378 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002379 break;
2380 }
anthonyebb73a22012-03-22 14:25:52 +00002381 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002382 }
2383 case 'g':
2384 {
anthonyafa3dfc2012-03-03 11:31:30 +00002385 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002386 {
anthony7a4d6102012-07-01 09:48:25 +00002387 double
2388 constant;
2389
anthony7bcfe7f2012-03-30 14:01:22 +00002390 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002391 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony7a4d6102012-07-01 09:48:25 +00002392 constant=StringToDouble(arg1,(char **) NULL);
2393#if 0
2394 /* Using Gamma, via a cache */
2395 if (IfPlusOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002396 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002397 (void) GammaImage(_image,constant,_exception);
2398#else
2399 /* Using Evaluate POW, direct update of values - more accurite */
anthonyafa3dfc2012-03-03 11:31:30 +00002400 if (IfNormalOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002401 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002402 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
2403#endif
2404 /* Set gamma setting -- Old meaning of "+gamma"
2405 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2406 */
anthony805a2d42011-09-25 08:25:12 +00002407 break;
2408 }
anthony975a8d72012-04-12 13:54:36 +00002409 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002410 {
anthonyfd706f92012-01-19 04:22:02 +00002411 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002412 if ((flags & (RhoValue|SigmaValue)) == 0)
2413 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002414 if ((flags & SigmaValue) == 0)
2415 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002416 new_image=GaussianBlurImage(_image,geometry_info.rho,
2417 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002418 break;
2419 }
anthony975a8d72012-04-12 13:54:36 +00002420 if (LocaleCompare("gaussian",option+1) == 0)
2421 {
anthony464f1c42012-04-22 08:51:01 +00002422 CLIWandWarnReplaced("-gaussian-blur");
anthony975a8d72012-04-12 13:54:36 +00002423 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
2424 }
anthonyafa3dfc2012-03-03 11:31:30 +00002425 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002426 {
anthonyfd706f92012-01-19 04:22:02 +00002427 /*
anthony31f1bf72012-01-30 12:37:22 +00002428 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002429 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002430 FUTURE: Why if no 'offset' does this resize ALL images?
2431 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002432 */
anthonyafa3dfc2012-03-03 11:31:30 +00002433 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002434 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002435 if (_image->geometry != (char *) NULL)
2436 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002437 break;
2438 }
anthony7bcfe7f2012-03-30 14:01:22 +00002439 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002440 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002441 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002442 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002443 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002444 else
anthony92c93bd2012-03-19 14:02:47 +00002445 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002446 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002447 break;
2448 }
cristyab943592013-03-29 16:47:23 +00002449 if (LocaleCompare("grayscale",option+1) == 0)
cristye0b9b8f2013-03-28 12:39:39 +00002450 {
cristyab943592013-03-29 16:47:23 +00002451 parse=ParseCommandOption(MagickPixelIntensityOptions,
cristye0b9b8f2013-03-28 12:39:39 +00002452 MagickFalse,arg1);
cristyab943592013-03-29 16:47:23 +00002453 if (parse < 0)
2454 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
2455 option,arg1);
2456 (void) GrayscaleImage(_image,(PixelIntensityMethod) parse,_exception);
cristye0b9b8f2013-03-28 12:39:39 +00002457 break;
2458 }
anthonyebb73a22012-03-22 14:25:52 +00002459 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002460 }
anthony805a2d42011-09-25 08:25:12 +00002461 case 'i':
2462 {
anthonyafa3dfc2012-03-03 11:31:30 +00002463 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002464 {
anthony31f1bf72012-01-30 12:37:22 +00002465 const char
2466 *format,
anthony805a2d42011-09-25 08:25:12 +00002467 *text;
2468
anthony92c93bd2012-03-19 14:02:47 +00002469 format=GetImageOption(_image_info,"format");
anthony964d28e2012-05-17 23:39:46 +00002470 if (format == (char *) NULL) {
2471 (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception);
2472 break;
2473 }
anthony92c93bd2012-03-19 14:02:47 +00002474 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002475 if (text == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00002476 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
2477 option);
anthony805a2d42011-09-25 08:25:12 +00002478 (void) fputs(text,stdout);
2479 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002480 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002481 break;
2482 }
anthonyafa3dfc2012-03-03 11:31:30 +00002483 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002484 {
anthonyb1e21ed2012-04-20 12:43:12 +00002485 flags=ParseGeometry(arg1,&geometry_info);
2486 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002487 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002488 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2489 _exception);
anthony805a2d42011-09-25 08:25:12 +00002490 break;
2491 }
anthonyafa3dfc2012-03-03 11:31:30 +00002492 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002493 {
anthonyfe1aa782012-03-24 13:43:04 +00002494 /* FUTURE: New to IMv7
2495 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002496 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002497 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002498 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2499 new_image=InterpolativeResizeImage(_image,geometry.width,
2500 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002501 break;
2502 }
anthonyebb73a22012-03-22 14:25:52 +00002503 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002504 }
2505 case 'l':
2506 {
anthonyafa3dfc2012-03-03 11:31:30 +00002507 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002508 {
anthonyfd706f92012-01-19 04:22:02 +00002509 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002510 if ((flags & (RhoValue|SigmaValue)) == 0)
2511 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyb5c691e2012-09-14 17:12:40 +00002512 if ((flags & SigmaValue) == 0)
2513 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00002514 if ((flags & PercentValue) != 0)
2515 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002516 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002517 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002518 _exception);
anthony805a2d42011-09-25 08:25:12 +00002519 break;
2520 }
anthonyafa3dfc2012-03-03 11:31:30 +00002521 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002522 {
cristya19f1d72012-08-07 18:24:38 +00002523 double
anthony805a2d42011-09-25 08:25:12 +00002524 black_point,
2525 gamma,
2526 white_point;
2527
2528 MagickStatusType
2529 flags;
2530
anthonyfd706f92012-01-19 04:22:02 +00002531 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002532 if ((flags & RhoValue) == 0)
2533 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002534 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002535 white_point=(double) QuantumRange;
anthony805a2d42011-09-25 08:25:12 +00002536 if ((flags & SigmaValue) != 0)
2537 white_point=geometry_info.sigma;
2538 gamma=1.0;
2539 if ((flags & XiValue) != 0)
2540 gamma=geometry_info.xi;
2541 if ((flags & PercentValue) != 0)
2542 {
cristya19f1d72012-08-07 18:24:38 +00002543 black_point*=(double) (QuantumRange/100.0);
2544 white_point*=(double) (QuantumRange/100.0);
anthony805a2d42011-09-25 08:25:12 +00002545 }
2546 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002547 white_point=(double) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002548 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002549 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002550 else
anthony92c93bd2012-03-19 14:02:47 +00002551 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002552 break;
2553 }
anthonyafa3dfc2012-03-03 11:31:30 +00002554 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002555 {
2556 char
2557 token[MaxTextExtent];
2558
2559 const char
2560 *p;
2561
2562 PixelInfo
2563 black_point,
2564 white_point;
2565
anthonyfd706f92012-01-19 04:22:02 +00002566 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002567 GetMagickToken(p,&p,token); /* get black point color */
2568 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002569 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002570 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002571 else
cristy269c9412011-10-13 23:41:15 +00002572 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002573 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002574 if (isalpha((int) token[0]) || (token[0] == '#'))
2575 GetMagickToken(p,&p,token);
2576 if (*token == '\0')
2577 white_point=black_point; /* set everything to that color */
2578 else
2579 {
2580 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2581 GetMagickToken(p,&p,token); /* Get white point color. */
2582 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002583 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002584 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002585 else
cristy269c9412011-10-13 23:41:15 +00002586 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002587 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002588 }
anthony92c93bd2012-03-19 14:02:47 +00002589 (void) LevelImageColors(_image,&black_point,&white_point,
anthonya322a832013-04-27 06:28:03 +00002590 IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002591 break;
2592 }
anthonyafa3dfc2012-03-03 11:31:30 +00002593 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002594 {
2595 double
2596 black_point,
2597 white_point;
2598
2599 MagickStatusType
2600 flags;
2601
anthonyfd706f92012-01-19 04:22:02 +00002602 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002603 if ((flags & RhoValue) == 0)
2604 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002605 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002606 white_point=(double) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002607 if ((flags & SigmaValue) != 0)
2608 white_point=geometry_info.sigma;
2609 if ((flags & PercentValue) != 0)
2610 {
anthony92c93bd2012-03-19 14:02:47 +00002611 black_point*=(double) _image->columns*_image->rows/100.0;
2612 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002613 }
2614 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002615 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002616 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002617 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002618 break;
2619 }
anthonyafa3dfc2012-03-03 11:31:30 +00002620 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002621 {
anthonyfe1aa782012-03-24 13:43:04 +00002622 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002623 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002624 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002625 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002626 if ((flags & XValue) == 0)
2627 geometry.x=1;
2628 if ((flags & YValue) == 0)
2629 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002630 new_image=LiquidRescaleImage(_image,geometry.width,
2631 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002632 break;
2633 }
anthonyebb73a22012-03-22 14:25:52 +00002634 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002635 }
2636 case 'm':
2637 {
cristy7220ee42013-04-14 01:30:34 +00002638 if (LocaleCompare("magnify",option+1) == 0)
2639 {
2640 new_image=MagnifyImage(_image,_exception);
2641 break;
2642 }
anthonyafa3dfc2012-03-03 11:31:30 +00002643 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002644 {
anthony464f1c42012-04-22 08:51:01 +00002645 CLIWandWarnReplaced("-remap");
anthony975a8d72012-04-12 13:54:36 +00002646 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
anthony805a2d42011-09-25 08:25:12 +00002647 break;
2648 }
anthonyafa3dfc2012-03-03 11:31:30 +00002649 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002650 {
anthony4837ac22012-05-18 23:39:48 +00002651 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002652 Image
2653 *mask;
2654
anthonyafa3dfc2012-03-03 11:31:30 +00002655 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002656 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002657 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002658 break;
2659 }
anthony5330ae02012-03-20 14:17:01 +00002660 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002661 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002662 if (mask == (Image *) NULL)
2663 break;
anthony92c93bd2012-03-19 14:02:47 +00002664 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002665 mask=DestroyImage(mask);
2666 break;
2667 }
cristy52ad9e92013-02-08 23:23:29 +00002668 if (LocaleCompare("matte",option+1) == 0)
2669 {
2670 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2671 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2672 DeactivateAlphaChannel, _exception);
2673 break;
2674 }
2675 if (LocaleCompare("median",option+1) == 0)
2676 {
2677 CLIWandWarnReplaced("-statistic Median");
2678 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2679 break;
2680 }
2681 if (LocaleCompare("mode",option+1) == 0)
2682 {
2683 /* FUTURE: note this is also a special "montage" option */
2684 CLIWandWarnReplaced("-statistic Mode");
2685 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
2686 break;
2687 }
anthonyafa3dfc2012-03-03 11:31:30 +00002688 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002689 {
anthony7bcfe7f2012-03-30 14:01:22 +00002690 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002691 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002692 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002693 break;
2694 }
anthonyafa3dfc2012-03-03 11:31:30 +00002695 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002696 {
anthony92c93bd2012-03-19 14:02:47 +00002697 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002698 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002699 break;
2700 }
anthonyafa3dfc2012-03-03 11:31:30 +00002701 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002702 {
anthony92c93bd2012-03-19 14:02:47 +00002703 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002704 break;
2705 }
anthonyafa3dfc2012-03-03 11:31:30 +00002706 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002707 {
2708 char
2709 token[MaxTextExtent];
2710
2711 const char
2712 *p;
2713
2714 KernelInfo
2715 *kernel;
2716
anthony805a2d42011-09-25 08:25:12 +00002717 ssize_t
2718 iterations;
2719
anthonyfd706f92012-01-19 04:22:02 +00002720 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002721 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002722 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2723 if ( parse < 0 )
2724 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2725 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002726 iterations=1L;
2727 GetMagickToken(p,&p,token);
2728 if ((*p == ':') || (*p == ','))
2729 GetMagickToken(p,&p,token);
2730 if ((*p != '\0'))
2731 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002732 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002733 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002734 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2735 option,arg2);
2736 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2737 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002738 kernel=DestroyKernelInfo(kernel);
2739 break;
2740 }
anthonyafa3dfc2012-03-03 11:31:30 +00002741 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002742 {
anthonyfd706f92012-01-19 04:22:02 +00002743 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002744 if ((flags & (RhoValue|SigmaValue)) == 0)
2745 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002746 if ((flags & SigmaValue) == 0)
2747 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002748 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002749 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002750 break;
2751 }
anthonyebb73a22012-03-22 14:25:52 +00002752 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002753 }
2754 case 'n':
2755 {
anthonyafa3dfc2012-03-03 11:31:30 +00002756 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002757 {
anthonya322a832013-04-27 06:28:03 +00002758 (void) NegateImage(_image, IsPlusOp, _exception);
anthony805a2d42011-09-25 08:25:12 +00002759 break;
2760 }
anthonyafa3dfc2012-03-03 11:31:30 +00002761 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002762 {
anthony975a8d72012-04-12 13:54:36 +00002763 double
2764 attenuate;
2765
2766 const char*
2767 value;
2768
anthonyafa3dfc2012-03-03 11:31:30 +00002769 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002770 {
anthony464f1c42012-04-22 08:51:01 +00002771 CLIWandWarnReplaced("-statistic NonPeak");
anthony975a8d72012-04-12 13:54:36 +00002772 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
2773 break;
anthony805a2d42011-09-25 08:25:12 +00002774 }
anthony975a8d72012-04-12 13:54:36 +00002775 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2776 if ( parse < 0 )
2777 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2778 option,arg1);
2779 attenuate=1.0;
2780 value=GetImageOption(_image_info,"attenuate");
2781 if (value != (const char *) NULL)
2782 attenuate=StringToDouble(value,(char **) NULL);
2783 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2784 _exception);
anthony805a2d42011-09-25 08:25:12 +00002785 break;
2786 }
anthonyafa3dfc2012-03-03 11:31:30 +00002787 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002788 {
anthony92c93bd2012-03-19 14:02:47 +00002789 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002790 break;
2791 }
anthonyebb73a22012-03-22 14:25:52 +00002792 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002793 }
2794 case 'o':
2795 {
anthonyafa3dfc2012-03-03 11:31:30 +00002796 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002797 {
2798 PixelInfo
2799 target;
2800
anthony92c93bd2012-03-19 14:02:47 +00002801 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
anthonya322a832013-04-27 06:28:03 +00002802 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,IsPlusOp,
anthony92c93bd2012-03-19 14:02:47 +00002803 _exception);
anthony805a2d42011-09-25 08:25:12 +00002804 break;
2805 }
anthonyafa3dfc2012-03-03 11:31:30 +00002806 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002807 {
anthony92c93bd2012-03-19 14:02:47 +00002808 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002809 break;
2810 }
anthonyebb73a22012-03-22 14:25:52 +00002811 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002812 }
2813 case 'p':
2814 {
anthonyafa3dfc2012-03-03 11:31:30 +00002815 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002816 {
anthony22de2722012-04-19 14:43:00 +00002817 flags=ParseGeometry(arg1,&geometry_info);
2818 if ((flags & (RhoValue|SigmaValue)) == 0)
2819 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002820 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2821 _exception);
anthony805a2d42011-09-25 08:25:12 +00002822 break;
2823 }
cristy7884a932012-11-04 14:33:51 +00002824 if (LocaleCompare("perceptible",option+1) == 0)
2825 {
2826 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2827 _exception);
2828 break;
2829 }
anthonyafa3dfc2012-03-03 11:31:30 +00002830 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002831 {
cristye9e3d382011-12-14 01:50:13 +00002832 const char
2833 *caption;
2834
anthony805a2d42011-09-25 08:25:12 +00002835 double
2836 angle;
2837
anthony7bc87992012-03-25 02:32:51 +00002838 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002839 RandomInfo
2840 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002841
anthonyf42014d2012-03-25 09:53:06 +00002842 random_info=AcquireRandomInfo();
2843 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2844 random_info=DestroyRandomInfo(random_info);
2845 }
anthony7bc87992012-03-25 02:32:51 +00002846 else {
anthonyf42014d2012-03-25 09:53:06 +00002847 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002848 if ((flags & RhoValue) == 0)
2849 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002850 angle=geometry_info.rho;
2851 }
anthony92c93bd2012-03-19 14:02:47 +00002852 caption=GetImageProperty(_image,"caption",_exception);
2853 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2854 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002855 break;
2856 }
anthonyafa3dfc2012-03-03 11:31:30 +00002857 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002858 {
anthony22de2722012-04-19 14:43:00 +00002859 flags=ParseGeometry(arg1,&geometry_info);
2860 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002861 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002862 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
cristycbda6112012-05-27 20:57:16 +00002863 _quantize_info->dither_method,_exception);
anthony805a2d42011-09-25 08:25:12 +00002864 break;
2865 }
anthonyafa3dfc2012-03-03 11:31:30 +00002866 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002867 {
anthony31f1bf72012-01-30 12:37:22 +00002868 /* FUTURE: should be a 'Genesis' option?
2869 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00002870 Why???
cristy947cb4c2011-10-20 18:41:46 +00002871 */
anthony7bc87992012-03-25 02:32:51 +00002872 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2873 if ( parse < 0 )
2874 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2875 option,arg1);
2876 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00002877 break;
2878 }
anthonyafa3dfc2012-03-03 11:31:30 +00002879 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002880 {
anthony4837ac22012-05-18 23:39:48 +00002881 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002882 const char
2883 *name;
2884
2885 const StringInfo
2886 *profile;
2887
2888 Image
2889 *profile_image;
2890
2891 ImageInfo
2892 *profile_info;
2893
anthonyafa3dfc2012-03-03 11:31:30 +00002894 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002895 { /* Remove a profile from the _image. */
2896 (void) ProfileImage(_image,arg1,(const unsigned char *)
2897 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002898 break;
2899 }
anthony92c93bd2012-03-19 14:02:47 +00002900 /* Associate a profile with the _image. */
2901 profile_info=CloneImageInfo(_image_info);
2902 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002903 if (profile != (StringInfo *) NULL)
2904 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002905 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002906 profile_info=DestroyImageInfo(profile_info);
2907 if (profile_image == (Image *) NULL)
2908 {
2909 StringInfo
2910 *profile;
2911
anthony92c93bd2012-03-19 14:02:47 +00002912 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002913 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002914 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002915 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002916 if (profile != (StringInfo *) NULL)
2917 {
anthony92c93bd2012-03-19 14:02:47 +00002918 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002919 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002920 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002921 profile=DestroyStringInfo(profile);
2922 }
2923 profile_info=DestroyImageInfo(profile_info);
2924 break;
2925 }
2926 ResetImageProfileIterator(profile_image);
2927 name=GetNextImageProfile(profile_image);
2928 while (name != (const char *) NULL)
2929 {
2930 profile=GetImageProfile(profile_image,name);
2931 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002932 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2933 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002934 name=GetNextImageProfile(profile_image);
2935 }
2936 profile_image=DestroyImage(profile_image);
2937 break;
2938 }
anthonyebb73a22012-03-22 14:25:52 +00002939 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002940 }
anthony805a2d42011-09-25 08:25:12 +00002941 case 'r':
2942 {
anthonyafa3dfc2012-03-03 11:31:30 +00002943 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002944 {
anthonyfd706f92012-01-19 04:22:02 +00002945 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002946 if ((flags & RhoValue) == 0)
2947 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyaa2c16c2012-03-25 22:21:35 +00002948 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002949 break;
2950 }
anthonyafa3dfc2012-03-03 11:31:30 +00002951 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002952 {
anthony7bcfe7f2012-03-30 14:01:22 +00002953 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002954 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002955 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthonya322a832013-04-27 06:28:03 +00002956 (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00002957 break;
2958 }
anthonyafa3dfc2012-03-03 11:31:30 +00002959 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002960 {
anthony7bcfe7f2012-03-30 14:01:22 +00002961 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002962 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002963 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002964 break;
2965 }
anthony975a8d72012-04-12 13:54:36 +00002966 if (LocaleCompare("recolor",option+1) == 0)
2967 {
anthony464f1c42012-04-22 08:51:01 +00002968 CLIWandWarnReplaced("-color-matrix");
anthony975a8d72012-04-12 13:54:36 +00002969 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
2970 }
anthonyafa3dfc2012-03-03 11:31:30 +00002971 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002972 {
anthony4837ac22012-05-18 23:39:48 +00002973 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002974 Image
2975 *remap_image;
2976
anthony92c93bd2012-03-19 14:02:47 +00002977 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002978 if (remap_image == (Image *) NULL)
2979 break;
anthony92c93bd2012-03-19 14:02:47 +00002980 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002981 remap_image=DestroyImage(remap_image);
2982 break;
2983 }
anthonyafa3dfc2012-03-03 11:31:30 +00002984 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002985 {
anthonyafa3dfc2012-03-03 11:31:30 +00002986 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00002987 {
anthony7bcfe7f2012-03-30 14:01:22 +00002988 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00002989 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
2990 arg1);
2991 (void) ResetImagePage(_image,arg1);
2992 }
anthony31f1bf72012-01-30 12:37:22 +00002993 else
anthony92c93bd2012-03-19 14:02:47 +00002994 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00002995 break;
2996 }
anthonyafa3dfc2012-03-03 11:31:30 +00002997 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002998 {
anthonyf46d4262012-03-26 03:30:34 +00002999 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00003000 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003001 if ((flags & (RhoValue|SigmaValue)) == 0)
3002 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003003 if ((flags & SigmaValue) == 0)
3004 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003005 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003006 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003007 break;
3008 }
anthonyafa3dfc2012-03-03 11:31:30 +00003009 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003010 {
anthony7bcfe7f2012-03-30 14:01:22 +00003011 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003012 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003013 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3014 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003015 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003016 break;
3017 }
anthonyafa3dfc2012-03-03 11:31:30 +00003018 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003019 {
anthony7bcfe7f2012-03-30 14:01:22 +00003020 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003021 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003022 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3023 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003024 break;
3025 }
anthonyafa3dfc2012-03-03 11:31:30 +00003026 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003027 {
anthony22de2722012-04-19 14:43:00 +00003028 flags=ParseGeometry(arg1,&geometry_info);
3029 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003030 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00003031 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00003032 break;
3033 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3034 break;
anthony92c93bd2012-03-19 14:02:47 +00003035 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003036 break;
3037 }
anthonyebb73a22012-03-22 14:25:52 +00003038 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003039 }
3040 case 's':
3041 {
anthonyafa3dfc2012-03-03 11:31:30 +00003042 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003043 {
anthonyfe1aa782012-03-24 13:43:04 +00003044 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003045 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003046 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003047 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3048 new_image=SampleImage(_image,geometry.width,geometry.height,
3049 _exception);
anthony805a2d42011-09-25 08:25:12 +00003050 break;
3051 }
anthonyafa3dfc2012-03-03 11:31:30 +00003052 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003053 {
anthonyfe1aa782012-03-24 13:43:04 +00003054 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003055 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003056 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003057 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3058 new_image=ScaleImage(_image,geometry.width,geometry.height,
3059 _exception);
anthony805a2d42011-09-25 08:25:12 +00003060 break;
3061 }
anthonyf42014d2012-03-25 09:53:06 +00003062 if (LocaleCompare("segment",option+1) == 0)
3063 {
anthonyf42014d2012-03-25 09:53:06 +00003064 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003065 if ((flags & (RhoValue|SigmaValue)) == 0)
3066 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003067 if ((flags & SigmaValue) == 0)
3068 geometry_info.sigma=1.0;
3069 (void) SegmentImage(_image,_image->colorspace,
3070 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3071 _exception);
3072 break;
3073 }
anthonyafa3dfc2012-03-03 11:31:30 +00003074 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003075 {
anthonyfd706f92012-01-19 04:22:02 +00003076 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003077 if ((flags & (RhoValue|SigmaValue)) == 0)
3078 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3079 if ((flags & SigmaValue) == 0)
3080 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003081 if ((flags & PercentValue) != 0)
3082 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003083 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003084 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003085 break;
3086 }
anthonyafa3dfc2012-03-03 11:31:30 +00003087 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003088 {
anthony31f1bf72012-01-30 12:37:22 +00003089 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003090 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003091 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003092 break;
3093 }
anthonyafa3dfc2012-03-03 11:31:30 +00003094 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003095 {
anthony7bcfe7f2012-03-30 14:01:22 +00003096 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003097 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3098 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3099 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003100 break;
3101 }
anthonyafa3dfc2012-03-03 11:31:30 +00003102 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003103 {
anthonyfd706f92012-01-19 04:22:02 +00003104 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003105 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3106 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya322a832013-04-27 06:28:03 +00003107 new_image=ShadeImage(_image,IsNormalOp,geometry_info.rho,
anthony92c93bd2012-03-19 14:02:47 +00003108 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003109 break;
3110 }
anthonyafa3dfc2012-03-03 11:31:30 +00003111 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003112 {
anthonyfd706f92012-01-19 04:22:02 +00003113 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003114 if ((flags & (RhoValue|SigmaValue)) == 0)
3115 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003116 if ((flags & SigmaValue) == 0)
3117 geometry_info.sigma=1.0;
3118 if ((flags & XiValue) == 0)
3119 geometry_info.xi=4.0;
3120 if ((flags & PsiValue) == 0)
3121 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003122 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3123 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3124 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003125 break;
3126 }
anthonyafa3dfc2012-03-03 11:31:30 +00003127 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003128 {
anthonyfd706f92012-01-19 04:22:02 +00003129 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003130 if ((flags & (RhoValue|SigmaValue)) == 0)
3131 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003132 if ((flags & SigmaValue) == 0)
3133 geometry_info.sigma=1.0;
3134 if ((flags & XiValue) == 0)
3135 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003136 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3137 _exception);
anthony805a2d42011-09-25 08:25:12 +00003138 break;
3139 }
anthonyafa3dfc2012-03-03 11:31:30 +00003140 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003141 {
anthony7bcfe7f2012-03-30 14:01:22 +00003142 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003143 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003144 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3145 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003146 break;
3147 }
anthonyafa3dfc2012-03-03 11:31:30 +00003148 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003149 {
anthonyfd706f92012-01-19 04:22:02 +00003150 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003151 if ((flags & RhoValue) == 0)
3152 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003153 if ((flags & SigmaValue) == 0)
3154 geometry_info.sigma=geometry_info.rho;
cristy4b892612012-08-03 19:31:31 +00003155 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3156 _exception);
anthony805a2d42011-09-25 08:25:12 +00003157 break;
3158 }
anthonyafa3dfc2012-03-03 11:31:30 +00003159 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003160 {
anthonyfd706f92012-01-19 04:22:02 +00003161 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003162 if ((flags & RhoValue) == 0)
3163 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003164 if ((flags & SigmaValue) == 0)
3165 geometry_info.sigma=(double) QuantumRange/2.0;
3166 if ((flags & PercentValue) != 0)
3167 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3168 100.0;
anthonya322a832013-04-27 06:28:03 +00003169 (void) SigmoidalContrastImage(_image,IsNormalOp,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003170 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003171 break;
3172 }
anthonyafa3dfc2012-03-03 11:31:30 +00003173 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003174 {
anthonyfd706f92012-01-19 04:22:02 +00003175 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003176 if ((flags & (RhoValue|SigmaValue)) == 0)
3177 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003178 if ((flags & SigmaValue) == 0)
3179 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003180 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003181 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003182 break;
3183 }
anthonyafa3dfc2012-03-03 11:31:30 +00003184 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003185 {
anthony7bcfe7f2012-03-30 14:01:22 +00003186 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003187 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003188 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3189 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003190 break;
3191 }
anthonyafa3dfc2012-03-03 11:31:30 +00003192 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003193 {
anthonyf42014d2012-03-25 09:53:06 +00003194 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3195 if ( parse < 0 )
3196 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3197 option,arg1);
anthony964d28e2012-05-17 23:39:46 +00003198 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3199 _exception);
anthony805a2d42011-09-25 08:25:12 +00003200 break;
3201 }
anthonyafa3dfc2012-03-03 11:31:30 +00003202 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003203 {
anthony7bcfe7f2012-03-30 14:01:22 +00003204 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003205 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003206 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003207 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003208 break;
3209 }
anthonyafa3dfc2012-03-03 11:31:30 +00003210 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003211 {
anthonyb1e21ed2012-04-20 12:43:12 +00003212 flags=ParseGeometry(arg1,&geometry_info);
3213 if ((flags & RhoValue) == 0)
3214 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003215 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3216 _exception);
anthony805a2d42011-09-25 08:25:12 +00003217 break;
3218 }
anthonyafa3dfc2012-03-03 11:31:30 +00003219 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003220 {
anthony7bc87992012-03-25 02:32:51 +00003221 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3222 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003223 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003224 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003225 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003226 if ((flags & RhoValue) == 0)
3227 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003228 if ((flags & SigmaValue) == 0)
3229 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003230 new_image=StatisticImage(_image,(StatisticType)parse,
3231 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3232 _exception);
anthony805a2d42011-09-25 08:25:12 +00003233 break;
3234 }
anthonyafa3dfc2012-03-03 11:31:30 +00003235 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003236 {
anthony92c93bd2012-03-19 14:02:47 +00003237 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003238 break;
3239 }
anthonyafa3dfc2012-03-03 11:31:30 +00003240 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003241 {
cristy898c6042012-06-24 00:36:34 +00003242 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00003243 if ((flags & RhoValue) == 0)
cristy898c6042012-06-24 00:36:34 +00003244 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003245 new_image=SwirlImage(_image,geometry_info.rho,
3246 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003247 break;
3248 }
anthonyebb73a22012-03-22 14:25:52 +00003249 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003250 }
3251 case 't':
3252 {
anthonyafa3dfc2012-03-03 11:31:30 +00003253 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003254 {
3255 double
3256 threshold;
3257
anthony52bef752012-03-27 13:54:47 +00003258 threshold=(double) QuantumRange/2;
anthonya322a832013-04-27 06:28:03 +00003259 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00003260 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003261 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003262 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003263 }
anthony92c93bd2012-03-19 14:02:47 +00003264 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003265 break;
3266 }
anthonyafa3dfc2012-03-03 11:31:30 +00003267 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003268 {
anthony7bcfe7f2012-03-30 14:01:22 +00003269 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003270 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003271 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3272 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3273 _exception);
anthony805a2d42011-09-25 08:25:12 +00003274 break;
3275 }
anthonyafa3dfc2012-03-03 11:31:30 +00003276 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003277 {
anthony7bcfe7f2012-03-30 14:01:22 +00003278 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003279 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003280 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003281 break;
3282 }
anthonyafa3dfc2012-03-03 11:31:30 +00003283 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003284 {
anthony464f1c42012-04-22 08:51:01 +00003285 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003286 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003287 break;
3288 }
anthonyafa3dfc2012-03-03 11:31:30 +00003289 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003290 {
3291 PixelInfo
3292 target;
3293
anthony92c93bd2012-03-19 14:02:47 +00003294 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3295 (void) TransparentPaintImage(_image,&target,(Quantum)
anthonya322a832013-04-27 06:28:03 +00003296 TransparentAlpha,IsPlusOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003297 break;
3298 }
anthonyafa3dfc2012-03-03 11:31:30 +00003299 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003300 {
anthony92c93bd2012-03-19 14:02:47 +00003301 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003302 break;
3303 }
anthonyafa3dfc2012-03-03 11:31:30 +00003304 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003305 {
anthony92c93bd2012-03-19 14:02:47 +00003306 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003307 break;
3308 }
anthonyafa3dfc2012-03-03 11:31:30 +00003309 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003310 {
anthony92c93bd2012-03-19 14:02:47 +00003311 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003312 break;
3313 }
anthonyafa3dfc2012-03-03 11:31:30 +00003314 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003315 {
anthonyab3a50c2011-10-27 11:48:57 +00003316 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003317 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003318 break;
3319 }
anthonyebb73a22012-03-22 14:25:52 +00003320 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003321 }
3322 case 'u':
3323 {
anthonyafa3dfc2012-03-03 11:31:30 +00003324 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003325 {
anthony52bef752012-03-27 13:54:47 +00003326 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3327 Option is not documented, bt appears to be for "identify".
3328 We may need a identify specific verbose!
3329 */
anthonya322a832013-04-27 06:28:03 +00003330 if (IsPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00003331 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003332 break;
3333 }
anthony92c93bd2012-03-19 14:02:47 +00003334 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3335 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003336 break;
3337 }
anthonyafa3dfc2012-03-03 11:31:30 +00003338 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003339 {
anthony92c93bd2012-03-19 14:02:47 +00003340 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003341 break;
3342 }
anthonyafa3dfc2012-03-03 11:31:30 +00003343 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003344 {
anthonyfd706f92012-01-19 04:22:02 +00003345 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003346 if ((flags & (RhoValue|SigmaValue)) == 0)
3347 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003348 if ((flags & SigmaValue) == 0)
3349 geometry_info.sigma=1.0;
3350 if ((flags & XiValue) == 0)
3351 geometry_info.xi=1.0;
3352 if ((flags & PsiValue) == 0)
3353 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003354 new_image=UnsharpMaskImage(_image,geometry_info.rho,
cristy3afd4012013-03-25 11:30:44 +00003355 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003356 break;
3357 }
anthonyebb73a22012-03-22 14:25:52 +00003358 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003359 }
3360 case 'v':
3361 {
anthonyafa3dfc2012-03-03 11:31:30 +00003362 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003363 {
anthonyafa3dfc2012-03-03 11:31:30 +00003364 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003365 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003366 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003367 */
anthony92c93bd2012-03-19 14:02:47 +00003368 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003369 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003370 break;
3371 }
anthonyafa3dfc2012-03-03 11:31:30 +00003372 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003373 {
anthonyfd706f92012-01-19 04:22:02 +00003374 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003375 if ((flags & (RhoValue|SigmaValue)) == 0)
3376 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003377 if ((flags & SigmaValue) == 0)
3378 geometry_info.sigma=1.0;
3379 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003380 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003381 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003382 geometry_info.psi=0.1*_image->rows;
3383 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003384 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3385 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003386 break;
3387 }
anthonyebb73a22012-03-22 14:25:52 +00003388 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003389 }
3390 case 'w':
3391 {
anthonyafa3dfc2012-03-03 11:31:30 +00003392 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003393 {
anthonyfd706f92012-01-19 04:22:02 +00003394 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003395 if ((flags & (RhoValue|SigmaValue)) == 0)
3396 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003397 if ((flags & SigmaValue) == 0)
3398 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003399 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3400 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003401 break;
3402 }
anthonyafa3dfc2012-03-03 11:31:30 +00003403 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003404 {
anthony7bcfe7f2012-03-30 14:01:22 +00003405 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003406 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003407 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003408 break;
3409 }
anthonyebb73a22012-03-22 14:25:52 +00003410 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003411 }
3412 default:
anthonyebb73a22012-03-22 14:25:52 +00003413 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003414 }
anthony964d28e2012-05-17 23:39:46 +00003415 /* clean up percent escape interpreted strings */
3416 if (arg1 != arg1n )
3417 arg1=DestroyString((char *)arg1);
3418 if (arg2 != arg2n )
3419 arg2=DestroyString((char *)arg2);
3420
3421 /* Replace current image with any image that was generated
3422 and set image point to last image (so image->next is correct) */
anthony805a2d42011-09-25 08:25:12 +00003423 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003424 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003425
cristyfe831852013-02-12 14:56:07 +00003426 return(MagickTrue);
anthony92c93bd2012-03-19 14:02:47 +00003427#undef _image_info
3428#undef _draw_info
3429#undef _quantize_info
3430#undef _image
3431#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003432#undef IfNormalOp
3433#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00003434#undef IsNormalOp
3435#undef IsPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003436}
anthonyfd706f92012-01-19 04:22:02 +00003437
cristyfe831852013-02-12 14:56:07 +00003438WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
3439 const char *option,const char *arg1,const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003440{
anthonyc7994672012-11-17 05:33:27 +00003441#if !USE_WAND_METHODS
anthony31f1bf72012-01-30 12:37:22 +00003442 size_t
anthony43f425d2012-02-26 12:58:58 +00003443 n,
anthony31f1bf72012-01-30 12:37:22 +00003444 i;
anthonyc7994672012-11-17 05:33:27 +00003445#endif
anthony31f1bf72012-01-30 12:37:22 +00003446
anthony43f425d2012-02-26 12:58:58 +00003447 assert(cli_wand != (MagickCLI *) NULL);
3448 assert(cli_wand->signature == WandSignature);
3449 assert(cli_wand->wand.signature == WandSignature);
3450 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthonya322a832013-04-27 06:28:03 +00003451
anthony7bcfe7f2012-03-30 14:01:22 +00003452 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00003453 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3454 "- Simple Operator: %s \"%s\" \"%s\"", option,arg1,arg2);
anthony31f1bf72012-01-30 12:37:22 +00003455
anthonyafa3dfc2012-03-03 11:31:30 +00003456#if !USE_WAND_METHODS
3457 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003458 i=0;
anthony43f425d2012-02-26 12:58:58 +00003459 n=GetImageListLength(cli_wand->wand.images);
3460 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003461 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003462 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003463 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003464 if ( cli_wand->wand.images->next == (Image *) NULL )
3465 break;
3466 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003467 }
anthony43f425d2012-02-26 12:58:58 +00003468 assert( i == n );
3469 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003470#else
3471 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003472 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
anthonyafa3dfc2012-03-03 11:31:30 +00003473 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3474 MagickResetIterator(&cli_wand->wand);
3475#endif
cristyfe831852013-02-12 14:56:07 +00003476 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003477}
3478
3479/*
3480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3481% %
3482% %
3483% %
anthony43f425d2012-02-26 12:58:58 +00003484+ C L I L i s t O p e r a t o r I m a g e s %
anthony805a2d42011-09-25 08:25:12 +00003485% %
3486% %
3487% %
3488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3489%
anthony43f425d2012-02-26 12:58:58 +00003490% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003491% entire image list as a whole. The result is often a complete replacment
anthonyc7994672012-11-17 05:33:27 +00003492% of the image list with a completely new list, or with just a single image
3493% result.
anthony805a2d42011-09-25 08:25:12 +00003494%
3495% The format of the MogrifyImage method is:
3496%
cristyfe831852013-02-12 14:56:07 +00003497% MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3498% const char *option,const char *arg1,const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003499%
3500% A description of each parameter follows:
3501%
anthony43f425d2012-02-26 12:58:58 +00003502% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003503%
anthony36a8c2c2012-02-10 00:08:44 +00003504% o option: The option string for the operation
3505%
anthony31f1bf72012-01-30 12:37:22 +00003506% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003507% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003508%
anthony805a2d42011-09-25 08:25:12 +00003509*/
cristyfe831852013-02-12 14:56:07 +00003510WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3511 const char *option,const char *arg1n,const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00003512{
anthonya322a832013-04-27 06:28:03 +00003513 const char /* percent escaped versions of the args */
cristya30f8e62013-02-19 15:03:45 +00003514 *arg1,
3515 *arg2;
anthony2a0ec8c2012-03-24 04:35:56 +00003516
anthony31f1bf72012-01-30 12:37:22 +00003517 Image
3518 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003519
cristya30f8e62013-02-19 15:03:45 +00003520 MagickStatusType
3521 status;
3522
3523 ssize_t
3524 parse;
anthony964d28e2012-05-17 23:39:46 +00003525
anthony2e4501b2012-03-30 04:41:54 +00003526#define _image_info (cli_wand->wand.image_info)
3527#define _images (cli_wand->wand.images)
3528#define _exception (cli_wand->wand.exception)
3529#define _draw_info (cli_wand->draw_info)
3530#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00003531#define _process_flags (cli_wand->process_flags)
3532#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00003533#define IfNormalOp (*option=='-')
3534#define IfPlusOp (*option!='-')
anthonya322a832013-04-27 06:28:03 +00003535#define IsNormalOp IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003536
anthony43f425d2012-02-26 12:58:58 +00003537 assert(cli_wand != (MagickCLI *) NULL);
3538 assert(cli_wand->signature == WandSignature);
3539 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003540 assert(_images != (Image *) NULL); /* _images must be present */
anthony31f1bf72012-01-30 12:37:22 +00003541
anthonya322a832013-04-27 06:28:03 +00003542 if (IfMagickTrue(cli_wand->wand.debug))
3543 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3544 "- List Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
3545
anthony964d28e2012-05-17 23:39:46 +00003546 arg1 = arg1n;
3547 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00003548
3549 /* Interpret Percent Escapes in Arguments - using first image */
anthony964d28e2012-05-17 23:39:46 +00003550 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3551 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3552 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3553 /* Interpret Percent escapes in argument 1 */
3554 if (arg1n != (char *) NULL) {
3555 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3556 if (arg1 == (char *) NULL) {
3557 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3558 arg1=arg1n; /* use the given argument as is */
3559 }
3560 }
3561 if (arg2n != (char *) NULL) {
3562 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3563 if (arg2 == (char *) NULL) {
3564 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3565 arg2=arg2n; /* use the given argument as is */
3566 }
3567 }
3568 }
anthony4837ac22012-05-18 23:39:48 +00003569#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00003570#undef _option_type
3571
cristyfe831852013-02-12 14:56:07 +00003572 status=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00003573 new_images=NewImageList();
3574
anthonyafa3dfc2012-03-03 11:31:30 +00003575 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003576 {
3577 case 'a':
3578 {
anthonyafa3dfc2012-03-03 11:31:30 +00003579 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003580 {
anthonya322a832013-04-27 06:28:03 +00003581 new_images=AppendImages(_images,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003582 break;
3583 }
cristy52ad9e92013-02-08 23:23:29 +00003584 if (LocaleCompare("average",option+1) == 0)
3585 {
3586 CLIWandWarnReplaced("-evaluate-sequence Mean");
3587 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
3588 break;
3589 }
anthonyebb73a22012-03-22 14:25:52 +00003590 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003591 }
3592 case 'c':
3593 {
cristy5f257b22012-03-07 00:27:29 +00003594 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003595 {
anthony92c93bd2012-03-19 14:02:47 +00003596 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003597 break;
3598 }
anthonyafa3dfc2012-03-03 11:31:30 +00003599 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003600 {
anthony805a2d42011-09-25 08:25:12 +00003601 Image
anthony31f1bf72012-01-30 12:37:22 +00003602 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003603
anthonyafa3dfc2012-03-03 11:31:30 +00003604 /* FUTURE - make this a compose option, and thus can be used
3605 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003606 _images.
cristy87c02f42012-02-24 00:19:10 +00003607 */
anthony92c93bd2012-03-19 14:02:47 +00003608 new_images=RemoveFirstImageFromList(&_images);
3609 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003610 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003611 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003612 break;
cristye52fb5e2012-04-06 23:30:20 +00003613 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003614 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003615 break;
3616 }
anthonyafa3dfc2012-03-03 11:31:30 +00003617 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003618 {
anthony92c93bd2012-03-19 14:02:47 +00003619 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003620 break;
3621 }
anthonyafa3dfc2012-03-03 11:31:30 +00003622 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003623 {
anthony43f425d2012-02-26 12:58:58 +00003624 /* FUTURE - this may be replaced by a 'channel' method */
cristy46f354c2012-07-04 13:31:29 +00003625 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
cristy8448a0d2013-02-15 18:20:53 +00003626 if (parse < 0)
3627 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
3628 arg1);
cristy46f354c2012-07-04 13:31:29 +00003629 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003630 break;
3631 }
anthonyafa3dfc2012-03-03 11:31:30 +00003632 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003633 {
cristyfeb3e962012-03-29 17:25:55 +00003634 CompositeOperator
3635 compose;
3636
3637 const char*
3638 value;
3639
3640 MagickBooleanType
3641 clip_to_self;
3642
anthony805a2d42011-09-25 08:25:12 +00003643 Image
3644 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003645 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003646
3647 RectangleInfo
3648 geometry;
3649
anthony7bcfe7f2012-03-30 14:01:22 +00003650 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003651 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003652 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003653 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003654 else
3655 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3656 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003657
anthony7bcfe7f2012-03-30 14:01:22 +00003658 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003659 value=GetImageOption(_image_info,"compose:clip-to-self");
3660 if (value == (const char *) NULL)
3661 clip_to_self=MagickTrue;
3662 else
3663 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3664 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003665 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003666 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003667 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003668 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003669 }
3670
anthony92c93bd2012-03-19 14:02:47 +00003671 new_images=RemoveFirstImageFromList(&_images);
3672 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003673 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003674 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003675
anthony31f1bf72012-01-30 12:37:22 +00003676 /* FUTURE - this should not be here! - should be part of -geometry */
3677 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003678 source_image->geometry,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003679 SetGeometry(source_image,&geometry);
3680 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3681 GravityAdjustGeometry(new_images->columns,new_images->rows,
cristyfe831852013-02-12 14:56:07 +00003682 new_images->gravity, &geometry);
anthony92c93bd2012-03-19 14:02:47 +00003683 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003684 if (mask_image != (Image *) NULL)
cristyfe831852013-02-12 14:56:07 +00003685 {
anthony5f867ae2011-10-09 10:28:34 +00003686 if ((compose == DisplaceCompositeOp) ||
cristyfe831852013-02-12 14:56:07 +00003687 (compose == DistortCompositeOp))
3688 status&=CompositeImage(source_image,mask_image,
anthony7bcfe7f2012-03-30 14:01:22 +00003689 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
cristyfe831852013-02-12 14:56:07 +00003690 else
cristy15007e82013-02-17 18:46:40 +00003691 {
3692 Image
3693 *image;
3694
3695 RectangleInfo
3696 source_geometry;
3697
3698 source_geometry.width=mask_image->columns;
3699 source_geometry.height=mask_image->rows;
3700 source_geometry.x=(-geometry.x);
3701 source_geometry.y=(-geometry.y);
3702 geometry.x=0;
3703 geometry.y=0;
3704 image=ExtentImage(source_image,&source_geometry,_exception);
3705 if (image != (Image *) NULL)
3706 {
3707 source_image=DestroyImage(source_image);
3708 source_image=image;
3709 }
3710 status&=CompositeImage(source_image,mask_image,
3711 IntensityCompositeOp,MagickTrue,0,0,_exception);
3712 }
cristyfe831852013-02-12 14:56:07 +00003713 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003714 }
cristyfe831852013-02-12 14:56:07 +00003715 status&=CompositeImage(new_images,source_image,compose,clip_to_self,
cristyfeb3e962012-03-29 17:25:55 +00003716 geometry.x,geometry.y,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003717 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003718 break;
3719 }
anthonyebb73a22012-03-22 14:25:52 +00003720 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003721 }
3722 case 'd':
3723 {
anthonyafa3dfc2012-03-03 11:31:30 +00003724 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003725 {
anthony464f1c42012-04-22 08:51:01 +00003726 CLIWandWarnReplaced("-layer CompareAny");
anthonyafa3dfc2012-03-03 11:31:30 +00003727 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003728 break;
3729 }
anthonyafa3dfc2012-03-03 11:31:30 +00003730 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003731 {
anthonyafa3dfc2012-03-03 11:31:30 +00003732 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003733 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003734 else
anthony92c93bd2012-03-19 14:02:47 +00003735 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003736 break;
3737 }
anthonyafa3dfc2012-03-03 11:31:30 +00003738 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003739 {
anthonyafa3dfc2012-03-03 11:31:30 +00003740 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003741 {
3742 const char
3743 *p;
3744
3745 size_t
3746 number_duplicates;
3747
anthony7bcfe7f2012-03-30 14:01:22 +00003748 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003749 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3750 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003751 number_duplicates=(size_t) StringToLong(arg1);
3752 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003753 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003754 new_images=DuplicateImages(_images,number_duplicates,"-1",
3755 _exception);
anthony805a2d42011-09-25 08:25:12 +00003756 else
anthony92c93bd2012-03-19 14:02:47 +00003757 new_images=DuplicateImages(_images,number_duplicates,p,
3758 _exception);
anthony805a2d42011-09-25 08:25:12 +00003759 }
anthonyafa3dfc2012-03-03 11:31:30 +00003760 else
anthony92c93bd2012-03-19 14:02:47 +00003761 new_images=DuplicateImages(_images,1,"-1",_exception);
3762 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003763 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003764 break;
3765 }
anthonyebb73a22012-03-22 14:25:52 +00003766 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003767 }
3768 case 'e':
3769 {
anthonyafa3dfc2012-03-03 11:31:30 +00003770 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003771 {
anthony2a0ec8c2012-03-24 04:35:56 +00003772 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3773 if ( parse < 0 )
3774 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3775 option,arg1);
3776 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3777 _exception);
anthony805a2d42011-09-25 08:25:12 +00003778 break;
3779 }
anthonyebb73a22012-03-22 14:25:52 +00003780 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003781 }
3782 case 'f':
3783 {
anthonyafa3dfc2012-03-03 11:31:30 +00003784 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003785 {
anthonya322a832013-04-27 06:28:03 +00003786 new_images=ForwardFourierTransformImage(_images,IsNormalOp,_exception);
anthony805a2d42011-09-25 08:25:12 +00003787 break;
3788 }
anthonyafa3dfc2012-03-03 11:31:30 +00003789 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003790 {
anthony319dac62012-03-06 04:12:44 +00003791 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003792 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003793 break;
3794 }
anthonyafa3dfc2012-03-03 11:31:30 +00003795 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003796 {
anthony92c93bd2012-03-19 14:02:47 +00003797 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003798 break;
3799 }
anthonyebb73a22012-03-22 14:25:52 +00003800 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003801 }
3802 case 'h':
3803 {
anthonyafa3dfc2012-03-03 11:31:30 +00003804 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003805 {
anthony31f1bf72012-01-30 12:37:22 +00003806 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003807 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003808 */
anthony805a2d42011-09-25 08:25:12 +00003809 Image
anthony31f1bf72012-01-30 12:37:22 +00003810 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003811
anthony92c93bd2012-03-19 14:02:47 +00003812 new_images=RemoveFirstImageFromList(&_images);
3813 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003814 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003815 break;
anthony92c93bd2012-03-19 14:02:47 +00003816 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003817 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003818 break;
3819 }
anthonyebb73a22012-03-22 14:25:52 +00003820 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003821 }
3822 case 'i':
3823 {
anthonyafa3dfc2012-03-03 11:31:30 +00003824 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003825 {
3826 Image
anthony805a2d42011-09-25 08:25:12 +00003827 *magnitude_image,
3828 *phase_image;
3829
anthony92c93bd2012-03-19 14:02:47 +00003830 magnitude_image=RemoveFirstImageFromList(&_images);
3831 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003832 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003833 if (phase_image == (Image *) NULL)
3834 break;
3835 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthonya322a832013-04-27 06:28:03 +00003836 IsNormalOp,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003837 magnitude_image=DestroyImage(magnitude_image);
3838 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003839 break;
3840 }
anthonyafa3dfc2012-03-03 11:31:30 +00003841 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003842 {
3843 Image
anthony31f1bf72012-01-30 12:37:22 +00003844 *insert_image,
3845 *index_image;
3846
3847 ssize_t
3848 index;
anthony805a2d42011-09-25 08:25:12 +00003849
anthony7bcfe7f2012-03-30 14:01:22 +00003850 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00003851 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003852 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003853 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003854 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003855 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003856 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003857 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003858 PrependImageToList(&_images,insert_image);
3859 else if (index == (ssize_t) GetImageListLength(_images))
3860 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003861 else
anthony43f425d2012-02-26 12:58:58 +00003862 {
anthony92c93bd2012-03-19 14:02:47 +00003863 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003864 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00003865 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00003866 InsertImageInList(&index_image,insert_image);
3867 }
anthony92c93bd2012-03-19 14:02:47 +00003868 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003869 break;
3870 }
anthonyebb73a22012-03-22 14:25:52 +00003871 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003872 }
3873 case 'l':
3874 {
anthonyafa3dfc2012-03-03 11:31:30 +00003875 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003876 {
anthonyfe1aa782012-03-24 13:43:04 +00003877 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3878 if ( parse < 0 )
3879 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3880 option,arg1);
cristya0417062012-09-02 23:34:56 +00003881 switch ((LayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00003882 {
3883 case CoalesceLayer:
3884 {
anthony92c93bd2012-03-19 14:02:47 +00003885 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003886 break;
3887 }
3888 case CompareAnyLayer:
3889 case CompareClearLayer:
3890 case CompareOverlayLayer:
3891 default:
3892 {
cristya0417062012-09-02 23:34:56 +00003893 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00003894 _exception);
anthony805a2d42011-09-25 08:25:12 +00003895 break;
3896 }
3897 case MergeLayer:
3898 case FlattenLayer:
3899 case MosaicLayer:
3900 case TrimBoundsLayer:
3901 {
cristya0417062012-09-02 23:34:56 +00003902 new_images=MergeImageLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00003903 _exception);
anthony805a2d42011-09-25 08:25:12 +00003904 break;
3905 }
3906 case DisposeLayer:
3907 {
anthony92c93bd2012-03-19 14:02:47 +00003908 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003909 break;
3910 }
3911 case OptimizeImageLayer:
3912 {
anthony92c93bd2012-03-19 14:02:47 +00003913 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003914 break;
3915 }
3916 case OptimizePlusLayer:
3917 {
anthony92c93bd2012-03-19 14:02:47 +00003918 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003919 break;
3920 }
3921 case OptimizeTransLayer:
3922 {
anthony92c93bd2012-03-19 14:02:47 +00003923 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003924 break;
3925 }
3926 case RemoveDupsLayer:
3927 {
anthony92c93bd2012-03-19 14:02:47 +00003928 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003929 break;
3930 }
3931 case RemoveZeroLayer:
3932 {
anthony92c93bd2012-03-19 14:02:47 +00003933 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003934 break;
3935 }
3936 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003937 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003938 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003939 if (new_images == (Image *) NULL)
3940 break;
anthony92c93bd2012-03-19 14:02:47 +00003941 _images=DestroyImageList(_images);
3942 _images=OptimizeImageLayers(new_images,_exception);
3943 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003944 break;
3945 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00003946 OptimizeImageTransparency(_images,_exception);
3947 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3948 _exception);
anthony805a2d42011-09-25 08:25:12 +00003949 break;
3950 }
3951 case CompositeLayer:
3952 {
anthony805a2d42011-09-25 08:25:12 +00003953 Image
3954 *source;
3955
3956 RectangleInfo
3957 geometry;
3958
anthony31f1bf72012-01-30 12:37:22 +00003959 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003960 compose;
3961
3962 const char*
3963 value;
3964
anthony92c93bd2012-03-19 14:02:47 +00003965 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003966 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003967 if (value != (const char *) NULL)
3968 compose=(CompositeOperator) ParseCommandOption(
3969 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003970
anthony31f1bf72012-01-30 12:37:22 +00003971 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00003972 source=_images;
anthony805a2d42011-09-25 08:25:12 +00003973 while (source != (Image *) NULL)
3974 {
3975 source=GetNextImageInList(source);
3976 if ((source != (Image *) NULL) &&
3977 (LocaleCompare(source->magick,"NULL") == 0))
3978 break;
3979 }
3980 if (source != (Image *) NULL)
3981 {
3982 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3983 (GetNextImageInList(source) == (Image *) NULL))
3984 source=(Image *) NULL;
3985 else
anthony31f1bf72012-01-30 12:37:22 +00003986 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003987 source=SplitImageList(source->previous);
3988 DeleteImageFromList(&source);
3989 }
3990 }
3991 if (source == (Image *) NULL)
3992 {
anthony92c93bd2012-03-19 14:02:47 +00003993 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00003994 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003995 break;
3996 }
anthony31f1bf72012-01-30 12:37:22 +00003997 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00003998 SetGeometry(_images,&geometry);
3999 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004000 geometry.width=source->page.width != 0 ?
4001 source->page.width : source->columns;
4002 geometry.height=source->page.height != 0 ?
4003 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004004 GravityAdjustGeometry(_images->page.width != 0 ?
4005 _images->page.width : _images->columns,
4006 _images->page.height != 0 ? _images->page.height :
4007 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004008
anthony31f1bf72012-01-30 12:37:22 +00004009 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004010 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4011 _exception);
anthony805a2d42011-09-25 08:25:12 +00004012 source=DestroyImageList(source);
4013 break;
4014 }
4015 }
anthony805a2d42011-09-25 08:25:12 +00004016 break;
4017 }
anthonyebb73a22012-03-22 14:25:52 +00004018 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004019 }
4020 case 'm':
4021 {
anthonyafa3dfc2012-03-03 11:31:30 +00004022 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004023 {
anthony464f1c42012-04-22 08:51:01 +00004024 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00004025 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004026 break;
4027 }
anthonyafa3dfc2012-03-03 11:31:30 +00004028 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004029 {
4030 Image
4031 *morph_image;
4032
anthony7bcfe7f2012-03-30 14:01:22 +00004033 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004034 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004035 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4036 _exception);
anthony805a2d42011-09-25 08:25:12 +00004037 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004038 break;
anthony92c93bd2012-03-19 14:02:47 +00004039 _images=DestroyImageList(_images);
4040 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004041 break;
4042 }
anthonyafa3dfc2012-03-03 11:31:30 +00004043 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004044 {
anthony319dac62012-03-06 04:12:44 +00004045 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00004046 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004047 break;
4048 }
anthonyebb73a22012-03-22 14:25:52 +00004049 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004050 }
4051 case 'p':
4052 {
cristy02016cf2012-11-13 01:14:41 +00004053 if (LocaleCompare("poly",option+1) == 0)
4054 {
4055 double
4056 *args;
4057
4058 ssize_t
4059 count;
4060
4061 /* convert argument string into an array of doubles */
4062 args = StringToArrayOfDoubles(arg2,&count,_exception);
4063 if (args == (double *)NULL )
4064 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
4065 new_images=PolynomialImage(_images,count >> 1,args,_exception);
4066 args=(double *) RelinquishMagickMemory(args);
4067 break;
4068 }
anthonyafa3dfc2012-03-03 11:31:30 +00004069 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004070 {
anthonyb1d483a2012-04-14 12:53:56 +00004071 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00004072 char
4073 **arguments;
4074
4075 int
4076 j,
4077 number_arguments;
4078
anthony31f1bf72012-01-30 12:37:22 +00004079 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004080 if (arguments == (char **) NULL)
4081 break;
anthony31f1bf72012-01-30 12:37:22 +00004082 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004083 {
4084 char
4085 breaker,
4086 quote,
4087 *token;
4088
4089 const char
4090 *arguments;
4091
4092 int
4093 next,
4094 status;
4095
4096 size_t
4097 length;
4098
4099 TokenInfo
4100 *token_info;
4101
4102 /*
anthony24aa8822012-03-11 00:56:06 +00004103 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004104 */
anthony31f1bf72012-01-30 12:37:22 +00004105 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004106 token=(char *) NULL;
4107 if (~length >= (MaxTextExtent-1))
4108 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4109 sizeof(*token));
4110 if (token == (char *) NULL)
4111 break;
4112 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004113 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004114 token_info=AcquireTokenInfo();
4115 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4116 "\"",'\0',&breaker,&next,&quote);
4117 token_info=DestroyTokenInfo(token_info);
4118 if (status == 0)
4119 {
4120 const char
4121 *argv;
4122
4123 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004124 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4125 _exception);
anthony805a2d42011-09-25 08:25:12 +00004126 }
4127 token=DestroyString(token);
4128 break;
4129 }
4130 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004131 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4132 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004133 for (j=0; j < number_arguments; j++)
4134 arguments[j]=DestroyString(arguments[j]);
4135 arguments=(char **) RelinquishMagickMemory(arguments);
4136 break;
4137 }
anthonyebb73a22012-03-22 14:25:52 +00004138 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004139 }
4140 case 'r':
4141 {
anthonyafa3dfc2012-03-03 11:31:30 +00004142 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004143 {
anthony92c93bd2012-03-19 14:02:47 +00004144 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004145 break;
4146 }
anthonyafa3dfc2012-03-03 11:31:30 +00004147 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004148 {
anthony92c93bd2012-03-19 14:02:47 +00004149 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004150 break;
4151 }
anthonyebb73a22012-03-22 14:25:52 +00004152 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004153 }
4154 case 's':
4155 {
anthonyafa3dfc2012-03-03 11:31:30 +00004156 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004157 {
anthonycd358fc2012-04-16 13:59:03 +00004158 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004159 ssize_t
4160 offset;
4161
anthony7bcfe7f2012-03-30 14:01:22 +00004162 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004163 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004164 offset=(ssize_t) StringToLong(arg1);
anthonya322a832013-04-27 06:28:03 +00004165 new_images=SmushImages(_images,IsNormalOp,offset,_exception);
anthonycd358fc2012-04-16 13:59:03 +00004166 break;
4167 }
4168 if (LocaleCompare("subimage",option+1) == 0)
4169 {
4170 Image
4171 *base_image,
4172 *compare_image;
4173
4174 const char *
4175 value;
4176
4177 MetricType
4178 metric;
4179
4180 double
4181 similarity;
4182
4183 RectangleInfo
4184 offset;
4185
4186 base_image=GetImageFromList(_images,0);
4187 compare_image=GetImageFromList(_images,1);
4188
4189 /* Comparision Metric */
4190 metric=UndefinedMetric;
4191 value=GetImageOption(_image_info,"metric");
4192 if (value != (const char *) NULL)
4193 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4194 MagickFalse,value);
4195
cristy99fcec42013-03-15 21:37:59 +00004196 new_images=SimilarityImage(base_image,compare_image,metric,0.0,
anthonycd358fc2012-04-16 13:59:03 +00004197 &offset,&similarity,_exception);
4198
4199 if ( new_images != (Image *)NULL ) {
4200 char
4201 result[MaxTextExtent];
4202
4203 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
4204 (void) SetImageProperty(new_images,"subimage:similarity",result,
4205 _exception);
4206 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4207 (long) offset.x);
4208 (void) SetImageProperty(new_images,"subimage:x",result,
4209 _exception);
4210 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4211 (long) offset.y);
4212 (void) SetImageProperty(new_images,"subimage:y",result,
4213 _exception);
4214 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
4215 (unsigned long) offset.width,(unsigned long) offset.height,
4216 (long) offset.x,(long) offset.y);
4217 (void) SetImageProperty(new_images,"subimage:offset",result,
4218 _exception);
4219 }
anthony805a2d42011-09-25 08:25:12 +00004220 break;
4221 }
anthony0ea037a2012-04-03 12:14:39 +00004222 if (LocaleCompare("swap",option+1) == 0) {
4223 Image
4224 *p,
4225 *q,
4226 *swap;
anthony805a2d42011-09-25 08:25:12 +00004227
anthony0ea037a2012-04-03 12:14:39 +00004228 ssize_t
4229 index,
4230 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004231
cristy6b36c942013-02-17 00:36:24 +00004232 index=(-1);
4233 swap_index=(-2);
anthony0ea037a2012-04-03 12:14:39 +00004234 if (IfNormalOp) {
4235 GeometryInfo
4236 geometry_info;
4237
4238 MagickStatusType
4239 flags;
4240
4241 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004242 flags=ParseGeometry(arg1,&geometry_info);
cristy90fbd1c2013-02-17 00:35:35 +00004243 if ((flags & RhoValue) == 0)
anthonyb1e21ed2012-04-20 12:43:12 +00004244 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004245 index=(ssize_t) geometry_info.rho;
4246 if ((flags & SigmaValue) != 0)
4247 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004248 }
anthony0ea037a2012-04-03 12:14:39 +00004249 p=GetImageFromList(_images,index);
4250 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004251 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4252 if (IfNormalOp)
4253 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4254 else
4255 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4256 }
anthony0ea037a2012-04-03 12:14:39 +00004257 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004258 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004259 swap=CloneImage(p,0,0,MagickTrue,_exception);
4260 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4261 ReplaceImageInList(&q,swap);
4262 _images=GetFirstImageInList(q);
4263 break;
4264 }
anthonyebb73a22012-03-22 14:25:52 +00004265 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004266 }
anthony805a2d42011-09-25 08:25:12 +00004267 default:
anthonyebb73a22012-03-22 14:25:52 +00004268 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004269 }
anthony964d28e2012-05-17 23:39:46 +00004270
4271 /* clean up percent escape interpreted strings */
4272 if (arg1 != arg1n )
4273 arg1=DestroyString((char *)arg1);
4274 if (arg2 != arg2n )
4275 arg2=DestroyString((char *)arg2);
4276
4277 /* if new image list generated, replace existing image list */
anthony31f1bf72012-01-30 12:37:22 +00004278 if (new_images == (Image *) NULL)
cristyfe831852013-02-12 14:56:07 +00004279 return(status);
anthony964d28e2012-05-17 23:39:46 +00004280 _images=DestroyImageList(_images);
anthony92c93bd2012-03-19 14:02:47 +00004281 _images=GetFirstImageInList(new_images);
cristyfe831852013-02-12 14:56:07 +00004282 return(status);
anthony31f1bf72012-01-30 12:37:22 +00004283
anthony92c93bd2012-03-19 14:02:47 +00004284#undef _image_info
4285#undef _images
4286#undef _exception
4287#undef _draw_info
4288#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004289#undef IfNormalOp
4290#undef IfPlusOp
anthonya322a832013-04-27 06:28:03 +00004291#undef IsNormalOp
anthony805a2d42011-09-25 08:25:12 +00004292}
anthony43f425d2012-02-26 12:58:58 +00004293
4294/*
4295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4296% %
4297% %
4298% %
anthony964d28e2012-05-17 23:39:46 +00004299+ C L I N o I m a g e O p e r a t i o n s %
anthony43f425d2012-02-26 12:58:58 +00004300% %
4301% %
4302% %
4303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4304%
anthony464f1c42012-04-22 08:51:01 +00004305% CLINoImageOperator() Applies operations that may not actually need images
anthony964d28e2012-05-17 23:39:46 +00004306% in an image list.
anthony43f425d2012-02-26 12:58:58 +00004307%
anthony4837ac22012-05-18 23:39:48 +00004308% The classic operators of this type is "-read", which actually creates
4309% images even when no images are present. Or image stack operators, which
4310% can be applied (push or pop) to an empty image list.
anthonyafa3dfc2012-03-03 11:31:30 +00004311%
anthony4837ac22012-05-18 23:39:48 +00004312% Note that these operators may involve other special 'option' prefix
4313% characters other than '-' or '+', namely parenthesis and braces.
anthony43f425d2012-02-26 12:58:58 +00004314%
anthony464f1c42012-04-22 08:51:01 +00004315% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004316%
anthony464f1c42012-04-22 08:51:01 +00004317% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4318% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004319%
4320% A description of each parameter follows:
4321%
anthonyc7994672012-11-17 05:33:27 +00004322% o cli_wand: the main CLI Wand to use. (sometimes not required)
anthony43f425d2012-02-26 12:58:58 +00004323%
4324% o option: The special option (with any switch char) to process
4325%
anthony464f1c42012-04-22 08:51:01 +00004326% o arg1 & arg2: Argument for option, if required
4327% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004328%
4329*/
cristyfe831852013-02-12 14:56:07 +00004330WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
anthonya322a832013-04-27 06:28:03 +00004331 const char *option,const char *arg1n,const char *arg2n)
anthony43f425d2012-02-26 12:58:58 +00004332{
anthonya322a832013-04-27 06:28:03 +00004333 const char /* percent escaped versions of the args */
anthony4837ac22012-05-18 23:39:48 +00004334 *arg1,
4335 *arg2;
anthony4837ac22012-05-18 23:39:48 +00004336
anthony8226e722012-04-05 14:25:46 +00004337#define _image_info (cli_wand->wand.image_info)
4338#define _images (cli_wand->wand.images)
4339#define _exception (cli_wand->wand.exception)
anthonya322a832013-04-27 06:28:03 +00004340#define _process_flags (cli_wand->process_flags)
4341#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthony8226e722012-04-05 14:25:46 +00004342#define IfNormalOp (*option=='-')
4343#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004344
4345 assert(cli_wand != (MagickCLI *) NULL);
4346 assert(cli_wand->signature == WandSignature);
4347 assert(cli_wand->wand.signature == WandSignature);
anthonya322a832013-04-27 06:28:03 +00004348
anthony7bcfe7f2012-03-30 14:01:22 +00004349 if (IfMagickTrue(cli_wand->wand.debug))
anthonya322a832013-04-27 06:28:03 +00004350 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
4351 "- NoImage Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
anthony43f425d2012-02-26 12:58:58 +00004352
anthony4837ac22012-05-18 23:39:48 +00004353 arg1 = arg1n;
4354 arg2 = arg2n;
anthonya322a832013-04-27 06:28:03 +00004355
4356 /* Interpret Percent Escapes in Arguments - using first image */
anthony4837ac22012-05-18 23:39:48 +00004357 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4358 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4359 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4360 /* Interpret Percent escapes in argument 1 */
4361 if (arg1n != (char *) NULL) {
4362 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4363 if (arg1 == (char *) NULL) {
4364 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4365 arg1=arg1n; /* use the given argument as is */
4366 }
4367 }
4368 if (arg2n != (char *) NULL) {
4369 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4370 if (arg2 == (char *) NULL) {
4371 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4372 arg2=arg2n; /* use the given argument as is */
4373 }
4374 }
4375 }
4376#undef _process_flags
4377#undef _option_type
anthony4837ac22012-05-18 23:39:48 +00004378
4379 do { /* break to exit code */
4380 /*
4381 No-op options (ignore these)
4382 */
anthonyc7994672012-11-17 05:33:27 +00004383 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
anthony4837ac22012-05-18 23:39:48 +00004384 break;
4385 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4386 break;
anthonyc7994672012-11-17 05:33:27 +00004387 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4388 break;
4389 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
anthony4837ac22012-05-18 23:39:48 +00004390 break;
4391 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4392 break;
4393 /*
4394 Image Reading
4395 */
4396 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4397 ( LocaleCompare("--",option) == 0 ) ) {
4398 /* Do Glob filename Expansion for 'arg1' then read all images.
4399 *
4400 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4401 * (but attaching to the filenames in the generated argument list) any
4402 * [...] read modifiers that may be present.
4403 *
4404 * For example: It will expand '*.gif[20x20]' into a list such as
4405 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4406 *
4407 * NOTE: In IMv6 this was done globally across all images. This
4408 * meant you could include IM options in '@filename' lists, but you
4409 * could not include comments. Doing it only for image read makes
4410 * it far more secure.
4411 *
4412 * Note: arguments do not have percent escapes expanded for security
4413 * reasons.
4414 */
4415 int argc;
4416 char **argv;
4417 ssize_t i;
4418
4419 argc = 1;
4420 argv = (char **) &arg1;
4421
4422 /* Expand 'glob' expressions in the given filename.
4423 Expansion handles any 'coder:' prefix, or read modifiers attached
4424 to the filename, including them in the resulting expanded list.
4425 */
4426 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4427 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4428 option,GetExceptionMessage(errno));
4429
4430 /* loop over expanded filename list, and read then all in */
4431 for (i=0; i<argc; i++) {
4432 Image *
4433 new_images;
4434 if (IfMagickTrue(_image_info->ping))
4435 new_images=PingImages(_image_info,argv[i],_exception);
4436 else
4437 new_images=ReadImages(_image_info,argv[i],_exception);
4438 AppendImageToList(&_images, new_images);
4439 }
4440 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4441 break;
4442 }
4443 /*
4444 Image Writing
4445 Note: Writing a empty image list is valid in specific cases
4446 */
4447 if (LocaleCompare("write",option+1) == 0) {
4448 /* Note: arguments do not have percent escapes expanded */
4449 char
4450 key[MaxTextExtent];
4451
4452 Image
4453 *write_images;
4454
4455 ImageInfo
4456 *write_info;
4457
4458 /* Need images, unless a "null:" output coder is used */
anthonya322a832013-04-27 06:28:03 +00004459 if ( _images == (Image *) NULL ) {
anthony4837ac22012-05-18 23:39:48 +00004460 if ( LocaleCompare(arg1,"null:") == 0 )
4461 break;
4462 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4463 }
4464
4465 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4466 (void) DeleteImageRegistry(key);
4467 write_images=_images;
4468 if (IfPlusOp)
4469 write_images=CloneImageList(_images,_exception);
4470 write_info=CloneImageInfo(_image_info);
4471 (void) WriteImages(write_info,write_images,arg1,_exception);
4472 write_info=DestroyImageInfo(write_info);
4473 if (IfPlusOp)
4474 write_images=DestroyImageList(write_images);
4475 break;
4476 }
4477 /*
4478 Parenthesis and Brace operations
4479 */
4480 if (LocaleCompare("(",option) == 0) {
4481 /* stack 'push' images */
4482 Stack
4483 *node;
4484
4485 size_t
4486 size;
4487
4488 size=0;
4489 node=cli_wand->image_list_stack;
4490 for ( ; node != (Stack *)NULL; node=node->next)
4491 size++;
4492 if ( size >= MAX_STACK_DEPTH )
4493 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4494 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4495 if (node == (Stack *) NULL)
4496 CLIWandExceptionBreak(ResourceLimitFatalError,
4497 "MemoryAllocationFailed",option);
4498 node->data = (void *)cli_wand->wand.images;
anthony4837ac22012-05-18 23:39:48 +00004499 node->next = cli_wand->image_list_stack;
4500 cli_wand->image_list_stack = node;
anthonya322a832013-04-27 06:28:03 +00004501 cli_wand->wand.images = NewImageList();
anthony4837ac22012-05-18 23:39:48 +00004502
4503 /* handle respect-parenthesis */
4504 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4505 "respect-parenthesis"))))
4506 option="{"; /* fall-thru so as to push image settings too */
anthony52bef752012-03-27 13:54:47 +00004507 else
anthony4837ac22012-05-18 23:39:48 +00004508 break;
anthonya322a832013-04-27 06:28:03 +00004509 /* fall thru to operation */
anthony52bef752012-03-27 13:54:47 +00004510 }
anthony4837ac22012-05-18 23:39:48 +00004511 if (LocaleCompare("{",option) == 0) {
4512 /* stack 'push' of image_info settings */
4513 Stack
4514 *node;
anthony8226e722012-04-05 14:25:46 +00004515
anthony4837ac22012-05-18 23:39:48 +00004516 size_t
4517 size;
anthony8226e722012-04-05 14:25:46 +00004518
anthony4837ac22012-05-18 23:39:48 +00004519 size=0;
4520 node=cli_wand->image_info_stack;
4521 for ( ; node != (Stack *)NULL; node=node->next)
4522 size++;
4523 if ( size >= MAX_STACK_DEPTH )
4524 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4525 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4526 if (node == (Stack *) NULL)
4527 CLIWandExceptionBreak(ResourceLimitFatalError,
4528 "MemoryAllocationFailed",option);
anthony8226e722012-04-05 14:25:46 +00004529
anthony4837ac22012-05-18 23:39:48 +00004530 node->data = (void *)cli_wand->wand.image_info;
anthonya322a832013-04-27 06:28:03 +00004531 node->next = cli_wand->image_info_stack;
4532
4533 cli_wand->image_info_stack = node;
anthony4837ac22012-05-18 23:39:48 +00004534 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4535 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4536 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4537 option);
4538 cli_wand->wand.image_info = (ImageInfo *)node->data;
4539 node = (Stack *)RelinquishMagickMemory(node);
4540 break;
4541 }
4542
anthony4837ac22012-05-18 23:39:48 +00004543 break;
anthony8226e722012-04-05 14:25:46 +00004544 }
anthony4837ac22012-05-18 23:39:48 +00004545 if (LocaleCompare(")",option) == 0) {
4546 /* pop images from stack */
4547 Stack
4548 *node;
anthony8226e722012-04-05 14:25:46 +00004549
anthony4837ac22012-05-18 23:39:48 +00004550 node = (Stack *)cli_wand->image_list_stack;
4551 if ( node == (Stack *)NULL)
4552 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4553 cli_wand->image_list_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004554
anthony4837ac22012-05-18 23:39:48 +00004555 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4556 cli_wand->wand.images= (Image *)node->data;
4557 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004558
anthony4837ac22012-05-18 23:39:48 +00004559 /* handle respect-parenthesis - of the previous 'pushed' settings */
4560 node = cli_wand->image_info_stack;
4561 if ( node != (Stack *)NULL)
4562 {
4563 if (IfMagickTrue(IsStringTrue(GetImageOption(
4564 cli_wand->wand.image_info,"respect-parenthesis"))))
4565 option="}"; /* fall-thru so as to pop image settings too */
4566 else
4567 break;
4568 }
4569 else
4570 break;
4571 /* fall thru to next if */
4572 }
4573 if (LocaleCompare("}",option) == 0) {
4574 /* pop image_info settings from stack */
4575 Stack
4576 *node;
anthony43f425d2012-02-26 12:58:58 +00004577
anthony4837ac22012-05-18 23:39:48 +00004578 node = (Stack *)cli_wand->image_info_stack;
4579 if ( node == (Stack *)NULL)
4580 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4581 cli_wand->image_info_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004582
anthony4837ac22012-05-18 23:39:48 +00004583 (void) DestroyImageInfo(cli_wand->wand.image_info);
anthony43f425d2012-02-26 12:58:58 +00004584 cli_wand->wand.image_info = (ImageInfo *)node->data;
4585 node = (Stack *)RelinquishMagickMemory(node);
anthony4837ac22012-05-18 23:39:48 +00004586
4587 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4588 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4589 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4590
4591 break;
4592 }
anthonya322a832013-04-27 06:28:03 +00004593 if (LocaleCompare("print",option+1) == 0)
4594 {
4595 (void) FormatLocaleFile(stdout,"%s",arg1);
4596 break;
4597 }
anthonyc7994672012-11-17 05:33:27 +00004598 if (LocaleCompare("set",option+1) == 0)
4599 {
anthonya322a832013-04-27 06:28:03 +00004600 /* Settings are applied to each image in memory in turn (if any).
4601 While a option: only need to be applied once globally.
4602
4603 NOTE: rguments have not been automatically percent expaneded
anthonyc7994672012-11-17 05:33:27 +00004604 */
anthonya322a832013-04-27 06:28:03 +00004605
4606 /* escape the 'key' once only, using first image. */
4607 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4608 if (arg1 == (char *) NULL)
4609 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4610 option);
anthonyc7994672012-11-17 05:33:27 +00004611
4612 if (LocaleNCompare(arg1,"registry:",9) == 0)
4613 {
4614 if (IfPlusOp)
4615 {
4616 (void) DeleteImageRegistry(arg1+9);
anthonya322a832013-04-27 06:28:03 +00004617 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004618 break;
4619 }
anthonya322a832013-04-27 06:28:03 +00004620 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4621 if (arg2 == (char *) NULL) {
4622 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004623 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4624 option);
anthonya322a832013-04-27 06:28:03 +00004625 }
4626 (void) SetImageRegistry(StringRegistryType,arg1+9,arg2,_exception);
4627 arg1=DestroyString((char *)arg1);
4628 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004629 break;
4630 }
4631 if (LocaleNCompare(arg1,"option:",7) == 0)
4632 {
4633 /* delete equivelent artifact from all images (if any) */
anthonya322a832013-04-27 06:28:03 +00004634 if (_images != (Image *)NULL)
4635 {
4636 MagickResetIterator(&cli_wand->wand);
4637 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4638 (void) DeleteImageArtifact(_images,arg1+7);
4639 MagickResetIterator(&cli_wand->wand);
4640 }
anthonyc7994672012-11-17 05:33:27 +00004641 /* now set/delete the global option as needed */
anthonya322a832013-04-27 06:28:03 +00004642 /* FUTURE: make escapes in a global 'option:' delayed */
4643 arg2=(char *)NULL;
4644 if (IfNormalOp)
4645 {
4646 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4647 if (arg2 == (char *) NULL)
4648 CLIWandExceptionBreak(OptionWarning,
4649 "InterpretPropertyFailure",option);
4650 }
4651 (void) SetImageOption(_image_info,arg1+7,arg2);
4652 arg1=DestroyString((char *)arg1);
4653 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004654 break;
4655 }
anthonya322a832013-04-27 06:28:03 +00004656 /* Set Artifacts/Properties/Attributes all images (required) */
4657 if ( _images == (Image *) NULL )
4658 CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
4659
anthonyc7994672012-11-17 05:33:27 +00004660 MagickResetIterator(&cli_wand->wand);
4661 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4662 {
anthonya322a832013-04-27 06:28:03 +00004663 arg2=(char *)NULL;
4664 if (IfNormalOp)
4665 {
4666 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4667 if (arg2 == (char *) NULL)
4668 CLIWandExceptionBreak(OptionWarning,
4669 "InterpretPropertyFailure",option);
4670 }
4671 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4672 (void) SetImageArtifact(_images,arg1+9,arg2);
4673 else if (LocaleNCompare(arg1,"property:",9) == 0)
4674 (void) SetImageProperty(_images,arg1+9,arg2,_exception);
4675 else
4676 (void) SetImageProperty(_images,arg1,arg2,_exception);
4677 arg2=DestroyString((char *)arg2);
anthonyc7994672012-11-17 05:33:27 +00004678 }
4679 MagickResetIterator(&cli_wand->wand);
anthonya322a832013-04-27 06:28:03 +00004680 arg1=DestroyString((char *)arg1);
anthonyc7994672012-11-17 05:33:27 +00004681 break;
4682 }
anthony4837ac22012-05-18 23:39:48 +00004683 if (LocaleCompare("clone",option+1) == 0) {
4684 Image
4685 *new_images;
4686
4687 if (*option == '+')
4688 arg1="-1";
4689 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4690 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
4691 if ( cli_wand->image_list_stack == (Stack *)NULL)
4692 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4693 new_images = (Image *)cli_wand->image_list_stack->data;
4694 if (new_images == (Image *) NULL)
4695 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4696 new_images=CloneImages(new_images,arg1,_exception);
4697 if (new_images == (Image *) NULL)
4698 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4699 AppendImageToList(&_images,new_images);
4700 break;
4701 }
4702 /*
cristy422d5502012-12-22 22:20:57 +00004703 Informational Operations.
anthony4837ac22012-05-18 23:39:48 +00004704
anthonyc7994672012-11-17 05:33:27 +00004705 Note that these do not require either a cli-wand or images!
4706 Though currently a cli-wand much be provided regardless.
anthony4837ac22012-05-18 23:39:48 +00004707 */
cristy422d5502012-12-22 22:20:57 +00004708 if (LocaleCompare("version",option+1) == 0)
4709 {
cristy4f7a6132012-12-23 00:35:19 +00004710 ListMagickVersion(stdout);
cristy422d5502012-12-22 22:20:57 +00004711 break;
4712 }
anthony4837ac22012-05-18 23:39:48 +00004713 if (LocaleCompare("list",option+1) == 0) {
4714 /*
anthonyc7994672012-11-17 05:33:27 +00004715 FUTURE: This 'switch' should really be part of MagickCore
anthony4837ac22012-05-18 23:39:48 +00004716 */
4717 ssize_t
4718 list;
4719
4720 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4721 if ( list < 0 ) {
4722 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4723 break;
4724 }
4725 switch (list)
4726 {
4727 case MagickCoderOptions:
4728 {
4729 (void) ListCoderInfo((FILE *) NULL,_exception);
4730 break;
4731 }
4732 case MagickColorOptions:
4733 {
4734 (void) ListColorInfo((FILE *) NULL,_exception);
4735 break;
4736 }
4737 case MagickConfigureOptions:
4738 {
4739 (void) ListConfigureInfo((FILE *) NULL,_exception);
4740 break;
4741 }
4742 case MagickDelegateOptions:
4743 {
4744 (void) ListDelegateInfo((FILE *) NULL,_exception);
4745 break;
4746 }
4747 case MagickFontOptions:
4748 {
4749 (void) ListTypeInfo((FILE *) NULL,_exception);
4750 break;
4751 }
4752 case MagickFormatOptions:
4753 (void) ListMagickInfo((FILE *) NULL,_exception);
4754 break;
4755 case MagickLocaleOptions:
4756 (void) ListLocaleInfo((FILE *) NULL,_exception);
4757 break;
4758 case MagickLogOptions:
4759 (void) ListLogInfo((FILE *) NULL,_exception);
4760 break;
4761 case MagickMagicOptions:
4762 (void) ListMagicInfo((FILE *) NULL,_exception);
4763 break;
4764 case MagickMimeOptions:
4765 (void) ListMimeInfo((FILE *) NULL,_exception);
4766 break;
4767 case MagickModuleOptions:
4768 (void) ListModuleInfo((FILE *) NULL,_exception);
4769 break;
4770 case MagickPolicyOptions:
4771 (void) ListPolicyInfo((FILE *) NULL,_exception);
4772 break;
4773 case MagickResourceOptions:
4774 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4775 break;
4776 case MagickThresholdOptions:
4777 (void) ListThresholdMaps((FILE *) NULL,_exception);
4778 break;
4779 default:
4780 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4781 _exception);
4782 break;
4783 }
4784 break;
anthony43f425d2012-02-26 12:58:58 +00004785 }
anthony8226e722012-04-05 14:25:46 +00004786
anthony4837ac22012-05-18 23:39:48 +00004787 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony8226e722012-04-05 14:25:46 +00004788
anthony4837ac22012-05-18 23:39:48 +00004789 } while (0); /* break to exit code. */
anthony43f425d2012-02-26 12:58:58 +00004790
anthony4837ac22012-05-18 23:39:48 +00004791 /* clean up percent escape interpreted strings */
4792 if (arg1 != arg1n )
4793 arg1=DestroyString((char *)arg1);
4794 if (arg2 != arg2n )
4795 arg2=DestroyString((char *)arg2);
anthony43f425d2012-02-26 12:58:58 +00004796
anthony8226e722012-04-05 14:25:46 +00004797#undef _image_info
4798#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004799#undef _exception
anthony8226e722012-04-05 14:25:46 +00004800#undef IfNormalOp
4801#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004802}
anthony464f1c42012-04-22 08:51:01 +00004803
4804/*
4805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4806% %
4807% %
4808% %
anthony964d28e2012-05-17 23:39:46 +00004809+ C L I O p t i o n %
anthony464f1c42012-04-22 08:51:01 +00004810% %
4811% %
4812% %
4813%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4814%
4815% CLIOption() Processes the given option using the given CLI Magick Wand.
anthony964d28e2012-05-17 23:39:46 +00004816% The option arguments can be variable in number, though at this time no more
4817% that two is actually used by any option (this may change). Excess options
4818% are simply ignored.
anthony464f1c42012-04-22 08:51:01 +00004819%
4820% If the cli_wand->command pointer is non-null, then it is assumed that the
4821% option has already been search for up from the CommandOptions[] table in
anthony964d28e2012-05-17 23:39:46 +00004822% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
4823% routine will do the lookup instead. The pointer is reset afterward.
4824%
4825% This action allows the caller to lookup and pre-handle any 'special'
4826% options, (such as implicit reads) before calling this general option
4827% handler to deal with 'standard' command line options.
anthony464f1c42012-04-22 08:51:01 +00004828%
4829% The format of the CLIOption method is:
4830%
4831% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
4832%
4833% A description of each parameter follows:
4834%
4835% o cli_wand: the main CLI Wand to use.
4836%
4837% o option: The special option (with any switch char) to process
4838%
anthony964d28e2012-05-17 23:39:46 +00004839% o args: any required arguments for an option (variable number)
anthony464f1c42012-04-22 08:51:01 +00004840%
4841% Example Usage...
4842%
4843% CLIoption(cli_wand,"-read","rose:");
4844% CLIoption(cli_wand,"-virtual-pixel","transparent");
4845% CLIoption(cli_wand,"-distort","SRT:","30");
4846% CLIoption(cli_wand,"-write","rotated_rose.png");
4847%
4848*/
4849WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
4850{
anthonya322a832013-04-27 06:28:03 +00004851 const char /* extracted option args from args */
anthony464f1c42012-04-22 08:51:01 +00004852 *arg1,
4853 *arg2;
4854
4855 CommandOptionFlags
4856 option_type;
4857
4858 assert(cli_wand != (MagickCLI *) NULL);
4859 assert(cli_wand->signature == WandSignature);
4860 assert(cli_wand->wand.signature == WandSignature);
anthony464f1c42012-04-22 08:51:01 +00004861
anthony964d28e2012-05-17 23:39:46 +00004862 do { /* Break Code Block for error handling */
4863
4864 /* get information about option */
4865 if ( cli_wand->command == (const OptionInfo *) NULL )
4866 cli_wand->command = GetCommandOptionInfo(option);
anthony464f1c42012-04-22 08:51:01 +00004867#if 0
anthony964d28e2012-05-17 23:39:46 +00004868 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
4869 option, cli_wand->command->mnemonic );
anthony464f1c42012-04-22 08:51:01 +00004870#endif
anthony964d28e2012-05-17 23:39:46 +00004871 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthony464f1c42012-04-22 08:51:01 +00004872
anthony964d28e2012-05-17 23:39:46 +00004873 if ( option_type == UndefinedOptionFlag )
4874 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
anthony464f1c42012-04-22 08:51:01 +00004875
anthony964d28e2012-05-17 23:39:46 +00004876 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
anthony464f1c42012-04-22 08:51:01 +00004877
anthony964d28e2012-05-17 23:39:46 +00004878 /* depreciated options */
4879 if ( (option_type & DeprecateOptionFlag) != 0 )
4880 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
anthony464f1c42012-04-22 08:51:01 +00004881
anthony964d28e2012-05-17 23:39:46 +00004882 /* options that this module does not handle */
4883 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
4884 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
anthony464f1c42012-04-22 08:51:01 +00004885
anthony964d28e2012-05-17 23:39:46 +00004886 /* Get argument strings from VarArgs
anthonya322a832013-04-27 06:28:03 +00004887 How can you determine if enough arguments was supplied?
4888 What happens if not enough arguments were supplied?
4889 */
anthony964d28e2012-05-17 23:39:46 +00004890 { size_t
4891 count = cli_wand->command->type;
anthony464f1c42012-04-22 08:51:01 +00004892
anthony964d28e2012-05-17 23:39:46 +00004893 va_list
4894 operands;
anthony464f1c42012-04-22 08:51:01 +00004895
anthony964d28e2012-05-17 23:39:46 +00004896 va_start(operands,option);
anthony464f1c42012-04-22 08:51:01 +00004897
anthony964d28e2012-05-17 23:39:46 +00004898 arg1=arg2=NULL;
4899 if ( count >= 1 )
4900 arg1=(const char *) va_arg(operands, const char *);
4901 if ( count >= 2 )
4902 arg2=(const char *) va_arg(operands, const char *);
anthony464f1c42012-04-22 08:51:01 +00004903
anthony964d28e2012-05-17 23:39:46 +00004904 va_end(operands);
anthony52cb3df2012-04-24 03:29:32 +00004905#if 0
anthony964d28e2012-05-17 23:39:46 +00004906 (void) FormatLocaleFile(stderr,
4907 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
4908 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00004909#endif
anthony964d28e2012-05-17 23:39:46 +00004910 }
4911
4912 /*
4913 Call the appropriate option handler
4914 */
4915
4916 /* FUTURE: this is temporary - get 'settings' to handle distribution of
4917 settings to images attributes,proprieties,artifacts */
4918 if ( cli_wand->wand.images != (Image *)NULL )
4919 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4920 cli_wand->wand.exception);
4921
4922 if ( (option_type & SettingOptionFlags) != 0 ) {
4923 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
4924 // FUTURE: Sync Specific Settings into Image Properities (not global)
4925 }
4926
4927 /* Operators that do not need images - read, write, stack, clone */
4928 if ( (option_type & NoImageOperatorFlag) != 0)
4929 CLINoImageOperator(cli_wand, option, arg1, arg2);
4930
4931 /* FUTURE: The not a setting part below is a temporary hack due to
4932 * some options being both a Setting and a Simple operator.
4933 * Specifically -monitor, -depth, and -colorspace */
4934 if ( cli_wand->wand.images == (Image *)NULL )
4935 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
4936 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
4937 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
4938
anthonya322a832013-04-27 06:28:03 +00004939 /* Operators which loop of individual images, simply */
4940 if ( (option_type & SimpleOperatorFlag) != 0 &&
4941 cli_wand->wand.images != (Image *)NULL) /* temp hack */
anthony964d28e2012-05-17 23:39:46 +00004942 CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
4943
4944 /* Operators that work on the image list as a whole */
4945 if ( (option_type & ListOperatorFlag) != 0 )
4946 CLIListOperatorImages(cli_wand, option, arg1, arg2);
4947
4948 } while (0); /* end Break code block */
anthony464f1c42012-04-22 08:51:01 +00004949
4950 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
anthony464f1c42012-04-22 08:51:01 +00004951}