blob: 0c2be9ddf07900811e1c99e738d6ecc39f00a64b [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,
171 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000172 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000173{
174 char
175 token[MaxTextExtent];
176
177 const char
178 *p;
179
180 double
181 *sparse_arguments;
182
183 Image
184 *sparse_image;
185
186 PixelInfo
187 color;
188
189 MagickBooleanType
190 error;
191
192 register size_t
193 x;
194
195 size_t
196 number_arguments,
197 number_colors;
198
199 assert(image != (Image *) NULL);
200 assert(image->signature == MagickSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000201 if (IfMagickTrue(image->debug))
anthony805a2d42011-09-25 08:25:12 +0000202 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
203 assert(exception != (ExceptionInfo *) NULL);
204 assert(exception->signature == MagickSignature);
205 /*
anthonyb1d483a2012-04-14 12:53:56 +0000206 Limit channels according to image
207 add up number of values needed per color.
anthony805a2d42011-09-25 08:25:12 +0000208 */
209 number_colors=0;
210 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
211 number_colors++;
212 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
213 number_colors++;
214 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
215 number_colors++;
216 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
217 (image->colorspace == CMYKColorspace))
218 number_colors++;
219 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy8a46d822012-08-28 23:32:39 +0000220 image->alpha_trait == BlendPixelTrait)
anthony805a2d42011-09-25 08:25:12 +0000221 number_colors++;
222
223 /*
224 Read string, to determine number of arguments needed,
225 */
226 p=arguments;
227 x=0;
228 while( *p != '\0' )
229 {
230 GetMagickToken(p,&p,token);
231 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000232 if ( isalpha((int) token[0]) || token[0] == '#' )
233 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000234 else
anthony805a2d42011-09-25 08:25:12 +0000235 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000236 }
anthony31f1bf72012-01-30 12:37:22 +0000237 /* control points and color values */
anthony7bcfe7f2012-03-30 14:01:22 +0000238 error = IsMagickTrue( x % (2+number_colors) );
anthony31f1bf72012-01-30 12:37:22 +0000239 number_arguments=x;
anthony7bcfe7f2012-03-30 14:01:22 +0000240 if ( IfMagickTrue(error) ) {
anthony805a2d42011-09-25 08:25:12 +0000241 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000242 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000243 "Invalid number of Arguments");
244 return( (Image *)NULL);
245 }
246
247 /* Allocate and fill in the floating point arguments */
248 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
249 sizeof(*sparse_arguments));
250 if (sparse_arguments == (double *) NULL) {
251 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
252 "MemoryAllocationFailed","%s","SparseColorOption");
253 return( (Image *)NULL);
254 }
255 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
256 sizeof(*sparse_arguments));
257 p=arguments;
258 x=0;
259 while( *p != '\0' && x < number_arguments ) {
260 /* X coordinate */
261 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
262 if ( token[0] == '\0' ) break;
263 if ( isalpha((int) token[0]) || token[0] == '#' ) {
264 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000265 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000266 "Color found, instead of X-coord");
267 error = MagickTrue;
268 break;
269 }
cristydbdd0e32011-11-04 23:29:40 +0000270 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000271 /* Y coordinate */
272 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
273 if ( token[0] == '\0' ) break;
274 if ( isalpha((int) token[0]) || token[0] == '#' ) {
275 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000276 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000277 "Color found, instead of Y-coord");
278 error = MagickTrue;
279 break;
280 }
cristydbdd0e32011-11-04 23:29:40 +0000281 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000282 /* color name or function given in string argument */
283 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
284 if ( token[0] == '\0' ) break;
285 if ( isalpha((int) token[0]) || token[0] == '#' ) {
286 /* Color string given */
287 (void) QueryColorCompliance(token,AllCompliance,&color,
288 exception);
289 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
290 sparse_arguments[x++] = QuantumScale*color.red;
291 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
292 sparse_arguments[x++] = QuantumScale*color.green;
293 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
294 sparse_arguments[x++] = QuantumScale*color.blue;
295 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
296 (image->colorspace == CMYKColorspace))
297 sparse_arguments[x++] = QuantumScale*color.black;
298 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy8a46d822012-08-28 23:32:39 +0000299 image->alpha_trait == BlendPixelTrait)
anthony31f1bf72012-01-30 12:37:22 +0000300 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000301 }
anthony31f1bf72012-01-30 12:37:22 +0000302 else {
303 /* Colors given as a set of floating point values - experimental */
304 /* NB: token contains the first floating point value to use! */
305 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
306 {
307 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
308 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
309 break;
310 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
311 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000312 }
anthony31f1bf72012-01-30 12:37:22 +0000313 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
314 {
315 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
316 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
317 break;
318 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
319 token[0] = ','; /* used this token - get another */
320 }
321 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
322 {
323 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
324 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
325 break;
326 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
327 token[0] = ','; /* used this token - get another */
328 }
329 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
330 (image->colorspace == CMYKColorspace))
331 {
332 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
333 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
334 break;
335 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
336 token[0] = ','; /* used this token - get another */
337 }
338 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
cristy8a46d822012-08-28 23:32:39 +0000339 image->alpha_trait == BlendPixelTrait)
anthony31f1bf72012-01-30 12:37:22 +0000340 {
341 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
342 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
343 break;
344 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
345 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000346 }
347 }
348 }
349 if ( number_arguments != x && !error ) {
350 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000351 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000352 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
353 return( (Image *)NULL);
354 }
355 if ( error )
356 return( (Image *)NULL);
357
anthony31f1bf72012-01-30 12:37:22 +0000358 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000359 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
360 exception);
361 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
362 return( sparse_image );
363}
364
365/*
366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367% %
368% %
369% %
anthony464f1c42012-04-22 08:51:01 +0000370% 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 +0000371% %
372% %
373% %
374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375%
376% CLISettingOptionInfo() applies a single settings option into a CLI wand
377% holding the image_info, draw_info, quantize_info structures that will be
378% used when processing the images.
379%
380% These options do no require images to be present in the CLI wand for them
381% to be able to be set, in which case they will generally be applied to image
382% that are read in later
anthony80c37752012-01-16 01:03:11 +0000383%
384% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000385% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000386%
anthony2052d272012-02-28 12:48:29 +0000387% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000388%
anthonyafa3dfc2012-03-03 11:31:30 +0000389% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000390% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000391%
392% A description of each parameter follows:
393%
anthony43f425d2012-02-26 12:58:58 +0000394% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000395%
anthonydcf510d2011-10-30 13:51:40 +0000396% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000397%
anthonye5fcd362012-04-09 04:02:09 +0000398% o arg1, arg2: optional argument strings to the operation
399% arg2 is currently only used by "-limit"
anthonydcf510d2011-10-30 13:51:40 +0000400%
anthony805a2d42011-09-25 08:25:12 +0000401*/
anthonyafa3dfc2012-03-03 11:31:30 +0000402WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000403 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000404{
anthony30b912a2012-03-22 01:20:28 +0000405 ssize_t
406 parse; /* option argument parsing (string to value table lookup) */
407
anthony43f425d2012-02-26 12:58:58 +0000408 assert(cli_wand != (MagickCLI *) NULL);
409 assert(cli_wand->signature == WandSignature);
410 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000411 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +0000412 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000413
anthony2e4501b2012-03-30 04:41:54 +0000414#define _image_info (cli_wand->wand.image_info)
415#define _exception (cli_wand->wand.exception)
416#define _draw_info (cli_wand->draw_info)
417#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000418#define IfSetOption (*option=='-')
anthony7bcfe7f2012-03-30 14:01:22 +0000419#define ArgBoolean IsMagickTrue(IfSetOption)
420#define ArgBooleanNot IsMagickFalse(IfSetOption)
anthony24aa8822012-03-11 00:56:06 +0000421#define ArgBooleanString (IfSetOption?"true":"false")
422#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000423
anthony4837ac22012-05-18 23:39:48 +0000424#if 0
425Setting are not directly involved with images, so can not
426interpret Percent Escapes in Arguments, At least not yet */
427
428#define _process_flags (cli_wand->process_flags)
429#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
430 /* Interpret Percent Escapes in Arguments - using first image */
431 arg1 = arg1n,
432 arg2 = arg2n;
433 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
434 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
435 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
436 /* Interpret Percent escapes in argument 1 */
437 if (arg1n != (char *) NULL) {
438 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
439 if (arg1 == (char *) NULL) {
440 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
441 arg1=arg1n; /* use the given argument as is */
442 }
443 }
444 if (arg2n != (char *) NULL) {
445 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
446 if (arg2 == (char *) NULL) {
447 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
448 arg2=arg2n; /* use the given argument as is */
449 }
450 }
451 }
452#undef _process_flags
453#undef _option_type
454#endif
455
anthonyafa3dfc2012-03-03 11:31:30 +0000456 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000457 {
458 case 'a':
459 {
anthonyafa3dfc2012-03-03 11:31:30 +0000460 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000461 {
anthony92c93bd2012-03-19 14:02:47 +0000462 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000463 break;
464 }
anthonyafa3dfc2012-03-03 11:31:30 +0000465 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000466 {
anthony464f1c42012-04-22 08:51:01 +0000467 CLIWandWarnReplaced("-draw 'affine ...'");
anthony74b1cfc2011-10-06 12:44:16 +0000468 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000469 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000470 else
anthony92c93bd2012-03-19 14:02:47 +0000471 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000472 break;
473 }
anthonyafa3dfc2012-03-03 11:31:30 +0000474 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000475 {
anthony92c93bd2012-03-19 14:02:47 +0000476 _image_info->antialias =
477 _draw_info->stroke_antialias =
478 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000479 break;
480 }
anthony31f1bf72012-01-30 12:37:22 +0000481 if (LocaleCompare("attenuate",option+1) == 0)
482 {
anthony7bcfe7f2012-03-30 14:01:22 +0000483 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +0000484 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
485 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000486 break;
487 }
anthonyafa3dfc2012-03-03 11:31:30 +0000488 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000489 {
anthony92c93bd2012-03-19 14:02:47 +0000490 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000491 break;
492 }
anthonyebb73a22012-03-22 14:25:52 +0000493 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000494 }
495 case 'b':
496 {
anthonyafa3dfc2012-03-03 11:31:30 +0000497 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000498 {
anthony92c93bd2012-03-19 14:02:47 +0000499 /* FUTURE: both _image_info attribute & ImageOption in use!
500 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000501 SyncImageSettings() used to set per-image attribute.
502
anthony92c93bd2012-03-19 14:02:47 +0000503 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000504 we should fall back to per-image background_color
505
506 At this time -background will 'wipe out' the per-image
507 background color!
508
509 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000510 */
anthony92c93bd2012-03-19 14:02:47 +0000511 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000512 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000513 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000514 break;
515 }
anthonyafa3dfc2012-03-03 11:31:30 +0000516 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000517 {
anthony52bef752012-03-27 13:54:47 +0000518 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000519 as it is actually rarely used except in direct convolve operations
520 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000521
522 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000523 */
anthony7bcfe7f2012-03-30 14:01:22 +0000524 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000525 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000526 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000527 break;
528 }
anthonyafa3dfc2012-03-03 11:31:30 +0000529 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000530 {
anthony72feaa62012-01-17 06:46:23 +0000531 /* Used as a image chromaticity setting
532 SyncImageSettings() used to set per-image attribute.
533 */
anthony92c93bd2012-03-19 14:02:47 +0000534 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000535 break;
536 }
anthonyafa3dfc2012-03-03 11:31:30 +0000537 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000538 {
anthonyafbaed72011-10-26 12:05:04 +0000539 /* Image chromaticity X,Y NB: Y=X if Y not defined
540 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000541 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000542 */
anthonyf42014d2012-03-25 09:53:06 +0000543 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000544 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000545 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000546 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000547 break;
548 }
anthonyafa3dfc2012-03-03 11:31:30 +0000549 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000550 {
anthony92c93bd2012-03-19 14:02:47 +0000551 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000552 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000553 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000554 */
anthony74b1cfc2011-10-06 12:44:16 +0000555 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000556 {
anthony92c93bd2012-03-19 14:02:47 +0000557 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000558 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000559 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000560 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000561 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000562 break;
563 }
anthony92c93bd2012-03-19 14:02:47 +0000564 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000565 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000566 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000567 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000568 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000569 break;
570 }
anthonyafa3dfc2012-03-03 11:31:30 +0000571 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000572 {
anthony464f1c42012-04-22 08:51:01 +0000573 CLIWandWarnReplaced("-undercolor");
anthony975a8d72012-04-12 13:54:36 +0000574 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
anthonyfd706f92012-01-19 04:22:02 +0000575 break;
anthony805a2d42011-09-25 08:25:12 +0000576 }
anthonyebb73a22012-03-22 14:25:52 +0000577 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000578 }
579 case 'c':
580 {
anthonyafa3dfc2012-03-03 11:31:30 +0000581 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000582 {
583 MagickSizeType
584 limit;
585
anthony7bcfe7f2012-03-30 14:01:22 +0000586 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000588 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000589 if (LocaleCompare("unlimited",arg1) != 0)
590 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000591 (void) SetMagickResourceLimit(MemoryResource,limit);
592 (void) SetMagickResourceLimit(MapResource,2*limit);
593 break;
594 }
anthonyafa3dfc2012-03-03 11:31:30 +0000595 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000596 {
anthony92c93bd2012-03-19 14:02:47 +0000597 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000598 break;
599 }
anthonyafa3dfc2012-03-03 11:31:30 +0000600 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000601 {
anthony30b912a2012-03-22 01:20:28 +0000602 arg1=ArgOption("default");
603 parse=ParseChannelOption(arg1);
604 if (parse < 0)
605 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
606 option,arg1);
607 _image_info->channel=(ChannelType) parse;
608 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000609 break;
610 }
anthonyafa3dfc2012-03-03 11:31:30 +0000611 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000612 {
anthonyafbaed72011-10-26 12:05:04 +0000613 /* Setting used for new images via AquireImage()
614 But also used as a SimpleImageOperator
615 Undefined colorspace means don't modify images on
616 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000617 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
618 ArgOption("undefined"));
619 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000620 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
621 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000622 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000623 break;
624 }
anthonyafa3dfc2012-03-03 11:31:30 +0000625 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000626 {
anthony92c93bd2012-03-19 14:02:47 +0000627 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000628 break;
629 }
anthonyafa3dfc2012-03-03 11:31:30 +0000630 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000631 {
anthony92c93bd2012-03-19 14:02:47 +0000632 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000633 SyncImageSettings() used to set per-image attribute. - REMOVE
634
anthonyafbaed72011-10-26 12:05:04 +0000635 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000636 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000637 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000638 */
anthonyebb73a22012-03-22 14:25:52 +0000639 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
640 ArgOption("undefined"));
641 if (parse < 0)
642 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
643 option,arg1);
644 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000645 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000646 break;
647 }
anthonyafa3dfc2012-03-03 11:31:30 +0000648 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000649 {
anthony92c93bd2012-03-19 14:02:47 +0000650 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000651 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000652 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000653
anthony92c93bd2012-03-19 14:02:47 +0000654 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000655 however the image attribute (for save) is set from the
656 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000657
658 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000659 */
anthonyebb73a22012-03-22 14:25:52 +0000660 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
661 ArgOption("undefined"));
662 if (parse < 0)
663 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
664 option,arg1);
665 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000666 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000667 break;
668 }
anthonyebb73a22012-03-22 14:25:52 +0000669 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000670 }
671 case 'd':
672 {
anthonyafa3dfc2012-03-03 11:31:30 +0000673 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000674 {
anthony72feaa62012-01-17 06:46:23 +0000675 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000676 arg1=ArgOption("none");
677 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
678 if (parse < 0)
679 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
680 option,arg1);
681 (void) SetLogEventMask(arg1);
682 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000683 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000684 break;
685 }
anthonyafa3dfc2012-03-03 11:31:30 +0000686 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000687 {
anthony24aa8822012-03-11 00:56:06 +0000688 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000689 {
anthony5f867ae2011-10-09 10:28:34 +0000690 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000691 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000692 else
anthony24aa8822012-03-11 00:56:06 +0000693 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000694 break;
695 }
anthony24aa8822012-03-11 00:56:06 +0000696 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000697 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000698 (void) DefineImageOption(_image_info,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +0000699 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000700 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000701 break;
702 }
anthonyafa3dfc2012-03-03 11:31:30 +0000703 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000704 {
anthonyafbaed72011-10-26 12:05:04 +0000705 /* Only used for new images via AcquireImage()
706 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000707 */
anthonyebb73a22012-03-22 14:25:52 +0000708 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000709 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000710 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
711 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000712 break;
713 }
anthonyafa3dfc2012-03-03 11:31:30 +0000714 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000715 {
anthony92c93bd2012-03-19 14:02:47 +0000716 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000717 Basically as density can be in a XxY form!
718
719 SyncImageSettings() used to set per-image attribute.
720 */
anthony7bcfe7f2012-03-30 14:01:22 +0000721 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000722 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000723 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
724 (void) CloneString(&_image_info->density,ArgOption(NULL));
725 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000726 break;
727 }
anthonyafa3dfc2012-03-03 11:31:30 +0000728 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000729 {
anthony72feaa62012-01-17 06:46:23 +0000730 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
731 SyncImageSettings() used to set per-image attribute.
732 */
anthony7bcfe7f2012-03-30 14:01:22 +0000733 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000734 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000735 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000736 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000737 break;
738 }
anthonyafa3dfc2012-03-03 11:31:30 +0000739 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000740 {
anthony92c93bd2012-03-19 14:02:47 +0000741 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000742 arg1=ArgOption("undefined");
743 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
744 if (parse < 0)
745 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
746 option,arg1);
747 _draw_info->direction=(DirectionType) parse;
748 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000749 break;
750 }
anthonyafa3dfc2012-03-03 11:31:30 +0000751 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000752 {
anthony92c93bd2012-03-19 14:02:47 +0000753 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
754 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000755 break;
756 }
anthonyafa3dfc2012-03-03 11:31:30 +0000757 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000758 {
anthony72feaa62012-01-17 06:46:23 +0000759 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000760 arg1=ArgOption("undefined");
761 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
762 if (parse < 0)
763 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
764 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000765 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000766 break;
767 }
anthonyb1d483a2012-04-14 12:53:56 +0000768 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
769 {
770 /* FUTURE: this is only used by CompareImages() which is used
771 only by the "compare" CLI program at this time. */
772 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
773 if (IfMagickFalse(IsGeometry(arg1)))
774 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
775 (void) SetImageOption(_image_info,option+1,arg1);
776 break;
777 }
anthonyafa3dfc2012-03-03 11:31:30 +0000778 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000779 {
anthony92c93bd2012-03-19 14:02:47 +0000780 /* _image_info attr (on/off), _quantize_info attr (on/off)
781 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000782 FUTURE: merge the duality of the dithering options
783 */
cristycbda6112012-05-27 20:57:16 +0000784 _image_info->dither = ArgBoolean;
anthony92c93bd2012-03-19 14:02:47 +0000785 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
786 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
cristycbda6112012-05-27 20:57:16 +0000787 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000788 if (_quantize_info->dither_method == NoDitherMethod)
cristycbda6112012-05-27 20:57:16 +0000789 _image_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000790 break;
791 }
anthonyebb73a22012-03-22 14:25:52 +0000792 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000793 }
794 case 'e':
795 {
anthonyafa3dfc2012-03-03 11:31:30 +0000796 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000797 {
anthony92c93bd2012-03-19 14:02:47 +0000798 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
799 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000800 break;
801 }
anthonyafa3dfc2012-03-03 11:31:30 +0000802 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000803 {
anthony92c93bd2012-03-19 14:02:47 +0000804 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000805 arg1 = ArgOption("undefined");
806 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
807 if (parse < 0)
808 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
809 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000810 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000811 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000812 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000813 break;
814 }
anthonyafa3dfc2012-03-03 11:31:30 +0000815 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000816 {
anthony92c93bd2012-03-19 14:02:47 +0000817 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000818 break;
819 }
anthonyebb73a22012-03-22 14:25:52 +0000820 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000821 }
822 case 'f':
823 {
anthonyafa3dfc2012-03-03 11:31:30 +0000824 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000825 {
anthony92c93bd2012-03-19 14:02:47 +0000826 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000827 break;
828 }
anthonyafa3dfc2012-03-03 11:31:30 +0000829 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000830 {
anthony92c93bd2012-03-19 14:02:47 +0000831 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000832 The original fill color is preserved if a fill-pattern is given.
833 That way it does not effect other operations that directly using
834 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000835 */
anthony72feaa62012-01-17 06:46:23 +0000836 MagickBooleanType
837 status;
anthony6dc09cd2011-10-12 08:56:49 +0000838
839 ExceptionInfo
840 *sans;
841
anthonyfd706f92012-01-19 04:22:02 +0000842 PixelInfo
843 color;
844
anthony2a0ec8c2012-03-24 04:35:56 +0000845 arg1 = ArgOption("none"); /* +fill turns it off! */
846 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000847 if (_draw_info->fill_pattern != (Image *) NULL)
848 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000849
850 /* is it a color or a image? -- ignore exceptions */
851 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +0000852 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000853 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000854
anthony7bcfe7f2012-03-30 14:01:22 +0000855 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +0000856 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000857 else
anthony92c93bd2012-03-19 14:02:47 +0000858 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000859 break;
860 }
anthonyafa3dfc2012-03-03 11:31:30 +0000861 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000862 {
anthony72feaa62012-01-17 06:46:23 +0000863 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +0000864 arg1 = ArgOption("undefined");
865 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
866 if (parse < 0)
867 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
868 option,arg1);
869 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000870 break;
871 }
anthonyafa3dfc2012-03-03 11:31:30 +0000872 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000873 {
anthony92c93bd2012-03-19 14:02:47 +0000874 (void) CloneString(&_draw_info->font,ArgOption(NULL));
875 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000876 break;
877 }
anthonyafa3dfc2012-03-03 11:31:30 +0000878 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000879 {
anthonydcf510d2011-10-30 13:51:40 +0000880 /* FUTURE: why the ping test, you could set ping after this! */
881 /*
anthony805a2d42011-09-25 08:25:12 +0000882 register const char
883 *q;
884
anthony24aa8822012-03-11 00:56:06 +0000885 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000886 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +0000887 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000888 */
anthony92c93bd2012-03-19 14:02:47 +0000889 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000890 break;
891 }
anthonyafa3dfc2012-03-03 11:31:30 +0000892 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000893 {
anthony72feaa62012-01-17 06:46:23 +0000894 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000895 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000896 SyncImageSettings() used to set per-image attribute.
897
anthony2a0ec8c2012-03-24 04:35:56 +0000898 FUTURE: Can't find anything else using _image_info->fuzz directly!
899 remove direct sttribute from image_info
anthony6613bf32011-10-15 07:24:44 +0000900 */
anthony2a0ec8c2012-03-24 04:35:56 +0000901 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000902 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +0000903 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
904 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +0000905 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +0000906 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000907 break;
908 }
anthonyebb73a22012-03-22 14:25:52 +0000909 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000910 }
911 case 'g':
912 {
anthonyafa3dfc2012-03-03 11:31:30 +0000913 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000914 {
anthony72feaa62012-01-17 06:46:23 +0000915 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000916 arg1 = ArgOption("none");
917 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
918 if (parse < 0)
919 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
920 option,arg1);
anthonyfe1aa782012-03-24 13:43:04 +0000921 _draw_info->gravity=(GravityType) parse;
anthonye8490972012-04-03 13:16:01 +0000922 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000923 break;
924 }
anthonyafa3dfc2012-03-03 11:31:30 +0000925 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000926 {
anthonydcf510d2011-10-30 13:51:40 +0000927 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000928 SyncImageSettings() used to set per-image attribute.
929 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000930 */
anthonyf42014d2012-03-25 09:53:06 +0000931 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000932 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000933 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000934 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000935 break;
936 }
anthonyebb73a22012-03-22 14:25:52 +0000937 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000938 }
anthonyb1d483a2012-04-14 12:53:56 +0000939 case 'h':
940 {
941 if (LocaleCompare("highlight-color",option+1) == 0)
942 {
943 /* FUTURE: this is only used by CompareImages() which is used
944 only by the "compare" CLI program at this time. */
945 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
946 break;
947 }
948 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
949 }
anthony805a2d42011-09-25 08:25:12 +0000950 case 'i':
951 {
anthonyafa3dfc2012-03-03 11:31:30 +0000952 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000953 {
anthony72feaa62012-01-17 06:46:23 +0000954 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000955 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000956 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000957 */
anthonyfe1aa782012-03-24 13:43:04 +0000958 arg1 = ArgOption("indefined");
959 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
960 if (parse < 0)
961 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
962 option,arg1);
963 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000964 break;
965 }
anthonyafa3dfc2012-03-03 11:31:30 +0000966 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000967 {
anthony92c93bd2012-03-19 14:02:47 +0000968 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +0000969 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000970 */
anthonyfe1aa782012-03-24 13:43:04 +0000971 arg1 = ArgOption("undefined");
972 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
973 if (parse < 0)
974 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
975 option,arg1);
976 _image_info->interlace=(InterlaceType) parse;
977 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000978 break;
979 }
anthonyafa3dfc2012-03-03 11:31:30 +0000980 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000981 {
anthony7bcfe7f2012-03-30 14:01:22 +0000982 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000983 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000984 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
985 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +0000986 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000987 break;
988 }
anthonyafa3dfc2012-03-03 11:31:30 +0000989 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000990 {
anthonyfd706f92012-01-19 04:22:02 +0000991 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000992 arg1 = ArgOption("undefined");
993 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
994 if (parse < 0)
995 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
996 option,arg1);
997 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000998 break;
999 }
anthonyafa3dfc2012-03-03 11:31:30 +00001000 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001001 {
anthony7bcfe7f2012-03-30 14:01:22 +00001002 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001003 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001004 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1005 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001006 break;
1007 }
anthonyebb73a22012-03-22 14:25:52 +00001008 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001009 }
1010 case 'k':
1011 {
anthonyafa3dfc2012-03-03 11:31:30 +00001012 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001013 {
anthony7bcfe7f2012-03-30 14:01:22 +00001014 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001015 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001016 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1017 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001018 break;
1019 }
anthonyebb73a22012-03-22 14:25:52 +00001020 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001021 }
1022 case 'l':
1023 {
anthonyafa3dfc2012-03-03 11:31:30 +00001024 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001025 {
anthony72feaa62012-01-17 06:46:23 +00001026 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001027 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001028 break;
1029 }
anthony756cd0d2012-04-08 12:41:44 +00001030 if (LocaleCompare("limit",option+1) == 0)
1031 {
1032 MagickSizeType
1033 limit;
1034
1035 limit=MagickResourceInfinity;
1036 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1037 if ( parse < 0 )
1038 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1039 option,arg1);
1040 if (LocaleCompare("unlimited",arg2) != 0)
1041 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1042 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1043 break;
1044 }
anthonyafa3dfc2012-03-03 11:31:30 +00001045 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001046 {
anthonyfe1aa782012-03-24 13:43:04 +00001047 if (IfSetOption) {
1048 if ((strchr(arg1,'%') == (char *) NULL))
1049 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001050 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001051 }
anthony805a2d42011-09-25 08:25:12 +00001052 break;
1053 }
anthony975a8d72012-04-12 13:54:36 +00001054 if (LocaleCompare("lowlight-color",option+1) == 0)
1055 {
anthonyb1d483a2012-04-14 12:53:56 +00001056 /* FUTURE: this is only used by CompareImages() which is used
1057 only by the "compare" CLI program at this time. */
anthony975a8d72012-04-12 13:54:36 +00001058 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1059 break;
1060 }
anthonyafa3dfc2012-03-03 11:31:30 +00001061 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001062 {
anthony72feaa62012-01-17 06:46:23 +00001063 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001064 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001065 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001066 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1067 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001068 break;
1069 }
anthonyebb73a22012-03-22 14:25:52 +00001070 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001071 }
1072 case 'm':
1073 {
anthonyafa3dfc2012-03-03 11:31:30 +00001074 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001075 {
anthony72feaa62012-01-17 06:46:23 +00001076 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001077 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001078 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001079 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001080 break;
anthonycd358fc2012-04-16 13:59:03 +00001081 }
anthonyb1d483a2012-04-14 12:53:56 +00001082 if (LocaleCompare("metric",option+1) == 0)
1083 {
1084 /* FUTURE: this is only used by CompareImages() which is used
1085 only by the "compare" CLI program at this time. */
1086 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1087 if ( parse < 0 )
1088 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1089 option,arg1);
1090 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthonycd358fc2012-04-16 13:59:03 +00001091 break;
anthony805a2d42011-09-25 08:25:12 +00001092 }
anthonyafa3dfc2012-03-03 11:31:30 +00001093 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001094 {
anthony92c93bd2012-03-19 14:02:47 +00001095 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001096 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001097 break;
1098 }
anthonyafa3dfc2012-03-03 11:31:30 +00001099 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001100 {
anthony24aa8822012-03-11 00:56:06 +00001101 /* Setting (used by some input coders!) -- why?
1102 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001103 */
anthony92c93bd2012-03-19 14:02:47 +00001104 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001105 break;
1106 }
anthonyebb73a22012-03-22 14:25:52 +00001107 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001108 }
1109 case 'o':
1110 {
anthonyafa3dfc2012-03-03 11:31:30 +00001111 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001112 {
anthony72feaa62012-01-17 06:46:23 +00001113 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001114 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001115 FUTURE: make set meta-data operator instead.
1116 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001117 */
anthony7bc87992012-03-25 02:32:51 +00001118 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1119 ArgOption("undefined"));
1120 if (parse < 0)
1121 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1122 option,arg1);
1123 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001124 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001125 break;
1126 }
anthonyebb73a22012-03-22 14:25:52 +00001127 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001128 }
1129 case 'p':
1130 {
anthonyafa3dfc2012-03-03 11:31:30 +00001131 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001132 {
anthony7bc87992012-03-25 02:32:51 +00001133 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001134 SyncImageSettings() used to set per-image attribute. ?????
1135 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001136 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001137 */
anthony805a2d42011-09-25 08:25:12 +00001138 char
1139 *canonical_page,
1140 page[MaxTextExtent];
1141
1142 const char
1143 *image_option;
1144
1145 MagickStatusType
1146 flags;
1147
1148 RectangleInfo
1149 geometry;
1150
anthonydcf510d2011-10-30 13:51:40 +00001151 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001152 {
anthony92c93bd2012-03-19 14:02:47 +00001153 (void) DeleteImageOption(_image_info,option+1);
1154 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001155 break;
1156 }
1157 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001158 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001159 if (image_option != (const char *) NULL)
1160 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001161 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001162 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1163 canonical_page=DestroyString(canonical_page);
1164 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1165 (unsigned long) geometry.width,(unsigned long) geometry.height);
1166 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1167 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1168 (unsigned long) geometry.width,(unsigned long) geometry.height,
1169 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001170 (void) SetImageOption(_image_info,option+1,page);
1171 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001172 break;
1173 }
anthonyafa3dfc2012-03-03 11:31:30 +00001174 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001175 {
anthony92c93bd2012-03-19 14:02:47 +00001176 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001177 break;
1178 }
anthonyafa3dfc2012-03-03 11:31:30 +00001179 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001180 {
anthonyf42014d2012-03-25 09:53:06 +00001181 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001182 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001183 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1184 _image_info->pointsize =
1185 _draw_info->pointsize =
1186 StringToDouble(arg1,(char **) NULL);
1187 }
1188 else {
1189 _image_info->pointsize=0.0; /* unset pointsize */
1190 _draw_info->pointsize=12.0;
1191 }
anthony805a2d42011-09-25 08:25:12 +00001192 break;
1193 }
anthonyafa3dfc2012-03-03 11:31:30 +00001194 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001195 {
anthonyf42014d2012-03-25 09:53:06 +00001196 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001197 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1199 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001200 break;
1201 }
anthonydcf510d2011-10-30 13:51:40 +00001202 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001203 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001204 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001205 {
anthony92c93bd2012-03-19 14:02:47 +00001206 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001207 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001208 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001209 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001210 break;
1211 }
anthonydcf510d2011-10-30 13:51:40 +00001212 */
anthonyebb73a22012-03-22 14:25:52 +00001213 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001214 }
1215 case 'q':
1216 {
anthonyafa3dfc2012-03-03 11:31:30 +00001217 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001218 {
anthony7bcfe7f2012-03-30 14:01:22 +00001219 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001220 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001221 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1222 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001223 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001224 break;
1225 }
anthonyafa3dfc2012-03-03 11:31:30 +00001226 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001227 {
anthony92c93bd2012-03-19 14:02:47 +00001228 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001229 arg1=ArgOption("undefined");
1230 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1231 if (parse < 0)
1232 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1233 option,arg1);
1234 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001235 break;
1236 }
anthonyafa3dfc2012-03-03 11:31:30 +00001237 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001238 {
anthonyf42014d2012-03-25 09:53:06 +00001239 /* FUTURE: if two -quiet is performed you can not do +quiet!
1240 This needs to be checked over thoughly.
1241 */
anthony805a2d42011-09-25 08:25:12 +00001242 static WarningHandler
1243 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001244
anthonyafbaed72011-10-26 12:05:04 +00001245 WarningHandler
1246 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001247
anthonyafbaed72011-10-26 12:05:04 +00001248 if ( tmp != (WarningHandler) NULL)
1249 warning_handler = tmp; /* remember the old handler */
1250 if (!IfSetOption) /* set the old handler */
1251 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001252 break;
1253 }
anthonyebb73a22012-03-22 14:25:52 +00001254 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001255 }
1256 case 'r':
1257 {
anthonyafa3dfc2012-03-03 11:31:30 +00001258 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001259 {
anthonydcf510d2011-10-30 13:51:40 +00001260 /* Image chromaticity X,Y NB: Y=X if Y not defined
1261 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001262 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001263 */
anthonyf42014d2012-03-25 09:53:06 +00001264 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001265 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001266 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001267 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001268 break;
1269 }
cristyb0f7a182012-04-06 23:33:11 +00001270 if (LocaleCompare("regard-warnings",option+1) == 0)
anthonye5fcd362012-04-09 04:02:09 +00001271 /* FUTURE: to be replaced by a 'fatal-level' type setting */
cristyb0f7a182012-04-06 23:33:11 +00001272 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001273 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001274 {
anthony92c93bd2012-03-19 14:02:47 +00001275 /* _draw_info only setting */
1276 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001277 break;
1278 }
anthony756cd0d2012-04-08 12:41:44 +00001279 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1280 {
1281 /* link image and setting stacks - option is itself saved on stack! */
1282 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1283 break;
1284 }
anthonyebb73a22012-03-22 14:25:52 +00001285 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001286 }
1287 case 's':
1288 {
anthonyafa3dfc2012-03-03 11:31:30 +00001289 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001290 {
anthonyafbaed72011-10-26 12:05:04 +00001291 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001292 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001293 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001294 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001295 break;
1296 }
anthonyafa3dfc2012-03-03 11:31:30 +00001297 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001298 {
anthonyf42014d2012-03-25 09:53:06 +00001299 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001300 What ??? Why ????
1301 */
anthony7bcfe7f2012-03-30 14:01:22 +00001302 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001303 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001304 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1305 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001306 break;
1307 }
anthonyafa3dfc2012-03-03 11:31:30 +00001308 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001309 {
anthony7bcfe7f2012-03-30 14:01:22 +00001310 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001311 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyd7761bb2012-04-14 01:42:05 +00001312 SetRandomSecretKey(
cristyacc69a72012-09-26 13:18:21 +00001313 IfSetOption ? (const unsigned long) StringToUnsignedLong(arg1)
1314 : (const unsigned long) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001315 break;
1316 }
anthonyafa3dfc2012-03-03 11:31:30 +00001317 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001318 {
anthony92c93bd2012-03-19 14:02:47 +00001319 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001320 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001321 */
anthony92c93bd2012-03-19 14:02:47 +00001322 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001323 break;
1324 }
anthonyafa3dfc2012-03-03 11:31:30 +00001325 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001326 {
anthonyf42014d2012-03-25 09:53:06 +00001327 arg1=ArgOption("undefined");
1328 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1329 if (parse < 0)
1330 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1331 option,arg1);
1332 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001333 break;
1334 }
anthonyafa3dfc2012-03-03 11:31:30 +00001335 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001336 {
anthonyafbaed72011-10-26 12:05:04 +00001337 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001338 UPDATE: ensure stroke color is not destroyed is a pattern
1339 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001340 */
anthony72feaa62012-01-17 06:46:23 +00001341 MagickBooleanType
1342 status;
anthonyafbaed72011-10-26 12:05:04 +00001343
1344 ExceptionInfo
1345 *sans;
1346
anthonyfd706f92012-01-19 04:22:02 +00001347 PixelInfo
1348 color;
1349
anthony2a0ec8c2012-03-24 04:35:56 +00001350 arg1 = ArgOption("none"); /* +fill turns it off! */
1351 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001352 if (_draw_info->stroke_pattern != (Image *) NULL)
1353 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001354
1355 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001356 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001357 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001358 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001359
anthony7bcfe7f2012-03-30 14:01:22 +00001360 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001361 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001362 else
anthony92c93bd2012-03-19 14:02:47 +00001363 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001364 break;
1365 }
anthonyafa3dfc2012-03-03 11:31:30 +00001366 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001367 {
anthony7bcfe7f2012-03-30 14:01:22 +00001368 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001369 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001370 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1371 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001372 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001373 break;
1374 }
anthonyafa3dfc2012-03-03 11:31:30 +00001375 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001376 {
anthonyf42014d2012-03-25 09:53:06 +00001377 arg1=ArgOption("undefined");
1378 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1379 if (parse < 0)
1380 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1381 option,arg1);
1382 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001383 break;
1384 }
anthonycd358fc2012-04-16 13:59:03 +00001385#if 0
anthonyb1d483a2012-04-14 12:53:56 +00001386 if (LocaleCompare("subimage-search",option+1) == 0)
1387 {
1388 /* FUTURE: this is only used by CompareImages() which is used
1389 only by the "compare" CLI program at this time. */
1390 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1391 break;
1392 }
anthonycd358fc2012-04-16 13:59:03 +00001393#endif
anthonyafa3dfc2012-03-03 11:31:30 +00001394 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001395 {
anthonyf42014d2012-03-25 09:53:06 +00001396 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001397 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001398 break;
1399 }
anthonyebb73a22012-03-22 14:25:52 +00001400 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001401 }
1402 case 't':
1403 {
anthonyafa3dfc2012-03-03 11:31:30 +00001404 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001405 {
anthony72feaa62012-01-17 06:46:23 +00001406 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001407 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001408 break;
1409 }
anthonyafa3dfc2012-03-03 11:31:30 +00001410 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001411 {
anthony4837ac22012-05-18 23:39:48 +00001412 /* Note: arguments do not have percent escapes expanded */
anthony52bef752012-03-27 13:54:47 +00001413 /* FUTURE: move _image_info string to option splay-tree
1414 Other than "montage" what uses "texture" ????
1415 */
anthony92c93bd2012-03-19 14:02:47 +00001416 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001417 break;
1418 }
anthonyafa3dfc2012-03-03 11:31:30 +00001419 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001420 {
anthony4837ac22012-05-18 23:39:48 +00001421 /* Note: arguments do not have percent escapes expanded */
anthony92c93bd2012-03-19 14:02:47 +00001422 _draw_info->fill_pattern=IfSetOption
1423 ?GetImageCache(_image_info,arg1,_exception)
1424 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001425 break;
1426 }
anthonyafa3dfc2012-03-03 11:31:30 +00001427 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001428 {
anthony72feaa62012-01-17 06:46:23 +00001429 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001430 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001431 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001432 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1433 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001434 break;
1435 }
anthonyafa3dfc2012-03-03 11:31:30 +00001436 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001437 {
anthony92c93bd2012-03-19 14:02:47 +00001438 /* FUTURE: both _image_info attribute & ImageOption in use!
1439 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001440 SyncImageSettings() used to set per-image attribute.
1441
anthonyafbaed72011-10-26 12:05:04 +00001442 Note that +transparent-color, means fall-back to image
1443 attribute so ImageOption is deleted, not set to a default.
1444 */
anthony7bcfe7f2012-03-30 14:01:22 +00001445 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001446 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001447 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001448 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001449 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001450 break;
1451 }
anthonyafa3dfc2012-03-03 11:31:30 +00001452 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001453 {
anthony92c93bd2012-03-19 14:02:47 +00001454 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1455 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001456 break;
1457 }
anthonyafa3dfc2012-03-03 11:31:30 +00001458 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001459 {
anthony72feaa62012-01-17 06:46:23 +00001460 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001461 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1462 ArgOption("undefined"));
1463 if (parse < 0)
1464 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1465 option,arg1);
1466 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001467 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001468 break;
1469 }
anthonyebb73a22012-03-22 14:25:52 +00001470 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001471 }
1472 case 'u':
1473 {
anthonyafa3dfc2012-03-03 11:31:30 +00001474 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001475 {
anthony92c93bd2012-03-19 14:02:47 +00001476 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001477 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001478 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001479 break;
1480 }
anthonyafa3dfc2012-03-03 11:31:30 +00001481 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001482 {
anthony72feaa62012-01-17 06:46:23 +00001483 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001484 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001485 FUTURE: this probably should be part of the density setting
1486 */
anthony52bef752012-03-27 13:54:47 +00001487 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1488 ArgOption("undefined"));
1489 if (parse < 0)
1490 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1491 option,arg1);
1492 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001493 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001494 break;
1495 }
anthonyebb73a22012-03-22 14:25:52 +00001496 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001497 }
1498 case 'v':
1499 {
anthonyafa3dfc2012-03-03 11:31:30 +00001500 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001501 {
anthony24aa8822012-03-11 00:56:06 +00001502 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001503 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001504 */
anthony92c93bd2012-03-19 14:02:47 +00001505 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1506 _image_info->verbose= ArgBoolean;
1507 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001508 break;
1509 }
anthonyafa3dfc2012-03-03 11:31:30 +00001510 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001511 {
anthony92c93bd2012-03-19 14:02:47 +00001512 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001513 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001514 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001515 */
anthony92c93bd2012-03-19 14:02:47 +00001516 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001517 break;
1518 }
anthonyafa3dfc2012-03-03 11:31:30 +00001519 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001520 {
anthonyfd706f92012-01-19 04:22:02 +00001521 /* SyncImageSettings() used to set per-image attribute.
1522 This is VERY deep in the image caching structure.
1523 */
anthony52bef752012-03-27 13:54:47 +00001524 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1525 ArgOption("undefined"));
1526 if (parse < 0)
1527 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1528 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001529 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001530 break;
1531 }
anthonyebb73a22012-03-22 14:25:52 +00001532 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001533 }
1534 case 'w':
1535 {
anthonyafa3dfc2012-03-03 11:31:30 +00001536 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001537 {
anthony72feaa62012-01-17 06:46:23 +00001538 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001539 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001540 */
anthony52bef752012-03-27 13:54:47 +00001541 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001542 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001543 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001544 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001545 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001546 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001547 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001548 if (_draw_info->weight <= 800)
1549 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001550 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001551 if (_draw_info->weight >= 100)
1552 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001553 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001554 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001555 break;
1556 }
anthonyafa3dfc2012-03-03 11:31:30 +00001557 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001558 {
anthony72feaa62012-01-17 06:46:23 +00001559 /* Used as a image chromaticity setting
1560 SyncImageSettings() used to set per-image attribute.
1561 */
anthony52bef752012-03-27 13:54:47 +00001562 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001563 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001564 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1565 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001566 break;
1567 }
anthonyebb73a22012-03-22 14:25:52 +00001568 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001569 }
1570 default:
anthonyebb73a22012-03-22 14:25:52 +00001571 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001572 }
anthony24aa8822012-03-11 00:56:06 +00001573
anthony4837ac22012-05-18 23:39:48 +00001574#if 0
1575 /* clean up percent escape interpreted strings */
1576 if (arg1 != arg1n )
1577 arg1=DestroyString((char *)arg1);
1578 if (arg2 != arg2n )
1579 arg2=DestroyString((char *)arg2);
1580#endif
1581
anthony92c93bd2012-03-19 14:02:47 +00001582#undef _image_info
1583#undef _exception
1584#undef _draw_info
1585#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001586#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001587#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001588#undef ArgBooleanNot
1589#undef ArgBooleanString
1590#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001591
anthony31f1bf72012-01-30 12:37:22 +00001592 return;
anthony805a2d42011-09-25 08:25:12 +00001593}
1594
1595/*
1596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597% %
1598% %
1599% %
anthony43f425d2012-02-26 12:58:58 +00001600+ 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 +00001601% %
1602% %
1603% %
1604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605%
anthonyc7994672012-11-17 05:33:27 +00001606% CLISimpleOperatorImages() applys one simple image operation given to all
1607% the images in the CLI wand, using any per-image or global settings that was
1608% previously saved in the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001609%
anthonyc7994672012-11-17 05:33:27 +00001610% It is assumed that any such settings are up-to-date.
anthony805a2d42011-09-25 08:25:12 +00001611%
anthony7a4d6102012-07-01 09:48:25 +00001612% The format of the WandSimpleOperatorImages method is:
anthony805a2d42011-09-25 08:25:12 +00001613%
anthony43f425d2012-02-26 12:58:58 +00001614% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001615% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001616%
1617% A description of each parameter follows:
1618%
anthony43f425d2012-02-26 12:58:58 +00001619% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001620%
anthonyfd706f92012-01-19 04:22:02 +00001621% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001622%
anthonyfd706f92012-01-19 04:22:02 +00001623% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001624%
anthony805a2d42011-09-25 08:25:12 +00001625*/
anthony31f1bf72012-01-30 12:37:22 +00001626
1627/*
anthonyc7994672012-11-17 05:33:27 +00001628 CLISimpleOperatorImage() is an Internal subrountine to apply one simple
1629 image operation to the current image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001630
1631 The image in the list may be modified in three different ways...
1632 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1633 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1634 * one image replace by a list of images (-separate and -crop only!)
1635
anthonyafa3dfc2012-03-03 11:31:30 +00001636 In each case the result replaces the single original image in the list, as
1637 well as the pointer to the modified image (last image added if replaced by a
1638 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001639
1640 As the image pointed to may be replaced, the first image in the list may
1641 also change. GetFirstImageInList() should be used by caller if they wish
1642 return the Image pointer to the first image in list.
1643*/
anthony43f425d2012-02-26 12:58:58 +00001644static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthony964d28e2012-05-17 23:39:46 +00001645 const char *option, const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00001646{
1647 Image *
1648 new_image;
1649
anthony805a2d42011-09-25 08:25:12 +00001650 GeometryInfo
1651 geometry_info;
1652
1653 RectangleInfo
1654 geometry;
1655
1656 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001657 flags;
1658
anthony92c93bd2012-03-19 14:02:47 +00001659 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001660 parse;
anthony92c93bd2012-03-19 14:02:47 +00001661
anthony964d28e2012-05-17 23:39:46 +00001662 const char /* For percent escape interpretImageProperties() */
1663 *arg1,
1664 *arg2;
1665
anthony2e4501b2012-03-30 04:41:54 +00001666#define _image_info (cli_wand->wand.image_info)
1667#define _image (cli_wand->wand.images)
1668#define _exception (cli_wand->wand.exception)
1669#define _draw_info (cli_wand->draw_info)
1670#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00001671#define _process_flags (cli_wand->process_flags)
1672#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00001673#define IfNormalOp (*option=='-')
1674#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00001675#define normal_op IsMagickTrue(IfNormalOp)
1676#define plus_alt_op IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001677
anthony43f425d2012-02-26 12:58:58 +00001678 assert(cli_wand != (MagickCLI *) NULL);
1679 assert(cli_wand->signature == WandSignature);
1680 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001681 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001682 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001683 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001684
anthony964d28e2012-05-17 23:39:46 +00001685 /* Interpret Percent Escapes in Arguments - using first image */
1686 arg1 = arg1n,
1687 arg2 = arg2n;
1688 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1689 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1690 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1691 /* Interpret Percent escapes in argument 1 */
1692 if (arg1n != (char *) NULL) {
1693 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1694 if (arg1 == (char *) NULL) {
1695 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1696 arg1=arg1n; /* use the given argument as is */
1697 }
1698 }
1699 if (arg2n != (char *) NULL) {
1700 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1701 if (arg2 == (char *) NULL) {
1702 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1703 arg2=arg2n; /* use the given argument as is */
1704 }
1705 }
1706 }
anthony4837ac22012-05-18 23:39:48 +00001707#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00001708#undef _option_type
1709
1710#if 0
1711 (void) FormatLocaleFile(stderr,
1712 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1713#endif
anthony805a2d42011-09-25 08:25:12 +00001714
anthony5330ae02012-03-20 14:17:01 +00001715 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony964d28e2012-05-17 23:39:46 +00001716 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001717
anthonyafa3dfc2012-03-03 11:31:30 +00001718 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001719 {
1720 case 'a':
1721 {
anthonyafa3dfc2012-03-03 11:31:30 +00001722 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001723 {
anthonyfd706f92012-01-19 04:22:02 +00001724 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001725 if ((flags & (RhoValue|SigmaValue)) == 0)
1726 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001727 if ((flags & SigmaValue) == 0)
1728 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001729 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001730 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001731 break;
1732 }
anthonyafa3dfc2012-03-03 11:31:30 +00001733 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001734 {
anthonyfe1aa782012-03-24 13:43:04 +00001735 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001736 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001737 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1738 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1739 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001740 _exception);
anthony805a2d42011-09-25 08:25:12 +00001741 break;
1742 }
anthonyafa3dfc2012-03-03 11:31:30 +00001743 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001744 {
anthonyfd706f92012-01-19 04:22:02 +00001745 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001746 if ((flags & (RhoValue|SigmaValue)) == 0)
1747 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001748 if ((flags & SigmaValue) == 0)
1749 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001750 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001751 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001752 break;
1753 }
anthonyafa3dfc2012-03-03 11:31:30 +00001754 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001755 {
cristy288a3532012-08-28 00:19:44 +00001756 parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001757 if (parse < 0)
cristyb15b06c2012-08-28 11:36:48 +00001758 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
anthony92c93bd2012-03-19 14:02:47 +00001759 option,arg1);
cristyb15b06c2012-08-28 11:36:48 +00001760 (void) SetImageAlphaChannel(_image,(AlphaChannelOption)parse,
anthony2a0ec8c2012-03-24 04:35:56 +00001761 _exception);
anthony805a2d42011-09-25 08:25:12 +00001762 break;
1763 }
anthonyafa3dfc2012-03-03 11:31:30 +00001764 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001765 {
1766 char
anthony805a2d42011-09-25 08:25:12 +00001767 geometry[MaxTextExtent];
1768
anthony805a2d42011-09-25 08:25:12 +00001769 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001770 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001771 if ((flags & RhoValue) == 0)
1772 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001773 if ((flags & SigmaValue) == 0)
1774 geometry_info.sigma=geometry_info.rho;
anthony964d28e2012-05-17 23:39:46 +00001775 (void) CloneString(&_draw_info->text,arg2);
anthony805a2d42011-09-25 08:25:12 +00001776 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1777 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001778 (void) CloneString(&_draw_info->geometry,geometry);
1779 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001780 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001781 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001782 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001783 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001784 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001785 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001786 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001787 (void) AnnotateImage(_image,_draw_info,_exception);
1788 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001789 break;
1790 }
anthonyafa3dfc2012-03-03 11:31:30 +00001791 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001792 {
anthony92c93bd2012-03-19 14:02:47 +00001793 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001794 break;
1795 }
anthonyafa3dfc2012-03-03 11:31:30 +00001796 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001797 {
anthony92c93bd2012-03-19 14:02:47 +00001798 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001799 break;
1800 }
anthonyafa3dfc2012-03-03 11:31:30 +00001801 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001802 {
anthony5330ae02012-03-20 14:17:01 +00001803 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001804 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001805 {
1806 case TopRightOrientation:
1807 {
anthony92c93bd2012-03-19 14:02:47 +00001808 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001809 break;
1810 }
1811 case BottomRightOrientation:
1812 {
anthony92c93bd2012-03-19 14:02:47 +00001813 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001814 break;
1815 }
1816 case BottomLeftOrientation:
1817 {
anthony92c93bd2012-03-19 14:02:47 +00001818 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001819 break;
1820 }
1821 case LeftTopOrientation:
1822 {
anthony92c93bd2012-03-19 14:02:47 +00001823 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001824 break;
1825 }
1826 case RightTopOrientation:
1827 {
anthony92c93bd2012-03-19 14:02:47 +00001828 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001829 break;
1830 }
1831 case RightBottomOrientation:
1832 {
anthony92c93bd2012-03-19 14:02:47 +00001833 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001834 break;
1835 }
1836 case LeftBottomOrientation:
1837 {
anthony92c93bd2012-03-19 14:02:47 +00001838 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001839 break;
1840 }
1841 default:
1842 break;
1843 }
1844 if (new_image != (Image *) NULL)
1845 new_image->orientation=TopLeftOrientation;
1846 break;
1847 }
anthonyebb73a22012-03-22 14:25:52 +00001848 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001849 }
1850 case 'b':
1851 {
anthonyafa3dfc2012-03-03 11:31:30 +00001852 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001853 {
anthony7bcfe7f2012-03-30 14:01:22 +00001854 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001855 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001856 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001857 break;
1858 }
anthonyafa3dfc2012-03-03 11:31:30 +00001859 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001860 {
anthony805a2d42011-09-25 08:25:12 +00001861 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001862 if (IfNormalOp) {
anthonyfd706f92012-01-19 04:22:02 +00001863 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001864 if ((flags & RhoValue) == 0)
1865 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony5330ae02012-03-20 14:17:01 +00001866 }
anthony92c93bd2012-03-19 14:02:47 +00001867 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001868 break;
1869 }
anthonyafa3dfc2012-03-03 11:31:30 +00001870 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001871 {
anthonyfd706f92012-01-19 04:22:02 +00001872 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001873 if ((flags & (RhoValue|SigmaValue)) == 0)
1874 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001875 if ((flags & SigmaValue) == 0)
1876 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001877 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1878 _exception);
anthony805a2d42011-09-25 08:25:12 +00001879 break;
1880 }
anthonyafa3dfc2012-03-03 11:31:30 +00001881 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001882 {
anthony31f1bf72012-01-30 12:37:22 +00001883 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001884 compose;
1885
1886 const char*
anthony5f867ae2011-10-09 10:28:34 +00001887 value;
1888
anthony22de2722012-04-19 14:43:00 +00001889 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
cristy64ad8f92012-08-03 00:58:24 +00001890 if ((flags & (WidthValue | HeightValue)) == 0)
anthony5330ae02012-03-20 14:17:01 +00001891 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy64ad8f92012-08-03 00:58:24 +00001892 compose=OverCompositeOp;
anthony92c93bd2012-03-19 14:02:47 +00001893 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001894 if (value != (const char *) NULL)
cristy64ad8f92012-08-03 00:58:24 +00001895 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
1896 MagickFalse,value);
anthony92c93bd2012-03-19 14:02:47 +00001897 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001898 break;
1899 }
anthonyafa3dfc2012-03-03 11:31:30 +00001900 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001901 {
1902 double
1903 brightness,
1904 contrast;
1905
1906 GeometryInfo
1907 geometry_info;
1908
1909 MagickStatusType
1910 flags;
1911
anthonyfd706f92012-01-19 04:22:02 +00001912 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001913 if ((flags & RhoValue) == 0)
1914 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001915 brightness=geometry_info.rho;
1916 contrast=0.0;
1917 if ((flags & SigmaValue) != 0)
1918 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001919 (void) BrightnessContrastImage(_image,brightness,contrast,
1920 _exception);
anthony805a2d42011-09-25 08:25:12 +00001921 break;
1922 }
anthonyebb73a22012-03-22 14:25:52 +00001923 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001924 }
1925 case 'c':
1926 {
anthonyafa3dfc2012-03-03 11:31:30 +00001927 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001928 {
anthony4837ac22012-05-18 23:39:48 +00001929 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001930 char
1931 *color_correction_collection;
1932
1933 /*
1934 Color correct with a color decision list.
1935 */
anthony92c93bd2012-03-19 14:02:47 +00001936 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001937 if (color_correction_collection == (char *) NULL)
1938 break;
anthony92c93bd2012-03-19 14:02:47 +00001939 (void) ColorDecisionListImage(_image,color_correction_collection,
1940 _exception);
anthony805a2d42011-09-25 08:25:12 +00001941 break;
1942 }
anthonyafa3dfc2012-03-03 11:31:30 +00001943 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001944 {
anthonyfd706f92012-01-19 04:22:02 +00001945 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001946 if ((flags & (RhoValue|SigmaValue)) == 0)
1947 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001948 if ((flags & SigmaValue) == 0)
1949 geometry_info.sigma=1.0;
1950 if ((flags & XiValue) == 0)
1951 geometry_info.xi=1.0;
cristyee3f7522012-12-21 19:27:44 +00001952 new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
1953 _exception);
anthony805a2d42011-09-25 08:25:12 +00001954 break;
1955 }
anthonyafa3dfc2012-03-03 11:31:30 +00001956 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001957 {
anthony7bcfe7f2012-03-30 14:01:22 +00001958 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001959 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001960 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1961 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001962 break;
1963 }
anthonyafa3dfc2012-03-03 11:31:30 +00001964 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001965 {
anthony92c93bd2012-03-19 14:02:47 +00001966 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001967 break;
1968 }
anthonyafa3dfc2012-03-03 11:31:30 +00001969 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001970 {
anthonyafa3dfc2012-03-03 11:31:30 +00001971 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001972 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001973 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001974 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001975 break;
1976 }
anthonyafa3dfc2012-03-03 11:31:30 +00001977 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001978 {
anthony4837ac22012-05-18 23:39:48 +00001979 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001980 CacheView
1981 *mask_view;
1982
1983 Image
1984 *mask_image;
1985
1986 register Quantum
1987 *restrict q;
1988
1989 register ssize_t
1990 x;
1991
1992 ssize_t
1993 y;
1994
anthonyafa3dfc2012-03-03 11:31:30 +00001995 if (IfPlusOp) {
anthony4837ac22012-05-18 23:39:48 +00001996 /* use "+clip-mask" Remove the write mask for -clip-path */
anthony92c93bd2012-03-19 14:02:47 +00001997 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00001998 break;
1999 }
anthony92c93bd2012-03-19 14:02:47 +00002000 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002001 if (mask_image == (Image *) NULL)
2002 break;
anthony7bcfe7f2012-03-30 14:01:22 +00002003 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00002004 break;
anthony5330ae02012-03-20 14:17:01 +00002005 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002006 /* FUTURE: use Alpha operations instead and create a Grey Image */
cristy46ff2672012-12-14 15:32:26 +00002007 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002008 for (y=0; y < (ssize_t) mask_image->rows; y++)
2009 {
2010 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002011 _exception);
anthony805a2d42011-09-25 08:25:12 +00002012 if (q == (Quantum *) NULL)
2013 break;
2014 for (x=0; x < (ssize_t) mask_image->columns; x++)
2015 {
cristy8a46d822012-08-28 23:32:39 +00002016 if (IfMagickFalse(mask_image->alpha_trait))
anthony805a2d42011-09-25 08:25:12 +00002017 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2018 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2019 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2020 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2021 q+=GetPixelChannels(mask_image);
2022 }
anthony7bcfe7f2012-03-30 14:01:22 +00002023 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00002024 break;
2025 }
anthonyfd706f92012-01-19 04:22:02 +00002026 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002027 mask_view=DestroyCacheView(mask_view);
cristy8a46d822012-08-28 23:32:39 +00002028 mask_image->alpha_trait=BlendPixelTrait;
anthony92c93bd2012-03-19 14:02:47 +00002029 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002030 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002031 break;
2032 }
anthonyafa3dfc2012-03-03 11:31:30 +00002033 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002034 {
anthony92c93bd2012-03-19 14:02:47 +00002035 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony4837ac22012-05-18 23:39:48 +00002036 /* Note: Use "+clip-mask" remove the write mask added */
anthony805a2d42011-09-25 08:25:12 +00002037 break;
2038 }
anthonyafa3dfc2012-03-03 11:31:30 +00002039 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002040 {
anthony7bcfe7f2012-03-30 14:01:22 +00002041 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002042 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002043 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002044 break;
2045 }
anthonyafa3dfc2012-03-03 11:31:30 +00002046 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002047 {
2048 KernelInfo
2049 *kernel;
2050
anthonyfd706f92012-01-19 04:22:02 +00002051 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002052 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002053 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002054 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002055 kernel=DestroyKernelInfo(kernel);
2056 break;
2057 }
anthonyafa3dfc2012-03-03 11:31:30 +00002058 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002059 {
anthony5330ae02012-03-20 14:17:01 +00002060 /* Reduce the number of colors in the image.
2061 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002062 */
anthony92c93bd2012-03-19 14:02:47 +00002063 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2064 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002065 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002066 if ((_image->storage_class == DirectClass) ||
2067 _image->colors > _quantize_info->number_colors)
2068 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002069 else
anthony92c93bd2012-03-19 14:02:47 +00002070 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002071 break;
2072 }
anthonyafa3dfc2012-03-03 11:31:30 +00002073 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002074 {
anthony5330ae02012-03-20 14:17:01 +00002075 /* WARNING: this is both a image_info setting (already done)
2076 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002077
2078 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002079 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002080
anthonyd2cdc862011-10-07 14:07:17 +00002081 Note that +colorspace sets "undefined" or no effect on
2082 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002083 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002084 */
anthony92c93bd2012-03-19 14:02:47 +00002085 (void) TransformImageColorspace(_image,
2086 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2087 _exception);
anthony805a2d42011-09-25 08:25:12 +00002088 break;
2089 }
anthonyafa3dfc2012-03-03 11:31:30 +00002090 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002091 {
anthony464f1c42012-04-22 08:51:01 +00002092 CLIWandWarnReplaced(normal_op?"-level":"+level");
anthony92c93bd2012-03-19 14:02:47 +00002093 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002094 break;
2095 }
anthonyafa3dfc2012-03-03 11:31:30 +00002096 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002097 {
2098 double
2099 black_point,
2100 white_point;
2101
2102 MagickStatusType
2103 flags;
2104
anthonyfd706f92012-01-19 04:22:02 +00002105 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002106 if ((flags & RhoValue) == 0)
2107 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002108 black_point=geometry_info.rho;
2109 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2110 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002111 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002112 black_point*=(double) _image->columns*_image->rows/100.0;
2113 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002114 }
cristya19f1d72012-08-07 18:24:38 +00002115 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002116 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002117 (void) ContrastStretchImage(_image,black_point,white_point,
2118 _exception);
anthony805a2d42011-09-25 08:25:12 +00002119 break;
2120 }
anthonyafa3dfc2012-03-03 11:31:30 +00002121 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002122 {
2123 KernelInfo
2124 *kernel_info;
2125
anthonyfd706f92012-01-19 04:22:02 +00002126 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002127 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002128 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristya12d8ba2012-04-29 16:33:41 +00002129 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2130 _exception);
anthony805a2d42011-09-25 08:25:12 +00002131 kernel_info=DestroyKernelInfo(kernel_info);
2132 break;
2133 }
anthonyafa3dfc2012-03-03 11:31:30 +00002134 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002135 {
anthony31f1bf72012-01-30 12:37:22 +00002136 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002137 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002138 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002139 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002140 break;
2141 }
anthonyafa3dfc2012-03-03 11:31:30 +00002142 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002143 {
anthony7bcfe7f2012-03-30 14:01:22 +00002144 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002145 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002146 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2147 _exception);
anthony805a2d42011-09-25 08:25:12 +00002148 break;
2149 }
anthonyebb73a22012-03-22 14:25:52 +00002150 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002151 }
2152 case 'd':
2153 {
anthonyafa3dfc2012-03-03 11:31:30 +00002154 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002155 {
anthony4837ac22012-05-18 23:39:48 +00002156 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002157 StringInfo
2158 *passkey;
2159
anthony92c93bd2012-03-19 14:02:47 +00002160 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002161 if (passkey == (StringInfo *) NULL)
2162 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2163
2164 (void) PasskeyDecipherImage(_image,passkey,_exception);
2165 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002166 break;
2167 }
anthonyafa3dfc2012-03-03 11:31:30 +00002168 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002169 {
anthony92c93bd2012-03-19 14:02:47 +00002170 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002171 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002172
anthonydcf510d2011-10-30 13:51:40 +00002173 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2174 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002175
anthonyfd706f92012-01-19 04:22:02 +00002176 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002177 */
anthony92c93bd2012-03-19 14:02:47 +00002178 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002179 break;
2180 }
anthonyafa3dfc2012-03-03 11:31:30 +00002181 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002182 {
2183 double
2184 threshold;
2185
anthonyebb73a22012-03-22 14:25:52 +00002186 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002187 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002188 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002189 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002190 }
anthonyafa3dfc2012-03-03 11:31:30 +00002191 else
2192 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002193 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002194 break;
2195 }
anthonyafa3dfc2012-03-03 11:31:30 +00002196 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002197 {
anthony92c93bd2012-03-19 14:02:47 +00002198 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002199 break;
2200 }
anthonyafa3dfc2012-03-03 11:31:30 +00002201 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002202 {
anthony805a2d42011-09-25 08:25:12 +00002203 double
anthonyb1d483a2012-04-14 12:53:56 +00002204 *args;
anthony805a2d42011-09-25 08:25:12 +00002205
anthonyb1d483a2012-04-14 12:53:56 +00002206 ssize_t
2207 count;
anthony805a2d42011-09-25 08:25:12 +00002208
anthony2a0ec8c2012-03-24 04:35:56 +00002209 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2210 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002211 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2212 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002213 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002214 {
anthony80c37752012-01-16 01:03:11 +00002215 double
2216 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002217 /* Special Case - Argument is actually a resize geometry!
2218 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002219 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002220 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002221 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002222 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2223 option,arg2);
2224 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002225 resize_args[0]=(double) geometry.width;
2226 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002227 new_image=DistortImage(_image,(DistortImageMethod) parse,
2228 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002229 break;
2230 }
anthonyb1d483a2012-04-14 12:53:56 +00002231 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002232 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002233 if (args == (double *)NULL )
2234 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2235
2236 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
2237 plus_alt_op,_exception);
2238 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002239 break;
2240 }
anthonyafa3dfc2012-03-03 11:31:30 +00002241 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002242 {
anthony92c93bd2012-03-19 14:02:47 +00002243 (void) CloneString(&_draw_info->primitive,arg1);
2244 (void) DrawImage(_image,_draw_info,_exception);
2245 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002246 break;
2247 }
anthonyebb73a22012-03-22 14:25:52 +00002248 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002249 }
2250 case 'e':
2251 {
anthonyafa3dfc2012-03-03 11:31:30 +00002252 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002253 {
anthonyfd706f92012-01-19 04:22:02 +00002254 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002255 if ((flags & (RhoValue|SigmaValue)) == 0)
2256 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002257 if ((flags & SigmaValue) == 0)
2258 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002259 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2260 _exception);
anthony805a2d42011-09-25 08:25:12 +00002261 break;
2262 }
anthonyafa3dfc2012-03-03 11:31:30 +00002263 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002264 {
anthonyfd706f92012-01-19 04:22:02 +00002265 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002266 if ((flags & (RhoValue|SigmaValue)) == 0)
2267 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002268 if ((flags & SigmaValue) == 0)
2269 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002270 new_image=EmbossImage(_image,geometry_info.rho,
2271 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002272 break;
2273 }
anthonyafa3dfc2012-03-03 11:31:30 +00002274 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002275 {
anthony4837ac22012-05-18 23:39:48 +00002276 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002277 StringInfo
2278 *passkey;
2279
anthony92c93bd2012-03-19 14:02:47 +00002280 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002281 if (passkey != (StringInfo *) NULL)
2282 {
anthony92c93bd2012-03-19 14:02:47 +00002283 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002284 passkey=DestroyStringInfo(passkey);
2285 }
2286 break;
2287 }
anthonyafa3dfc2012-03-03 11:31:30 +00002288 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002289 {
anthony92c93bd2012-03-19 14:02:47 +00002290 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002291 break;
2292 }
anthonyafa3dfc2012-03-03 11:31:30 +00002293 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002294 {
anthony92c93bd2012-03-19 14:02:47 +00002295 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002296 break;
2297 }
anthonyafa3dfc2012-03-03 11:31:30 +00002298 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002299 {
2300 double
2301 constant;
2302
anthony2a0ec8c2012-03-24 04:35:56 +00002303 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2304 if ( parse < 0 )
2305 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2306 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002307 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002308 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002309 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002310 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2311 _exception);
anthony805a2d42011-09-25 08:25:12 +00002312 break;
2313 }
anthonyafa3dfc2012-03-03 11:31:30 +00002314 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002315 {
anthony7bcfe7f2012-03-30 14:01:22 +00002316 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002317 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002318 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002319 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002320 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002321 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002322 geometry.height=_image->rows;
2323 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002324 break;
2325 }
anthonyebb73a22012-03-22 14:25:52 +00002326 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002327 }
2328 case 'f':
2329 {
anthonyafa3dfc2012-03-03 11:31:30 +00002330 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002331 {
anthony31f1bf72012-01-30 12:37:22 +00002332 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002333 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002334 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002335 break;
2336 }
anthony92c93bd2012-03-19 14:02:47 +00002337 (void) SetImageArtifact(_image,"identify:features","true");
2338 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002339 break;
2340 }
anthonyafa3dfc2012-03-03 11:31:30 +00002341 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002342 {
anthony92c93bd2012-03-19 14:02:47 +00002343 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002344 break;
2345 }
anthonyafa3dfc2012-03-03 11:31:30 +00002346 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002347 {
anthony92c93bd2012-03-19 14:02:47 +00002348 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002349 break;
2350 }
anthonyafa3dfc2012-03-03 11:31:30 +00002351 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002352 {
2353 PixelInfo
2354 target;
2355
anthony7bcfe7f2012-03-30 14:01:22 +00002356 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002357 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002358 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2359 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2360 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
cristy4b892612012-08-03 19:31:31 +00002361 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002362 break;
2363 }
anthonyafa3dfc2012-03-03 11:31:30 +00002364 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002365 {
2366 FrameInfo
2367 frame_info;
2368
anthony31f1bf72012-01-30 12:37:22 +00002369 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002370 compose;
2371
2372 const char*
2373 value;
2374
anthony92c93bd2012-03-19 14:02:47 +00002375 value=GetImageOption(_image_info,"compose");
anthony92c93bd2012-03-19 14:02:47 +00002376 compose=OverCompositeOp; /* use Over not _image->compose */
cristy4b892612012-08-03 19:31:31 +00002377 if (value != (const char *) NULL)
2378 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2379 MagickFalse,value);
anthony7bcfe7f2012-03-30 14:01:22 +00002380 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002381 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002382 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002383 frame_info.width=geometry.width;
2384 frame_info.height=geometry.height;
anthony805a2d42011-09-25 08:25:12 +00002385 frame_info.outer_bevel=geometry.x;
2386 frame_info.inner_bevel=geometry.y;
2387 frame_info.x=(ssize_t) frame_info.width;
2388 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002389 frame_info.width=_image->columns+2*frame_info.width;
2390 frame_info.height=_image->rows+2*frame_info.height;
2391 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002392 break;
2393 }
anthonyafa3dfc2012-03-03 11:31:30 +00002394 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002395 {
anthony805a2d42011-09-25 08:25:12 +00002396 double
anthonyb1d483a2012-04-14 12:53:56 +00002397 *args;
anthony805a2d42011-09-25 08:25:12 +00002398
anthonyb1d483a2012-04-14 12:53:56 +00002399 ssize_t
2400 count;
anthony805a2d42011-09-25 08:25:12 +00002401
anthony2a0ec8c2012-03-24 04:35:56 +00002402 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2403 if ( parse < 0 )
2404 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2405 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002406 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002407 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002408 if (args == (double *)NULL )
2409 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2410
2411 (void) FunctionImage(_image,(MagickFunction)parse,count,args,
2412 _exception);
2413 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002414 break;
2415 }
anthonyebb73a22012-03-22 14:25:52 +00002416 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002417 }
2418 case 'g':
2419 {
anthonyafa3dfc2012-03-03 11:31:30 +00002420 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002421 {
anthony7a4d6102012-07-01 09:48:25 +00002422 double
2423 constant;
2424
anthony7bcfe7f2012-03-30 14:01:22 +00002425 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002426 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony7a4d6102012-07-01 09:48:25 +00002427 constant=StringToDouble(arg1,(char **) NULL);
2428#if 0
2429 /* Using Gamma, via a cache */
2430 if (IfPlusOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002431 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002432 (void) GammaImage(_image,constant,_exception);
2433#else
2434 /* Using Evaluate POW, direct update of values - more accurite */
anthonyafa3dfc2012-03-03 11:31:30 +00002435 if (IfNormalOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002436 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002437 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
2438#endif
2439 /* Set gamma setting -- Old meaning of "+gamma"
2440 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2441 */
anthony805a2d42011-09-25 08:25:12 +00002442 break;
2443 }
anthony975a8d72012-04-12 13:54:36 +00002444 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002445 {
anthonyfd706f92012-01-19 04:22:02 +00002446 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002447 if ((flags & (RhoValue|SigmaValue)) == 0)
2448 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002449 if ((flags & SigmaValue) == 0)
2450 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002451 new_image=GaussianBlurImage(_image,geometry_info.rho,
2452 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002453 break;
2454 }
anthony975a8d72012-04-12 13:54:36 +00002455 if (LocaleCompare("gaussian",option+1) == 0)
2456 {
anthony464f1c42012-04-22 08:51:01 +00002457 CLIWandWarnReplaced("-gaussian-blur");
anthony975a8d72012-04-12 13:54:36 +00002458 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
2459 }
anthonyafa3dfc2012-03-03 11:31:30 +00002460 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002461 {
anthonyfd706f92012-01-19 04:22:02 +00002462 /*
anthony31f1bf72012-01-30 12:37:22 +00002463 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002464 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002465 FUTURE: Why if no 'offset' does this resize ALL images?
2466 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002467 */
anthonyafa3dfc2012-03-03 11:31:30 +00002468 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002469 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002470 if (_image->geometry != (char *) NULL)
2471 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002472 break;
2473 }
anthony7bcfe7f2012-03-30 14:01:22 +00002474 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002475 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002476 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002477 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002478 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002479 else
anthony92c93bd2012-03-19 14:02:47 +00002480 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002481 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002482 break;
2483 }
anthonyebb73a22012-03-22 14:25:52 +00002484 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002485 }
anthony805a2d42011-09-25 08:25:12 +00002486 case 'i':
2487 {
anthonyafa3dfc2012-03-03 11:31:30 +00002488 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002489 {
anthony31f1bf72012-01-30 12:37:22 +00002490 const char
2491 *format,
anthony805a2d42011-09-25 08:25:12 +00002492 *text;
2493
anthony92c93bd2012-03-19 14:02:47 +00002494 format=GetImageOption(_image_info,"format");
anthony964d28e2012-05-17 23:39:46 +00002495 if (format == (char *) NULL) {
2496 (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception);
2497 break;
2498 }
anthony92c93bd2012-03-19 14:02:47 +00002499 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002500 if (text == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00002501 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
2502 option);
anthony805a2d42011-09-25 08:25:12 +00002503 (void) fputs(text,stdout);
2504 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002505 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002506 break;
2507 }
anthonyafa3dfc2012-03-03 11:31:30 +00002508 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002509 {
anthonyb1e21ed2012-04-20 12:43:12 +00002510 flags=ParseGeometry(arg1,&geometry_info);
2511 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002512 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002513 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2514 _exception);
anthony805a2d42011-09-25 08:25:12 +00002515 break;
2516 }
anthonyafa3dfc2012-03-03 11:31:30 +00002517 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002518 {
anthonyfe1aa782012-03-24 13:43:04 +00002519 /* FUTURE: New to IMv7
2520 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002521 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002522 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002523 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2524 new_image=InterpolativeResizeImage(_image,geometry.width,
2525 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002526 break;
2527 }
anthonyebb73a22012-03-22 14:25:52 +00002528 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002529 }
2530 case 'l':
2531 {
anthonyafa3dfc2012-03-03 11:31:30 +00002532 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002533 {
anthonyfd706f92012-01-19 04:22:02 +00002534 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002535 if ((flags & (RhoValue|SigmaValue)) == 0)
2536 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyb5c691e2012-09-14 17:12:40 +00002537 if ((flags & SigmaValue) == 0)
2538 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00002539 if ((flags & PercentValue) != 0)
2540 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002541 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002542 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002543 _exception);
anthony805a2d42011-09-25 08:25:12 +00002544 break;
2545 }
anthonyafa3dfc2012-03-03 11:31:30 +00002546 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002547 {
cristya19f1d72012-08-07 18:24:38 +00002548 double
anthony805a2d42011-09-25 08:25:12 +00002549 black_point,
2550 gamma,
2551 white_point;
2552
2553 MagickStatusType
2554 flags;
2555
anthonyfd706f92012-01-19 04:22:02 +00002556 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002557 if ((flags & RhoValue) == 0)
2558 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002559 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002560 white_point=(double) QuantumRange;
anthony805a2d42011-09-25 08:25:12 +00002561 if ((flags & SigmaValue) != 0)
2562 white_point=geometry_info.sigma;
2563 gamma=1.0;
2564 if ((flags & XiValue) != 0)
2565 gamma=geometry_info.xi;
2566 if ((flags & PercentValue) != 0)
2567 {
cristya19f1d72012-08-07 18:24:38 +00002568 black_point*=(double) (QuantumRange/100.0);
2569 white_point*=(double) (QuantumRange/100.0);
anthony805a2d42011-09-25 08:25:12 +00002570 }
2571 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002572 white_point=(double) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002573 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002574 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002575 else
anthony92c93bd2012-03-19 14:02:47 +00002576 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002577 break;
2578 }
anthonyafa3dfc2012-03-03 11:31:30 +00002579 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002580 {
2581 char
2582 token[MaxTextExtent];
2583
2584 const char
2585 *p;
2586
2587 PixelInfo
2588 black_point,
2589 white_point;
2590
anthonyfd706f92012-01-19 04:22:02 +00002591 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002592 GetMagickToken(p,&p,token); /* get black point color */
2593 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002594 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002595 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002596 else
cristy269c9412011-10-13 23:41:15 +00002597 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002598 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002599 if (isalpha((int) token[0]) || (token[0] == '#'))
2600 GetMagickToken(p,&p,token);
2601 if (*token == '\0')
2602 white_point=black_point; /* set everything to that color */
2603 else
2604 {
2605 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2606 GetMagickToken(p,&p,token); /* Get white point color. */
2607 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002608 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002609 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002610 else
cristy269c9412011-10-13 23:41:15 +00002611 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002612 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002613 }
anthony92c93bd2012-03-19 14:02:47 +00002614 (void) LevelImageColors(_image,&black_point,&white_point,
2615 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002616 break;
2617 }
anthonyafa3dfc2012-03-03 11:31:30 +00002618 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002619 {
2620 double
2621 black_point,
2622 white_point;
2623
2624 MagickStatusType
2625 flags;
2626
anthonyfd706f92012-01-19 04:22:02 +00002627 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002628 if ((flags & RhoValue) == 0)
2629 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002630 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002631 white_point=(double) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002632 if ((flags & SigmaValue) != 0)
2633 white_point=geometry_info.sigma;
2634 if ((flags & PercentValue) != 0)
2635 {
anthony92c93bd2012-03-19 14:02:47 +00002636 black_point*=(double) _image->columns*_image->rows/100.0;
2637 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002638 }
2639 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002640 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002641 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002642 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002643 break;
2644 }
anthonyafa3dfc2012-03-03 11:31:30 +00002645 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002646 {
anthonyfe1aa782012-03-24 13:43:04 +00002647 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002648 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002649 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002650 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002651 if ((flags & XValue) == 0)
2652 geometry.x=1;
2653 if ((flags & YValue) == 0)
2654 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002655 new_image=LiquidRescaleImage(_image,geometry.width,
2656 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002657 break;
2658 }
anthonyebb73a22012-03-22 14:25:52 +00002659 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002660 }
2661 case 'm':
2662 {
anthonyafa3dfc2012-03-03 11:31:30 +00002663 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002664 {
anthony464f1c42012-04-22 08:51:01 +00002665 CLIWandWarnReplaced("-remap");
anthony975a8d72012-04-12 13:54:36 +00002666 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
anthony805a2d42011-09-25 08:25:12 +00002667 break;
2668 }
anthonyafa3dfc2012-03-03 11:31:30 +00002669 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002670 {
anthony4837ac22012-05-18 23:39:48 +00002671 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002672 Image
2673 *mask;
2674
anthonyafa3dfc2012-03-03 11:31:30 +00002675 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002676 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002677 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002678 break;
2679 }
anthony5330ae02012-03-20 14:17:01 +00002680 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002681 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002682 if (mask == (Image *) NULL)
2683 break;
anthony92c93bd2012-03-19 14:02:47 +00002684 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002685 mask=DestroyImage(mask);
2686 break;
2687 }
anthonyafa3dfc2012-03-03 11:31:30 +00002688 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002689 {
anthony464f1c42012-04-22 08:51:01 +00002690 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
anthony92c93bd2012-03-19 14:02:47 +00002691 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2692 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002693 break;
2694 }
anthonya3ef4ed2012-03-17 06:52:53 +00002695 if (LocaleCompare("median",option+1) == 0)
2696 {
anthony464f1c42012-04-22 08:51:01 +00002697 CLIWandWarnReplaced("-statistic Median");
anthonya3ef4ed2012-03-17 06:52:53 +00002698 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2699 break;
2700 }
anthonyafa3dfc2012-03-03 11:31:30 +00002701 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002702 {
anthony975a8d72012-04-12 13:54:36 +00002703 /* FUTURE: note this is also a special "montage" option */
anthony464f1c42012-04-22 08:51:01 +00002704 CLIWandWarnReplaced("-statistic Mode");
anthony975a8d72012-04-12 13:54:36 +00002705 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
anthony805a2d42011-09-25 08:25:12 +00002706 break;
2707 }
anthonyafa3dfc2012-03-03 11:31:30 +00002708 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002709 {
anthony7bcfe7f2012-03-30 14:01:22 +00002710 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002711 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002712 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002713 break;
2714 }
anthonyafa3dfc2012-03-03 11:31:30 +00002715 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002716 {
anthony92c93bd2012-03-19 14:02:47 +00002717 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002718 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002719 break;
2720 }
anthonyafa3dfc2012-03-03 11:31:30 +00002721 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002722 {
anthony92c93bd2012-03-19 14:02:47 +00002723 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002724 break;
2725 }
anthonyafa3dfc2012-03-03 11:31:30 +00002726 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002727 {
2728 char
2729 token[MaxTextExtent];
2730
2731 const char
2732 *p;
2733
2734 KernelInfo
2735 *kernel;
2736
anthony805a2d42011-09-25 08:25:12 +00002737 ssize_t
2738 iterations;
2739
anthonyfd706f92012-01-19 04:22:02 +00002740 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002741 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002742 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2743 if ( parse < 0 )
2744 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2745 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002746 iterations=1L;
2747 GetMagickToken(p,&p,token);
2748 if ((*p == ':') || (*p == ','))
2749 GetMagickToken(p,&p,token);
2750 if ((*p != '\0'))
2751 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002752 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002753 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002754 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2755 option,arg2);
2756 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2757 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002758 kernel=DestroyKernelInfo(kernel);
2759 break;
2760 }
anthonyafa3dfc2012-03-03 11:31:30 +00002761 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002762 {
anthonyfd706f92012-01-19 04:22:02 +00002763 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002764 if ((flags & (RhoValue|SigmaValue)) == 0)
2765 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002766 if ((flags & SigmaValue) == 0)
2767 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002768 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002769 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002770 break;
2771 }
anthonyebb73a22012-03-22 14:25:52 +00002772 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002773 }
2774 case 'n':
2775 {
anthonyafa3dfc2012-03-03 11:31:30 +00002776 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002777 {
anthony92c93bd2012-03-19 14:02:47 +00002778 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002779 break;
2780 }
anthonyafa3dfc2012-03-03 11:31:30 +00002781 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002782 {
anthony975a8d72012-04-12 13:54:36 +00002783 double
2784 attenuate;
2785
2786 const char*
2787 value;
2788
anthonyafa3dfc2012-03-03 11:31:30 +00002789 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002790 {
anthony464f1c42012-04-22 08:51:01 +00002791 CLIWandWarnReplaced("-statistic NonPeak");
anthony975a8d72012-04-12 13:54:36 +00002792 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
2793 break;
anthony805a2d42011-09-25 08:25:12 +00002794 }
anthony975a8d72012-04-12 13:54:36 +00002795 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2796 if ( parse < 0 )
2797 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2798 option,arg1);
2799 attenuate=1.0;
2800 value=GetImageOption(_image_info,"attenuate");
2801 if (value != (const char *) NULL)
2802 attenuate=StringToDouble(value,(char **) NULL);
2803 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2804 _exception);
anthony805a2d42011-09-25 08:25:12 +00002805 break;
2806 }
anthonyafa3dfc2012-03-03 11:31:30 +00002807 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002808 {
anthony92c93bd2012-03-19 14:02:47 +00002809 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002810 break;
2811 }
anthonyebb73a22012-03-22 14:25:52 +00002812 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002813 }
2814 case 'o':
2815 {
anthonyafa3dfc2012-03-03 11:31:30 +00002816 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002817 {
2818 PixelInfo
2819 target;
2820
anthony92c93bd2012-03-19 14:02:47 +00002821 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2822 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2823 _exception);
anthony805a2d42011-09-25 08:25:12 +00002824 break;
2825 }
anthonyafa3dfc2012-03-03 11:31:30 +00002826 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002827 {
anthony92c93bd2012-03-19 14:02:47 +00002828 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002829 break;
2830 }
anthonyebb73a22012-03-22 14:25:52 +00002831 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002832 }
2833 case 'p':
2834 {
anthonyafa3dfc2012-03-03 11:31:30 +00002835 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002836 {
anthony22de2722012-04-19 14:43:00 +00002837 flags=ParseGeometry(arg1,&geometry_info);
2838 if ((flags & (RhoValue|SigmaValue)) == 0)
2839 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002840 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2841 _exception);
anthony805a2d42011-09-25 08:25:12 +00002842 break;
2843 }
cristy7884a932012-11-04 14:33:51 +00002844 if (LocaleCompare("perceptible",option+1) == 0)
2845 {
2846 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2847 _exception);
2848 break;
2849 }
anthonyafa3dfc2012-03-03 11:31:30 +00002850 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002851 {
cristye9e3d382011-12-14 01:50:13 +00002852 const char
2853 *caption;
2854
anthony805a2d42011-09-25 08:25:12 +00002855 double
2856 angle;
2857
anthony7bc87992012-03-25 02:32:51 +00002858 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002859 RandomInfo
2860 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002861
anthonyf42014d2012-03-25 09:53:06 +00002862 random_info=AcquireRandomInfo();
2863 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2864 random_info=DestroyRandomInfo(random_info);
2865 }
anthony7bc87992012-03-25 02:32:51 +00002866 else {
anthonyf42014d2012-03-25 09:53:06 +00002867 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002868 if ((flags & RhoValue) == 0)
2869 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002870 angle=geometry_info.rho;
2871 }
anthony92c93bd2012-03-19 14:02:47 +00002872 caption=GetImageProperty(_image,"caption",_exception);
2873 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2874 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002875 break;
2876 }
anthonyafa3dfc2012-03-03 11:31:30 +00002877 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002878 {
anthony22de2722012-04-19 14:43:00 +00002879 flags=ParseGeometry(arg1,&geometry_info);
2880 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002881 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002882 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
cristycbda6112012-05-27 20:57:16 +00002883 _quantize_info->dither_method,_exception);
anthony805a2d42011-09-25 08:25:12 +00002884 break;
2885 }
anthonyafa3dfc2012-03-03 11:31:30 +00002886 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002887 {
anthony31f1bf72012-01-30 12:37:22 +00002888 /* FUTURE: should be a 'Genesis' option?
2889 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00002890 Why???
cristy947cb4c2011-10-20 18:41:46 +00002891 */
anthony7bc87992012-03-25 02:32:51 +00002892 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2893 if ( parse < 0 )
2894 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2895 option,arg1);
2896 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00002897 break;
2898 }
anthonyafa3dfc2012-03-03 11:31:30 +00002899 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002900 {
anthony4837ac22012-05-18 23:39:48 +00002901 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002902 const char
2903 *name;
2904
2905 const StringInfo
2906 *profile;
2907
2908 Image
2909 *profile_image;
2910
2911 ImageInfo
2912 *profile_info;
2913
anthonyafa3dfc2012-03-03 11:31:30 +00002914 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002915 { /* Remove a profile from the _image. */
2916 (void) ProfileImage(_image,arg1,(const unsigned char *)
2917 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002918 break;
2919 }
anthony92c93bd2012-03-19 14:02:47 +00002920 /* Associate a profile with the _image. */
2921 profile_info=CloneImageInfo(_image_info);
2922 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002923 if (profile != (StringInfo *) NULL)
2924 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002925 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002926 profile_info=DestroyImageInfo(profile_info);
2927 if (profile_image == (Image *) NULL)
2928 {
2929 StringInfo
2930 *profile;
2931
anthony92c93bd2012-03-19 14:02:47 +00002932 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002933 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002934 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002935 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002936 if (profile != (StringInfo *) NULL)
2937 {
anthony92c93bd2012-03-19 14:02:47 +00002938 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002939 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002940 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002941 profile=DestroyStringInfo(profile);
2942 }
2943 profile_info=DestroyImageInfo(profile_info);
2944 break;
2945 }
2946 ResetImageProfileIterator(profile_image);
2947 name=GetNextImageProfile(profile_image);
2948 while (name != (const char *) NULL)
2949 {
2950 profile=GetImageProfile(profile_image,name);
2951 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002952 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2953 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002954 name=GetNextImageProfile(profile_image);
2955 }
2956 profile_image=DestroyImage(profile_image);
2957 break;
2958 }
anthonyebb73a22012-03-22 14:25:52 +00002959 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002960 }
anthony805a2d42011-09-25 08:25:12 +00002961 case 'r':
2962 {
anthonyafa3dfc2012-03-03 11:31:30 +00002963 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002964 {
anthonyfd706f92012-01-19 04:22:02 +00002965 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002966 if ((flags & RhoValue) == 0)
2967 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyaa2c16c2012-03-25 22:21:35 +00002968 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002969 break;
2970 }
anthonyafa3dfc2012-03-03 11:31:30 +00002971 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002972 {
anthony7bcfe7f2012-03-30 14:01:22 +00002973 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002974 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002975 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00002976 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002977 break;
2978 }
anthonyafa3dfc2012-03-03 11:31:30 +00002979 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002980 {
anthony7bcfe7f2012-03-30 14:01:22 +00002981 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002982 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002983 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002984 break;
2985 }
anthony975a8d72012-04-12 13:54:36 +00002986 if (LocaleCompare("recolor",option+1) == 0)
2987 {
anthony464f1c42012-04-22 08:51:01 +00002988 CLIWandWarnReplaced("-color-matrix");
anthony975a8d72012-04-12 13:54:36 +00002989 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
2990 }
anthonyafa3dfc2012-03-03 11:31:30 +00002991 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002992 {
anthony4837ac22012-05-18 23:39:48 +00002993 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002994 Image
2995 *remap_image;
2996
anthony92c93bd2012-03-19 14:02:47 +00002997 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002998 if (remap_image == (Image *) NULL)
2999 break;
anthony92c93bd2012-03-19 14:02:47 +00003000 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003001 remap_image=DestroyImage(remap_image);
3002 break;
3003 }
anthonyafa3dfc2012-03-03 11:31:30 +00003004 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003005 {
anthonyafa3dfc2012-03-03 11:31:30 +00003006 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00003007 {
anthony7bcfe7f2012-03-30 14:01:22 +00003008 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00003009 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3010 arg1);
3011 (void) ResetImagePage(_image,arg1);
3012 }
anthony31f1bf72012-01-30 12:37:22 +00003013 else
anthony92c93bd2012-03-19 14:02:47 +00003014 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003015 break;
3016 }
anthonyafa3dfc2012-03-03 11:31:30 +00003017 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003018 {
anthonyf46d4262012-03-26 03:30:34 +00003019 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00003020 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003021 if ((flags & (RhoValue|SigmaValue)) == 0)
3022 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003023 if ((flags & SigmaValue) == 0)
3024 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003025 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003026 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003027 break;
3028 }
anthonyafa3dfc2012-03-03 11:31:30 +00003029 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003030 {
anthony7bcfe7f2012-03-30 14:01:22 +00003031 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003032 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003033 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3034 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003035 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003036 break;
3037 }
anthonyafa3dfc2012-03-03 11:31:30 +00003038 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003039 {
anthony7bcfe7f2012-03-30 14:01:22 +00003040 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003041 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003042 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3043 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003044 break;
3045 }
anthonyafa3dfc2012-03-03 11:31:30 +00003046 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003047 {
anthony22de2722012-04-19 14:43:00 +00003048 flags=ParseGeometry(arg1,&geometry_info);
3049 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003050 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00003051 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00003052 break;
3053 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3054 break;
anthony92c93bd2012-03-19 14:02:47 +00003055 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003056 break;
3057 }
anthonyebb73a22012-03-22 14:25:52 +00003058 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003059 }
3060 case 's':
3061 {
anthonyafa3dfc2012-03-03 11:31:30 +00003062 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003063 {
anthonyfe1aa782012-03-24 13:43:04 +00003064 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003065 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003066 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003067 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3068 new_image=SampleImage(_image,geometry.width,geometry.height,
3069 _exception);
anthony805a2d42011-09-25 08:25:12 +00003070 break;
3071 }
anthonyafa3dfc2012-03-03 11:31:30 +00003072 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003073 {
anthonyfe1aa782012-03-24 13:43:04 +00003074 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003075 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003076 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003077 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3078 new_image=ScaleImage(_image,geometry.width,geometry.height,
3079 _exception);
anthony805a2d42011-09-25 08:25:12 +00003080 break;
3081 }
anthonyf42014d2012-03-25 09:53:06 +00003082 if (LocaleCompare("segment",option+1) == 0)
3083 {
anthonyf42014d2012-03-25 09:53:06 +00003084 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003085 if ((flags & (RhoValue|SigmaValue)) == 0)
3086 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003087 if ((flags & SigmaValue) == 0)
3088 geometry_info.sigma=1.0;
3089 (void) SegmentImage(_image,_image->colorspace,
3090 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3091 _exception);
3092 break;
3093 }
anthonyafa3dfc2012-03-03 11:31:30 +00003094 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003095 {
anthonyfd706f92012-01-19 04:22:02 +00003096 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003097 if ((flags & (RhoValue|SigmaValue)) == 0)
3098 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3099 if ((flags & SigmaValue) == 0)
3100 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003101 if ((flags & PercentValue) != 0)
3102 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003103 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003104 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003105 break;
3106 }
anthonyafa3dfc2012-03-03 11:31:30 +00003107 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003108 {
anthony31f1bf72012-01-30 12:37:22 +00003109 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003110 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003111 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003112 break;
3113 }
anthonyafa3dfc2012-03-03 11:31:30 +00003114 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003115 {
anthony7bcfe7f2012-03-30 14:01:22 +00003116 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003117 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3118 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3119 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003120 break;
3121 }
anthonyafa3dfc2012-03-03 11:31:30 +00003122 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003123 {
anthonyfd706f92012-01-19 04:22:02 +00003124 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003125 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3126 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003127 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3128 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003129 break;
3130 }
anthonyafa3dfc2012-03-03 11:31:30 +00003131 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003132 {
anthonyfd706f92012-01-19 04:22:02 +00003133 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003134 if ((flags & (RhoValue|SigmaValue)) == 0)
3135 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003136 if ((flags & SigmaValue) == 0)
3137 geometry_info.sigma=1.0;
3138 if ((flags & XiValue) == 0)
3139 geometry_info.xi=4.0;
3140 if ((flags & PsiValue) == 0)
3141 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003142 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3143 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3144 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003145 break;
3146 }
anthonyafa3dfc2012-03-03 11:31:30 +00003147 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003148 {
anthonyfd706f92012-01-19 04:22:02 +00003149 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003150 if ((flags & (RhoValue|SigmaValue)) == 0)
3151 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003152 if ((flags & SigmaValue) == 0)
3153 geometry_info.sigma=1.0;
3154 if ((flags & XiValue) == 0)
3155 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003156 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3157 _exception);
anthony805a2d42011-09-25 08:25:12 +00003158 break;
3159 }
anthonyafa3dfc2012-03-03 11:31:30 +00003160 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003161 {
anthony7bcfe7f2012-03-30 14:01:22 +00003162 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003163 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003164 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3165 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003166 break;
3167 }
anthonyafa3dfc2012-03-03 11:31:30 +00003168 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003169 {
anthonyfd706f92012-01-19 04:22:02 +00003170 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003171 if ((flags & RhoValue) == 0)
3172 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003173 if ((flags & SigmaValue) == 0)
3174 geometry_info.sigma=geometry_info.rho;
cristy4b892612012-08-03 19:31:31 +00003175 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3176 _exception);
anthony805a2d42011-09-25 08:25:12 +00003177 break;
3178 }
anthonyafa3dfc2012-03-03 11:31:30 +00003179 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003180 {
anthonyfd706f92012-01-19 04:22:02 +00003181 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003182 if ((flags & RhoValue) == 0)
3183 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003184 if ((flags & SigmaValue) == 0)
3185 geometry_info.sigma=(double) QuantumRange/2.0;
3186 if ((flags & PercentValue) != 0)
3187 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3188 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003189 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003190 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003191 break;
3192 }
anthonyafa3dfc2012-03-03 11:31:30 +00003193 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003194 {
anthonyfd706f92012-01-19 04:22:02 +00003195 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003196 if ((flags & (RhoValue|SigmaValue)) == 0)
3197 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003198 if ((flags & SigmaValue) == 0)
3199 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003200 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003201 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003202 break;
3203 }
anthonyafa3dfc2012-03-03 11:31:30 +00003204 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003205 {
anthony7bcfe7f2012-03-30 14:01:22 +00003206 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003207 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003208 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3209 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003210 break;
3211 }
anthonyafa3dfc2012-03-03 11:31:30 +00003212 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003213 {
anthonyf42014d2012-03-25 09:53:06 +00003214 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3215 if ( parse < 0 )
3216 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3217 option,arg1);
anthony964d28e2012-05-17 23:39:46 +00003218 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3219 _exception);
anthony805a2d42011-09-25 08:25:12 +00003220 break;
3221 }
anthonyafa3dfc2012-03-03 11:31:30 +00003222 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003223 {
anthony7bcfe7f2012-03-30 14:01:22 +00003224 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003225 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003226 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003227 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003228 break;
3229 }
anthonyafa3dfc2012-03-03 11:31:30 +00003230 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003231 {
anthonyb1e21ed2012-04-20 12:43:12 +00003232 flags=ParseGeometry(arg1,&geometry_info);
3233 if ((flags & RhoValue) == 0)
3234 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003235 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3236 _exception);
anthony805a2d42011-09-25 08:25:12 +00003237 break;
3238 }
anthonyafa3dfc2012-03-03 11:31:30 +00003239 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003240 {
anthony7bc87992012-03-25 02:32:51 +00003241 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3242 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003243 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003244 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003245 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003246 if ((flags & RhoValue) == 0)
3247 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003248 if ((flags & SigmaValue) == 0)
3249 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003250 new_image=StatisticImage(_image,(StatisticType)parse,
3251 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3252 _exception);
anthony805a2d42011-09-25 08:25:12 +00003253 break;
3254 }
anthonyafa3dfc2012-03-03 11:31:30 +00003255 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003256 {
anthony92c93bd2012-03-19 14:02:47 +00003257 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003258 break;
3259 }
anthonyafa3dfc2012-03-03 11:31:30 +00003260 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003261 {
cristy898c6042012-06-24 00:36:34 +00003262 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00003263 if ((flags & RhoValue) == 0)
cristy898c6042012-06-24 00:36:34 +00003264 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003265 new_image=SwirlImage(_image,geometry_info.rho,
3266 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003267 break;
3268 }
anthonyebb73a22012-03-22 14:25:52 +00003269 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003270 }
3271 case 't':
3272 {
anthonyafa3dfc2012-03-03 11:31:30 +00003273 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003274 {
3275 double
3276 threshold;
3277
anthony52bef752012-03-27 13:54:47 +00003278 threshold=(double) QuantumRange/2;
3279 if (normal_op) {
anthony7bcfe7f2012-03-30 14:01:22 +00003280 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003281 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003282 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003283 }
anthony92c93bd2012-03-19 14:02:47 +00003284 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003285 break;
3286 }
anthonyafa3dfc2012-03-03 11:31:30 +00003287 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003288 {
anthony7bcfe7f2012-03-30 14:01:22 +00003289 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003290 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003291 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3292 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3293 _exception);
anthony805a2d42011-09-25 08:25:12 +00003294 break;
3295 }
anthonyafa3dfc2012-03-03 11:31:30 +00003296 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003297 {
anthony7bcfe7f2012-03-30 14:01:22 +00003298 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003299 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003300 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003301 break;
3302 }
anthonyafa3dfc2012-03-03 11:31:30 +00003303 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003304 {
anthony464f1c42012-04-22 08:51:01 +00003305 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003306 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003307 break;
3308 }
anthonyafa3dfc2012-03-03 11:31:30 +00003309 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003310 {
3311 PixelInfo
3312 target;
3313
anthony92c93bd2012-03-19 14:02:47 +00003314 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3315 (void) TransparentPaintImage(_image,&target,(Quantum)
3316 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003317 break;
3318 }
anthonyafa3dfc2012-03-03 11:31:30 +00003319 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003320 {
anthony92c93bd2012-03-19 14:02:47 +00003321 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003322 break;
3323 }
anthonyafa3dfc2012-03-03 11:31:30 +00003324 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003325 {
anthony92c93bd2012-03-19 14:02:47 +00003326 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003327 break;
3328 }
anthonyafa3dfc2012-03-03 11:31:30 +00003329 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003330 {
anthony92c93bd2012-03-19 14:02:47 +00003331 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003332 break;
3333 }
anthonyafa3dfc2012-03-03 11:31:30 +00003334 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003335 {
anthonyab3a50c2011-10-27 11:48:57 +00003336 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003337 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003338 break;
3339 }
anthonyebb73a22012-03-22 14:25:52 +00003340 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003341 }
3342 case 'u':
3343 {
anthonyafa3dfc2012-03-03 11:31:30 +00003344 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003345 {
anthony52bef752012-03-27 13:54:47 +00003346 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3347 Option is not documented, bt appears to be for "identify".
3348 We may need a identify specific verbose!
3349 */
3350 if (plus_alt_op) {
anthony92c93bd2012-03-19 14:02:47 +00003351 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003352 break;
3353 }
anthony92c93bd2012-03-19 14:02:47 +00003354 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3355 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003356 break;
3357 }
anthonyafa3dfc2012-03-03 11:31:30 +00003358 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003359 {
anthony92c93bd2012-03-19 14:02:47 +00003360 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003361 break;
3362 }
anthonyafa3dfc2012-03-03 11:31:30 +00003363 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003364 {
anthonyfd706f92012-01-19 04:22:02 +00003365 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003366 if ((flags & (RhoValue|SigmaValue)) == 0)
3367 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003368 if ((flags & SigmaValue) == 0)
3369 geometry_info.sigma=1.0;
3370 if ((flags & XiValue) == 0)
3371 geometry_info.xi=1.0;
3372 if ((flags & PsiValue) == 0)
3373 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003374 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3375 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003376 break;
3377 }
anthonyebb73a22012-03-22 14:25:52 +00003378 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003379 }
3380 case 'v':
3381 {
anthonyafa3dfc2012-03-03 11:31:30 +00003382 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003383 {
anthonyafa3dfc2012-03-03 11:31:30 +00003384 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003385 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003386 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003387 */
anthony92c93bd2012-03-19 14:02:47 +00003388 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003389 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003390 break;
3391 }
anthonyafa3dfc2012-03-03 11:31:30 +00003392 if (LocaleCompare("vignette",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;
3399 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003400 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003401 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003402 geometry_info.psi=0.1*_image->rows;
3403 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003404 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3405 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003406 break;
3407 }
anthonyebb73a22012-03-22 14:25:52 +00003408 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003409 }
3410 case 'w':
3411 {
anthonyafa3dfc2012-03-03 11:31:30 +00003412 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003413 {
anthonyfd706f92012-01-19 04:22:02 +00003414 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003415 if ((flags & (RhoValue|SigmaValue)) == 0)
3416 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003417 if ((flags & SigmaValue) == 0)
3418 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003419 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3420 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003421 break;
3422 }
anthonyafa3dfc2012-03-03 11:31:30 +00003423 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003424 {
anthony7bcfe7f2012-03-30 14:01:22 +00003425 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003426 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003427 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003428 break;
3429 }
anthonyebb73a22012-03-22 14:25:52 +00003430 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003431 }
3432 default:
anthonyebb73a22012-03-22 14:25:52 +00003433 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003434 }
anthony964d28e2012-05-17 23:39:46 +00003435 /* clean up percent escape interpreted strings */
3436 if (arg1 != arg1n )
3437 arg1=DestroyString((char *)arg1);
3438 if (arg2 != arg2n )
3439 arg2=DestroyString((char *)arg2);
3440
3441 /* Replace current image with any image that was generated
3442 and set image point to last image (so image->next is correct) */
anthony805a2d42011-09-25 08:25:12 +00003443 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003444 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003445
anthony31f1bf72012-01-30 12:37:22 +00003446 return;
anthony92c93bd2012-03-19 14:02:47 +00003447#undef _image_info
3448#undef _draw_info
3449#undef _quantize_info
3450#undef _image
3451#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003452#undef IfNormalOp
3453#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003454#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003455#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003456}
anthonyfd706f92012-01-19 04:22:02 +00003457
anthony43f425d2012-02-26 12:58:58 +00003458WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003459 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003460{
anthonyc7994672012-11-17 05:33:27 +00003461#if !USE_WAND_METHODS
anthony31f1bf72012-01-30 12:37:22 +00003462 size_t
anthony43f425d2012-02-26 12:58:58 +00003463 n,
anthony31f1bf72012-01-30 12:37:22 +00003464 i;
anthonyc7994672012-11-17 05:33:27 +00003465#endif
anthony31f1bf72012-01-30 12:37:22 +00003466
anthony43f425d2012-02-26 12:58:58 +00003467 assert(cli_wand != (MagickCLI *) NULL);
3468 assert(cli_wand->signature == WandSignature);
3469 assert(cli_wand->wand.signature == WandSignature);
3470 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003471 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003472 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003473
anthonyafa3dfc2012-03-03 11:31:30 +00003474#if !USE_WAND_METHODS
3475 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003476 i=0;
anthony43f425d2012-02-26 12:58:58 +00003477 n=GetImageListLength(cli_wand->wand.images);
3478 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003479 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003480 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003481 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003482 if ( cli_wand->wand.images->next == (Image *) NULL )
3483 break;
3484 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003485 }
anthony43f425d2012-02-26 12:58:58 +00003486 assert( i == n );
3487 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003488#else
3489 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003490 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
anthonyafa3dfc2012-03-03 11:31:30 +00003491 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3492 MagickResetIterator(&cli_wand->wand);
3493#endif
anthony31f1bf72012-01-30 12:37:22 +00003494 return;
anthony805a2d42011-09-25 08:25:12 +00003495}
3496
3497/*
3498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3499% %
3500% %
3501% %
anthony43f425d2012-02-26 12:58:58 +00003502+ 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 +00003503% %
3504% %
3505% %
3506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3507%
anthony43f425d2012-02-26 12:58:58 +00003508% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003509% entire image list as a whole. The result is often a complete replacment
anthonyc7994672012-11-17 05:33:27 +00003510% of the image list with a completely new list, or with just a single image
3511% result.
anthony805a2d42011-09-25 08:25:12 +00003512%
3513% The format of the MogrifyImage method is:
3514%
anthony43f425d2012-02-26 12:58:58 +00003515% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003516% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003517%
3518% A description of each parameter follows:
3519%
anthony43f425d2012-02-26 12:58:58 +00003520% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003521%
anthony36a8c2c2012-02-10 00:08:44 +00003522% o option: The option string for the operation
3523%
anthony31f1bf72012-01-30 12:37:22 +00003524% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003525% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003526%
anthony805a2d42011-09-25 08:25:12 +00003527*/
anthony43f425d2012-02-26 12:58:58 +00003528WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthony964d28e2012-05-17 23:39:46 +00003529 const char *option,const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00003530{
anthony2a0ec8c2012-03-24 04:35:56 +00003531 ssize_t
3532 parse;
3533
anthony31f1bf72012-01-30 12:37:22 +00003534 Image
3535 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003536
anthony964d28e2012-05-17 23:39:46 +00003537 const char /* For percent escape interpretImageProperties() */
3538 *arg1,
3539 *arg2;
3540
anthony2e4501b2012-03-30 04:41:54 +00003541#define _image_info (cli_wand->wand.image_info)
3542#define _images (cli_wand->wand.images)
3543#define _exception (cli_wand->wand.exception)
3544#define _draw_info (cli_wand->draw_info)
3545#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00003546#define _process_flags (cli_wand->process_flags)
3547#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00003548#define IfNormalOp (*option=='-')
3549#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00003550#define normal_op IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003551
anthony43f425d2012-02-26 12:58:58 +00003552 assert(cli_wand != (MagickCLI *) NULL);
3553 assert(cli_wand->signature == WandSignature);
3554 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003555 assert(_images != (Image *) NULL); /* _images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003556 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003557 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003558
anthony964d28e2012-05-17 23:39:46 +00003559 /* Interpret Percent Escapes in Arguments - using first image */
3560 arg1 = arg1n;
3561 arg2 = arg2n;
3562 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3563 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3564 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3565 /* Interpret Percent escapes in argument 1 */
3566 if (arg1n != (char *) NULL) {
3567 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3568 if (arg1 == (char *) NULL) {
3569 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3570 arg1=arg1n; /* use the given argument as is */
3571 }
3572 }
3573 if (arg2n != (char *) NULL) {
3574 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3575 if (arg2 == (char *) NULL) {
3576 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3577 arg2=arg2n; /* use the given argument as is */
3578 }
3579 }
3580 }
anthony4837ac22012-05-18 23:39:48 +00003581#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00003582#undef _option_type
3583
3584#if 0
3585 (void) FormatLocaleFile(stderr,
3586 "CLIListOperatorImages: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
3587#endif
3588
3589
anthony31f1bf72012-01-30 12:37:22 +00003590 new_images=NewImageList();
3591
anthonyafa3dfc2012-03-03 11:31:30 +00003592 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003593 {
3594 case 'a':
3595 {
anthonyafa3dfc2012-03-03 11:31:30 +00003596 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003597 {
anthony92c93bd2012-03-19 14:02:47 +00003598 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003599 break;
3600 }
anthonyafa3dfc2012-03-03 11:31:30 +00003601 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003602 {
anthony464f1c42012-04-22 08:51:01 +00003603 CLIWandWarnReplaced("-evaluate-sequence Mean");
anthonyafa3dfc2012-03-03 11:31:30 +00003604 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003605 break;
3606 }
anthonyebb73a22012-03-22 14:25:52 +00003607 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003608 }
3609 case 'c':
3610 {
cristy5f257b22012-03-07 00:27:29 +00003611 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003612 {
anthony92c93bd2012-03-19 14:02:47 +00003613 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003614 break;
3615 }
anthonyafa3dfc2012-03-03 11:31:30 +00003616 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003617 {
anthony805a2d42011-09-25 08:25:12 +00003618 Image
anthony31f1bf72012-01-30 12:37:22 +00003619 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003620
anthonyafa3dfc2012-03-03 11:31:30 +00003621 /* FUTURE - make this a compose option, and thus can be used
3622 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003623 _images.
cristy87c02f42012-02-24 00:19:10 +00003624 */
anthony92c93bd2012-03-19 14:02:47 +00003625 new_images=RemoveFirstImageFromList(&_images);
3626 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003627 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003628 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003629 break;
cristye52fb5e2012-04-06 23:30:20 +00003630 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003631 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003632 break;
3633 }
anthonyafa3dfc2012-03-03 11:31:30 +00003634 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003635 {
anthony92c93bd2012-03-19 14:02:47 +00003636 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003637 break;
3638 }
anthonyafa3dfc2012-03-03 11:31:30 +00003639 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003640 {
anthony43f425d2012-02-26 12:58:58 +00003641 /* FUTURE - this may be replaced by a 'channel' method */
cristy46f354c2012-07-04 13:31:29 +00003642 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
3643 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003644 break;
3645 }
anthonyafa3dfc2012-03-03 11:31:30 +00003646 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003647 {
cristyfeb3e962012-03-29 17:25:55 +00003648 CompositeOperator
3649 compose;
3650
3651 const char*
3652 value;
3653
3654 MagickBooleanType
3655 clip_to_self;
3656
anthony805a2d42011-09-25 08:25:12 +00003657 Image
3658 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003659 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003660
3661 RectangleInfo
3662 geometry;
3663
anthony7bcfe7f2012-03-30 14:01:22 +00003664 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003665 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003666 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003667 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003668 else
3669 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3670 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003671
anthony7bcfe7f2012-03-30 14:01:22 +00003672 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003673 value=GetImageOption(_image_info,"compose:clip-to-self");
3674 if (value == (const char *) NULL)
3675 clip_to_self=MagickTrue;
3676 else
3677 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3678 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003679 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003680 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003681 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003682 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003683 }
3684
anthony92c93bd2012-03-19 14:02:47 +00003685 new_images=RemoveFirstImageFromList(&_images);
3686 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003687 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003688 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003689
anthony31f1bf72012-01-30 12:37:22 +00003690 /* FUTURE - this should not be here! - should be part of -geometry */
3691 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003692 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003693
anthony31f1bf72012-01-30 12:37:22 +00003694 SetGeometry(source_image,&geometry);
3695 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3696 GravityAdjustGeometry(new_images->columns,new_images->rows,
3697 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003698
anthony92c93bd2012-03-19 14:02:47 +00003699 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003700 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003701 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003702 if ((compose == DisplaceCompositeOp) ||
anthony7bcfe7f2012-03-30 14:01:22 +00003703 (compose == DistortCompositeOp)) {
3704 /* Merge Y displacement into X displace/distort map. */
3705 (void) CompositeImage(source_image,mask_image,
3706 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3707 mask_image=DestroyImage(mask_image);
3708 }
3709 else {
3710 /* Set a blending mask for the composition. */
3711 (void) NegateImage(mask_image,MagickFalse,_exception);
cristy665e18f2012-05-17 12:39:54 +00003712 (void) SetImageMask(source_image,mask_image,_exception);
anthony7bcfe7f2012-03-30 14:01:22 +00003713 mask_image=DestroyImage(mask_image);
3714 }
anthony805a2d42011-09-25 08:25:12 +00003715 }
cristyfeb3e962012-03-29 17:25:55 +00003716 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3717 geometry.x,geometry.y,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003718 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003719 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003720 break;
3721 }
anthonyebb73a22012-03-22 14:25:52 +00003722 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003723 }
3724 case 'd':
3725 {
anthonyafa3dfc2012-03-03 11:31:30 +00003726 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003727 {
anthony464f1c42012-04-22 08:51:01 +00003728 CLIWandWarnReplaced("-layer CompareAny");
anthonyafa3dfc2012-03-03 11:31:30 +00003729 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003730 break;
3731 }
anthonyafa3dfc2012-03-03 11:31:30 +00003732 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003733 {
anthonyafa3dfc2012-03-03 11:31:30 +00003734 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003735 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003736 else
anthony92c93bd2012-03-19 14:02:47 +00003737 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003738 break;
3739 }
anthonyafa3dfc2012-03-03 11:31:30 +00003740 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003741 {
anthonyafa3dfc2012-03-03 11:31:30 +00003742 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003743 {
3744 const char
3745 *p;
3746
3747 size_t
3748 number_duplicates;
3749
anthony7bcfe7f2012-03-30 14:01:22 +00003750 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003751 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3752 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003753 number_duplicates=(size_t) StringToLong(arg1);
3754 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003755 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003756 new_images=DuplicateImages(_images,number_duplicates,"-1",
3757 _exception);
anthony805a2d42011-09-25 08:25:12 +00003758 else
anthony92c93bd2012-03-19 14:02:47 +00003759 new_images=DuplicateImages(_images,number_duplicates,p,
3760 _exception);
anthony805a2d42011-09-25 08:25:12 +00003761 }
anthonyafa3dfc2012-03-03 11:31:30 +00003762 else
anthony92c93bd2012-03-19 14:02:47 +00003763 new_images=DuplicateImages(_images,1,"-1",_exception);
3764 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003765 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003766 break;
3767 }
anthonyebb73a22012-03-22 14:25:52 +00003768 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003769 }
3770 case 'e':
3771 {
anthonyafa3dfc2012-03-03 11:31:30 +00003772 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003773 {
anthony2a0ec8c2012-03-24 04:35:56 +00003774 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3775 if ( parse < 0 )
3776 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3777 option,arg1);
3778 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3779 _exception);
anthony805a2d42011-09-25 08:25:12 +00003780 break;
3781 }
anthonyebb73a22012-03-22 14:25:52 +00003782 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003783 }
3784 case 'f':
3785 {
anthonyafa3dfc2012-03-03 11:31:30 +00003786 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003787 {
anthony92c93bd2012-03-19 14:02:47 +00003788 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003789 break;
3790 }
anthonyafa3dfc2012-03-03 11:31:30 +00003791 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003792 {
anthony319dac62012-03-06 04:12:44 +00003793 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003794 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003795 break;
3796 }
anthonyafa3dfc2012-03-03 11:31:30 +00003797 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003798 {
anthony92c93bd2012-03-19 14:02:47 +00003799 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003800 break;
3801 }
anthonyebb73a22012-03-22 14:25:52 +00003802 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003803 }
3804 case 'h':
3805 {
anthonyafa3dfc2012-03-03 11:31:30 +00003806 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003807 {
anthony31f1bf72012-01-30 12:37:22 +00003808 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003809 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003810 */
anthony805a2d42011-09-25 08:25:12 +00003811 Image
anthony31f1bf72012-01-30 12:37:22 +00003812 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003813
anthony92c93bd2012-03-19 14:02:47 +00003814 new_images=RemoveFirstImageFromList(&_images);
3815 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003816 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003817 break;
anthony92c93bd2012-03-19 14:02:47 +00003818 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003819 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003820 break;
3821 }
anthonyebb73a22012-03-22 14:25:52 +00003822 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003823 }
3824 case 'i':
3825 {
anthonyafa3dfc2012-03-03 11:31:30 +00003826 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003827 {
3828 Image
anthony805a2d42011-09-25 08:25:12 +00003829 *magnitude_image,
3830 *phase_image;
3831
anthony92c93bd2012-03-19 14:02:47 +00003832 magnitude_image=RemoveFirstImageFromList(&_images);
3833 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003834 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003835 if (phase_image == (Image *) NULL)
3836 break;
3837 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003838 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003839 magnitude_image=DestroyImage(magnitude_image);
3840 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003841 break;
3842 }
anthonyafa3dfc2012-03-03 11:31:30 +00003843 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003844 {
3845 Image
anthony31f1bf72012-01-30 12:37:22 +00003846 *insert_image,
3847 *index_image;
3848
3849 ssize_t
3850 index;
anthony805a2d42011-09-25 08:25:12 +00003851
anthony7bcfe7f2012-03-30 14:01:22 +00003852 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00003853 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003854 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003855 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003856 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003857 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003858 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003859 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003860 PrependImageToList(&_images,insert_image);
3861 else if (index == (ssize_t) GetImageListLength(_images))
3862 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003863 else
anthony43f425d2012-02-26 12:58:58 +00003864 {
anthony92c93bd2012-03-19 14:02:47 +00003865 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003866 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00003867 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00003868 InsertImageInList(&index_image,insert_image);
3869 }
anthony92c93bd2012-03-19 14:02:47 +00003870 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003871 break;
3872 }
anthonyebb73a22012-03-22 14:25:52 +00003873 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003874 }
3875 case 'l':
3876 {
anthonyafa3dfc2012-03-03 11:31:30 +00003877 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003878 {
anthonyfe1aa782012-03-24 13:43:04 +00003879 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3880 if ( parse < 0 )
3881 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3882 option,arg1);
cristya0417062012-09-02 23:34:56 +00003883 switch ((LayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00003884 {
3885 case CoalesceLayer:
3886 {
anthony92c93bd2012-03-19 14:02:47 +00003887 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003888 break;
3889 }
3890 case CompareAnyLayer:
3891 case CompareClearLayer:
3892 case CompareOverlayLayer:
3893 default:
3894 {
cristya0417062012-09-02 23:34:56 +00003895 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00003896 _exception);
anthony805a2d42011-09-25 08:25:12 +00003897 break;
3898 }
3899 case MergeLayer:
3900 case FlattenLayer:
3901 case MosaicLayer:
3902 case TrimBoundsLayer:
3903 {
cristya0417062012-09-02 23:34:56 +00003904 new_images=MergeImageLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00003905 _exception);
anthony805a2d42011-09-25 08:25:12 +00003906 break;
3907 }
3908 case DisposeLayer:
3909 {
anthony92c93bd2012-03-19 14:02:47 +00003910 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003911 break;
3912 }
3913 case OptimizeImageLayer:
3914 {
anthony92c93bd2012-03-19 14:02:47 +00003915 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003916 break;
3917 }
3918 case OptimizePlusLayer:
3919 {
anthony92c93bd2012-03-19 14:02:47 +00003920 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003921 break;
3922 }
3923 case OptimizeTransLayer:
3924 {
anthony92c93bd2012-03-19 14:02:47 +00003925 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003926 break;
3927 }
3928 case RemoveDupsLayer:
3929 {
anthony92c93bd2012-03-19 14:02:47 +00003930 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003931 break;
3932 }
3933 case RemoveZeroLayer:
3934 {
anthony92c93bd2012-03-19 14:02:47 +00003935 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003936 break;
3937 }
3938 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003939 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003940 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003941 if (new_images == (Image *) NULL)
3942 break;
anthony92c93bd2012-03-19 14:02:47 +00003943 _images=DestroyImageList(_images);
3944 _images=OptimizeImageLayers(new_images,_exception);
3945 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003946 break;
3947 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00003948 OptimizeImageTransparency(_images,_exception);
3949 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3950 _exception);
anthony805a2d42011-09-25 08:25:12 +00003951 break;
3952 }
3953 case CompositeLayer:
3954 {
anthony805a2d42011-09-25 08:25:12 +00003955 Image
3956 *source;
3957
3958 RectangleInfo
3959 geometry;
3960
anthony31f1bf72012-01-30 12:37:22 +00003961 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003962 compose;
3963
3964 const char*
3965 value;
3966
anthony92c93bd2012-03-19 14:02:47 +00003967 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003968 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003969 if (value != (const char *) NULL)
3970 compose=(CompositeOperator) ParseCommandOption(
3971 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003972
anthony31f1bf72012-01-30 12:37:22 +00003973 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00003974 source=_images;
anthony805a2d42011-09-25 08:25:12 +00003975 while (source != (Image *) NULL)
3976 {
3977 source=GetNextImageInList(source);
3978 if ((source != (Image *) NULL) &&
3979 (LocaleCompare(source->magick,"NULL") == 0))
3980 break;
3981 }
3982 if (source != (Image *) NULL)
3983 {
3984 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3985 (GetNextImageInList(source) == (Image *) NULL))
3986 source=(Image *) NULL;
3987 else
anthony31f1bf72012-01-30 12:37:22 +00003988 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003989 source=SplitImageList(source->previous);
3990 DeleteImageFromList(&source);
3991 }
3992 }
3993 if (source == (Image *) NULL)
3994 {
anthony92c93bd2012-03-19 14:02:47 +00003995 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00003996 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003997 break;
3998 }
anthony31f1bf72012-01-30 12:37:22 +00003999 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004000 SetGeometry(_images,&geometry);
4001 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004002 geometry.width=source->page.width != 0 ?
4003 source->page.width : source->columns;
4004 geometry.height=source->page.height != 0 ?
4005 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004006 GravityAdjustGeometry(_images->page.width != 0 ?
4007 _images->page.width : _images->columns,
4008 _images->page.height != 0 ? _images->page.height :
4009 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004010
anthony31f1bf72012-01-30 12:37:22 +00004011 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004012 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4013 _exception);
anthony805a2d42011-09-25 08:25:12 +00004014 source=DestroyImageList(source);
4015 break;
4016 }
4017 }
anthony805a2d42011-09-25 08:25:12 +00004018 break;
4019 }
anthonyebb73a22012-03-22 14:25:52 +00004020 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004021 }
4022 case 'm':
4023 {
anthonyafa3dfc2012-03-03 11:31:30 +00004024 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004025 {
anthony464f1c42012-04-22 08:51:01 +00004026 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00004027 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004028 break;
4029 }
anthonyafa3dfc2012-03-03 11:31:30 +00004030 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004031 {
4032 Image
4033 *morph_image;
4034
anthony7bcfe7f2012-03-30 14:01:22 +00004035 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004036 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004037 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4038 _exception);
anthony805a2d42011-09-25 08:25:12 +00004039 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004040 break;
anthony92c93bd2012-03-19 14:02:47 +00004041 _images=DestroyImageList(_images);
4042 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004043 break;
4044 }
anthonyafa3dfc2012-03-03 11:31:30 +00004045 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004046 {
anthony319dac62012-03-06 04:12:44 +00004047 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00004048 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004049 break;
4050 }
anthonyebb73a22012-03-22 14:25:52 +00004051 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004052 }
4053 case 'p':
4054 {
cristy02016cf2012-11-13 01:14:41 +00004055 if (LocaleCompare("poly",option+1) == 0)
4056 {
4057 double
4058 *args;
4059
4060 ssize_t
4061 count;
4062
4063 /* convert argument string into an array of doubles */
4064 args = StringToArrayOfDoubles(arg2,&count,_exception);
4065 if (args == (double *)NULL )
4066 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
4067 new_images=PolynomialImage(_images,count >> 1,args,_exception);
4068 args=(double *) RelinquishMagickMemory(args);
4069 break;
4070 }
anthonyafa3dfc2012-03-03 11:31:30 +00004071 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004072 {
anthony964d28e2012-05-17 23:39:46 +00004073 (void) FormatLocaleFile(stdout,"%s",arg1);
anthony24aa8822012-03-11 00:56:06 +00004074 break;
anthony805a2d42011-09-25 08:25:12 +00004075 }
anthonyafa3dfc2012-03-03 11:31:30 +00004076 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004077 {
anthonyb1d483a2012-04-14 12:53:56 +00004078 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00004079 char
4080 **arguments;
4081
4082 int
4083 j,
4084 number_arguments;
4085
anthony31f1bf72012-01-30 12:37:22 +00004086 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004087 if (arguments == (char **) NULL)
4088 break;
anthony31f1bf72012-01-30 12:37:22 +00004089 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004090 {
4091 char
4092 breaker,
4093 quote,
4094 *token;
4095
4096 const char
4097 *arguments;
4098
4099 int
4100 next,
4101 status;
4102
4103 size_t
4104 length;
4105
4106 TokenInfo
4107 *token_info;
4108
4109 /*
anthony24aa8822012-03-11 00:56:06 +00004110 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004111 */
anthony31f1bf72012-01-30 12:37:22 +00004112 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004113 token=(char *) NULL;
4114 if (~length >= (MaxTextExtent-1))
4115 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4116 sizeof(*token));
4117 if (token == (char *) NULL)
4118 break;
4119 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004120 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004121 token_info=AcquireTokenInfo();
4122 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4123 "\"",'\0',&breaker,&next,&quote);
4124 token_info=DestroyTokenInfo(token_info);
4125 if (status == 0)
4126 {
4127 const char
4128 *argv;
4129
4130 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004131 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4132 _exception);
anthony805a2d42011-09-25 08:25:12 +00004133 }
4134 token=DestroyString(token);
4135 break;
4136 }
4137 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004138 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4139 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004140 for (j=0; j < number_arguments; j++)
4141 arguments[j]=DestroyString(arguments[j]);
4142 arguments=(char **) RelinquishMagickMemory(arguments);
4143 break;
4144 }
anthonyebb73a22012-03-22 14:25:52 +00004145 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004146 }
4147 case 'r':
4148 {
anthonyafa3dfc2012-03-03 11:31:30 +00004149 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004150 {
anthony92c93bd2012-03-19 14:02:47 +00004151 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004152 break;
4153 }
anthonyafa3dfc2012-03-03 11:31:30 +00004154 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004155 {
anthony92c93bd2012-03-19 14:02:47 +00004156 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004157 break;
4158 }
anthonyebb73a22012-03-22 14:25:52 +00004159 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004160 }
4161 case 's':
4162 {
anthonyafa3dfc2012-03-03 11:31:30 +00004163 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004164 {
anthonycd358fc2012-04-16 13:59:03 +00004165 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004166 ssize_t
4167 offset;
4168
anthony7bcfe7f2012-03-30 14:01:22 +00004169 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004170 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004171 offset=(ssize_t) StringToLong(arg1);
anthonycd358fc2012-04-16 13:59:03 +00004172 new_images=SmushImages(_images,normal_op,offset,_exception);
4173 break;
4174 }
4175 if (LocaleCompare("subimage",option+1) == 0)
4176 {
4177 Image
4178 *base_image,
4179 *compare_image;
4180
4181 const char *
4182 value;
4183
4184 MetricType
4185 metric;
4186
4187 double
4188 similarity;
4189
4190 RectangleInfo
4191 offset;
4192
4193 base_image=GetImageFromList(_images,0);
4194 compare_image=GetImageFromList(_images,1);
4195
4196 /* Comparision Metric */
4197 metric=UndefinedMetric;
4198 value=GetImageOption(_image_info,"metric");
4199 if (value != (const char *) NULL)
4200 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4201 MagickFalse,value);
4202
4203 new_images=SimilarityImage(base_image,compare_image,metric,
4204 &offset,&similarity,_exception);
4205
4206 if ( new_images != (Image *)NULL ) {
4207 char
4208 result[MaxTextExtent];
4209
4210 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
4211 (void) SetImageProperty(new_images,"subimage:similarity",result,
4212 _exception);
4213 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4214 (long) offset.x);
4215 (void) SetImageProperty(new_images,"subimage:x",result,
4216 _exception);
4217 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4218 (long) offset.y);
4219 (void) SetImageProperty(new_images,"subimage:y",result,
4220 _exception);
4221 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
4222 (unsigned long) offset.width,(unsigned long) offset.height,
4223 (long) offset.x,(long) offset.y);
4224 (void) SetImageProperty(new_images,"subimage:offset",result,
4225 _exception);
4226 }
anthony805a2d42011-09-25 08:25:12 +00004227 break;
4228 }
anthony0ea037a2012-04-03 12:14:39 +00004229 if (LocaleCompare("swap",option+1) == 0) {
4230 Image
4231 *p,
4232 *q,
4233 *swap;
anthony805a2d42011-09-25 08:25:12 +00004234
anthony0ea037a2012-04-03 12:14:39 +00004235 ssize_t
4236 index,
4237 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004238
anthony0ea037a2012-04-03 12:14:39 +00004239 index=-1;
4240 swap_index=-2;
4241 if (IfNormalOp) {
4242 GeometryInfo
4243 geometry_info;
4244
4245 MagickStatusType
4246 flags;
4247
4248 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004249 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00004250 if ((flags & RhoValue) != 0)
4251 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004252 index=(ssize_t) geometry_info.rho;
4253 if ((flags & SigmaValue) != 0)
4254 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004255 }
anthony0ea037a2012-04-03 12:14:39 +00004256 p=GetImageFromList(_images,index);
4257 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004258 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4259 if (IfNormalOp)
4260 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4261 else
4262 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4263 }
anthony0ea037a2012-04-03 12:14:39 +00004264 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004265 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004266 swap=CloneImage(p,0,0,MagickTrue,_exception);
4267 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4268 ReplaceImageInList(&q,swap);
4269 _images=GetFirstImageInList(q);
4270 break;
4271 }
anthonyebb73a22012-03-22 14:25:52 +00004272 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004273 }
anthony805a2d42011-09-25 08:25:12 +00004274 default:
anthonyebb73a22012-03-22 14:25:52 +00004275 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004276 }
anthony964d28e2012-05-17 23:39:46 +00004277
4278 /* clean up percent escape interpreted strings */
4279 if (arg1 != arg1n )
4280 arg1=DestroyString((char *)arg1);
4281 if (arg2 != arg2n )
4282 arg2=DestroyString((char *)arg2);
4283
4284 /* if new image list generated, replace existing image list */
anthony31f1bf72012-01-30 12:37:22 +00004285 if (new_images == (Image *) NULL)
4286 return;
anthony964d28e2012-05-17 23:39:46 +00004287 _images=DestroyImageList(_images);
anthony92c93bd2012-03-19 14:02:47 +00004288 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004289 return;
4290
anthony92c93bd2012-03-19 14:02:47 +00004291#undef _image_info
4292#undef _images
4293#undef _exception
4294#undef _draw_info
4295#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004296#undef IfNormalOp
4297#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004298#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004299}
anthony43f425d2012-02-26 12:58:58 +00004300
4301/*
4302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4303% %
4304% %
4305% %
anthony964d28e2012-05-17 23:39:46 +00004306+ 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 +00004307% %
4308% %
4309% %
4310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4311%
anthony464f1c42012-04-22 08:51:01 +00004312% CLINoImageOperator() Applies operations that may not actually need images
anthony964d28e2012-05-17 23:39:46 +00004313% in an image list.
anthony43f425d2012-02-26 12:58:58 +00004314%
anthony4837ac22012-05-18 23:39:48 +00004315% The classic operators of this type is "-read", which actually creates
4316% images even when no images are present. Or image stack operators, which
4317% can be applied (push or pop) to an empty image list.
anthonyafa3dfc2012-03-03 11:31:30 +00004318%
anthony4837ac22012-05-18 23:39:48 +00004319% Note that these operators may involve other special 'option' prefix
4320% characters other than '-' or '+', namely parenthesis and braces.
anthony43f425d2012-02-26 12:58:58 +00004321%
anthony464f1c42012-04-22 08:51:01 +00004322% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004323%
anthony464f1c42012-04-22 08:51:01 +00004324% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4325% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004326%
4327% A description of each parameter follows:
4328%
anthonyc7994672012-11-17 05:33:27 +00004329% o cli_wand: the main CLI Wand to use. (sometimes not required)
anthony43f425d2012-02-26 12:58:58 +00004330%
4331% o option: The special option (with any switch char) to process
4332%
anthony464f1c42012-04-22 08:51:01 +00004333% o arg1 & arg2: Argument for option, if required
4334% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004335%
4336*/
anthony464f1c42012-04-22 08:51:01 +00004337WandExport void CLINoImageOperator(MagickCLI *cli_wand,
anthonyc7994672012-11-17 05:33:27 +00004338 const char *option, const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004339{
anthony4837ac22012-05-18 23:39:48 +00004340#if 0
4341 const char /* For percent escape interpretImageProperties() */
4342 *arg1,
4343 *arg2;
4344#endif
4345
anthony8226e722012-04-05 14:25:46 +00004346#define _image_info (cli_wand->wand.image_info)
4347#define _images (cli_wand->wand.images)
4348#define _exception (cli_wand->wand.exception)
4349#define IfNormalOp (*option=='-')
4350#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004351
4352 assert(cli_wand != (MagickCLI *) NULL);
4353 assert(cli_wand->signature == WandSignature);
4354 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +00004355 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00004356 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4357
anthonyde897b72012-04-27 00:16:17 +00004358#if 0
anthony4837ac22012-05-18 23:39:48 +00004359 Not able to be used as their may not be any images!
4360 Also the only option that may have arguments that can be percent escaped is
4361 "-clone".
anthony52bef752012-03-27 13:54:47 +00004362
anthony4837ac22012-05-18 23:39:48 +00004363#define _process_flags (cli_wand->process_flags)
4364#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
4365 /* Interpret Percent Escapes in Arguments - using first image */
4366 arg1 = arg1n;
4367 arg2 = arg2n;
4368 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4369 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4370 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4371 /* Interpret Percent escapes in argument 1 */
4372 if (arg1n != (char *) NULL) {
4373 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4374 if (arg1 == (char *) NULL) {
4375 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4376 arg1=arg1n; /* use the given argument as is */
4377 }
4378 }
4379 if (arg2n != (char *) NULL) {
4380 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4381 if (arg2 == (char *) NULL) {
4382 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4383 arg2=arg2n; /* use the given argument as is */
4384 }
4385 }
4386 }
4387#undef _process_flags
4388#undef _option_type
anthonyde897b72012-04-27 00:16:17 +00004389#endif
anthony4837ac22012-05-18 23:39:48 +00004390
4391 do { /* break to exit code */
4392 /*
4393 No-op options (ignore these)
4394 */
anthonyc7994672012-11-17 05:33:27 +00004395 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
anthony4837ac22012-05-18 23:39:48 +00004396 break;
4397 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4398 break;
anthonyc7994672012-11-17 05:33:27 +00004399 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4400 break;
4401 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
anthony4837ac22012-05-18 23:39:48 +00004402 break;
4403 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4404 break;
4405 /*
4406 Image Reading
4407 */
4408 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4409 ( LocaleCompare("--",option) == 0 ) ) {
4410 /* Do Glob filename Expansion for 'arg1' then read all images.
4411 *
4412 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4413 * (but attaching to the filenames in the generated argument list) any
4414 * [...] read modifiers that may be present.
4415 *
4416 * For example: It will expand '*.gif[20x20]' into a list such as
4417 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4418 *
4419 * NOTE: In IMv6 this was done globally across all images. This
4420 * meant you could include IM options in '@filename' lists, but you
4421 * could not include comments. Doing it only for image read makes
4422 * it far more secure.
4423 *
4424 * Note: arguments do not have percent escapes expanded for security
4425 * reasons.
4426 */
4427 int argc;
4428 char **argv;
4429 ssize_t i;
4430
4431 argc = 1;
4432 argv = (char **) &arg1;
4433
4434 /* Expand 'glob' expressions in the given filename.
4435 Expansion handles any 'coder:' prefix, or read modifiers attached
4436 to the filename, including them in the resulting expanded list.
4437 */
4438 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4439 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4440 option,GetExceptionMessage(errno));
4441
4442 /* loop over expanded filename list, and read then all in */
4443 for (i=0; i<argc; i++) {
4444 Image *
4445 new_images;
4446 if (IfMagickTrue(_image_info->ping))
4447 new_images=PingImages(_image_info,argv[i],_exception);
4448 else
4449 new_images=ReadImages(_image_info,argv[i],_exception);
4450 AppendImageToList(&_images, new_images);
4451 }
4452 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4453 break;
4454 }
4455 /*
4456 Image Writing
4457 Note: Writing a empty image list is valid in specific cases
4458 */
4459 if (LocaleCompare("write",option+1) == 0) {
4460 /* Note: arguments do not have percent escapes expanded */
4461 char
4462 key[MaxTextExtent];
4463
4464 Image
4465 *write_images;
4466
4467 ImageInfo
4468 *write_info;
4469
4470 /* Need images, unless a "null:" output coder is used */
4471 if ( cli_wand->wand.images == (Image *) NULL ) {
4472 if ( LocaleCompare(arg1,"null:") == 0 )
4473 break;
4474 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4475 }
4476
4477 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4478 (void) DeleteImageRegistry(key);
4479 write_images=_images;
4480 if (IfPlusOp)
4481 write_images=CloneImageList(_images,_exception);
4482 write_info=CloneImageInfo(_image_info);
4483 (void) WriteImages(write_info,write_images,arg1,_exception);
4484 write_info=DestroyImageInfo(write_info);
4485 if (IfPlusOp)
4486 write_images=DestroyImageList(write_images);
4487 break;
4488 }
4489 /*
4490 Parenthesis and Brace operations
4491 */
4492 if (LocaleCompare("(",option) == 0) {
4493 /* stack 'push' images */
4494 Stack
4495 *node;
4496
4497 size_t
4498 size;
4499
4500 size=0;
4501 node=cli_wand->image_list_stack;
4502 for ( ; node != (Stack *)NULL; node=node->next)
4503 size++;
4504 if ( size >= MAX_STACK_DEPTH )
4505 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4506 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4507 if (node == (Stack *) NULL)
4508 CLIWandExceptionBreak(ResourceLimitFatalError,
4509 "MemoryAllocationFailed",option);
4510 node->data = (void *)cli_wand->wand.images;
4511 cli_wand->wand.images = NewImageList();
4512 node->next = cli_wand->image_list_stack;
4513 cli_wand->image_list_stack = node;
4514
4515 /* handle respect-parenthesis */
4516 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4517 "respect-parenthesis"))))
4518 option="{"; /* fall-thru so as to push image settings too */
anthony52bef752012-03-27 13:54:47 +00004519 else
anthony4837ac22012-05-18 23:39:48 +00004520 break;
4521 /* fall thru to next if */
anthony52bef752012-03-27 13:54:47 +00004522 }
anthony4837ac22012-05-18 23:39:48 +00004523 if (LocaleCompare("{",option) == 0) {
4524 /* stack 'push' of image_info settings */
4525 Stack
4526 *node;
anthony8226e722012-04-05 14:25:46 +00004527
anthony4837ac22012-05-18 23:39:48 +00004528 size_t
4529 size;
anthony8226e722012-04-05 14:25:46 +00004530
anthony4837ac22012-05-18 23:39:48 +00004531 size=0;
4532 node=cli_wand->image_info_stack;
4533 for ( ; node != (Stack *)NULL; node=node->next)
4534 size++;
4535 if ( size >= MAX_STACK_DEPTH )
4536 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4537 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4538 if (node == (Stack *) NULL)
4539 CLIWandExceptionBreak(ResourceLimitFatalError,
4540 "MemoryAllocationFailed",option);
anthony8226e722012-04-05 14:25:46 +00004541
anthony4837ac22012-05-18 23:39:48 +00004542 node->data = (void *)cli_wand->wand.image_info;
4543 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4544 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4545 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4546 option);
4547 cli_wand->wand.image_info = (ImageInfo *)node->data;
4548 node = (Stack *)RelinquishMagickMemory(node);
4549 break;
4550 }
4551
4552 node->next = cli_wand->image_info_stack;
4553 cli_wand->image_info_stack = node;
4554
4555 break;
anthony8226e722012-04-05 14:25:46 +00004556 }
anthony4837ac22012-05-18 23:39:48 +00004557 if (LocaleCompare(")",option) == 0) {
4558 /* pop images from stack */
4559 Stack
4560 *node;
anthony8226e722012-04-05 14:25:46 +00004561
anthony4837ac22012-05-18 23:39:48 +00004562 node = (Stack *)cli_wand->image_list_stack;
4563 if ( node == (Stack *)NULL)
4564 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4565 cli_wand->image_list_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004566
anthony4837ac22012-05-18 23:39:48 +00004567 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4568 cli_wand->wand.images= (Image *)node->data;
4569 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004570
anthony4837ac22012-05-18 23:39:48 +00004571 /* handle respect-parenthesis - of the previous 'pushed' settings */
4572 node = cli_wand->image_info_stack;
4573 if ( node != (Stack *)NULL)
4574 {
4575 if (IfMagickTrue(IsStringTrue(GetImageOption(
4576 cli_wand->wand.image_info,"respect-parenthesis"))))
4577 option="}"; /* fall-thru so as to pop image settings too */
4578 else
4579 break;
4580 }
4581 else
4582 break;
4583 /* fall thru to next if */
4584 }
4585 if (LocaleCompare("}",option) == 0) {
4586 /* pop image_info settings from stack */
4587 Stack
4588 *node;
anthony43f425d2012-02-26 12:58:58 +00004589
anthony4837ac22012-05-18 23:39:48 +00004590 node = (Stack *)cli_wand->image_info_stack;
4591 if ( node == (Stack *)NULL)
4592 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4593 cli_wand->image_info_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004594
anthony4837ac22012-05-18 23:39:48 +00004595 (void) DestroyImageInfo(cli_wand->wand.image_info);
anthony43f425d2012-02-26 12:58:58 +00004596 cli_wand->wand.image_info = (ImageInfo *)node->data;
4597 node = (Stack *)RelinquishMagickMemory(node);
anthony4837ac22012-05-18 23:39:48 +00004598
4599 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4600 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4601 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4602
4603 break;
4604 }
anthonyc7994672012-11-17 05:33:27 +00004605 if (LocaleCompare("set",option+1) == 0)
4606 {
4607 /* Note: arguments are not percent escapes expanded yet */
4608 /* Some settings are applied to each image in memory in turn.
4609 While others only need to be applied once globally.
4610 */
4611 char
4612 *value;
4613
4614 if (LocaleNCompare(arg1,"registry:",9) == 0)
4615 {
4616 if (IfPlusOp)
4617 {
4618 (void) DeleteImageRegistry(arg1+9);
4619 break;
4620 }
4621 value=InterpretImageProperties(_image_info,_images,arg2,_exception);
4622 if (value == (char *) NULL)
4623 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4624 option);
4625 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
4626 value=DestroyString(value);
4627 break;
4628 }
4629 if (LocaleNCompare(arg1,"option:",7) == 0)
4630 {
4631 /* delete equivelent artifact from all images (if any) */
4632 MagickResetIterator(&cli_wand->wand);
4633 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4634 (void) DeleteImageArtifact(_images,arg1+7);
4635 MagickResetIterator(&cli_wand->wand);
4636 /* now set/delete the global option as needed */
4637 if (IfPlusOp) {
4638 (void) DeleteImageOption(_image_info,arg1+7);
4639 break;
4640 }
4641 value=InterpretImageProperties(_image_info,_images,arg2,_exception);
4642 if (value == (char *) NULL)
4643 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4644 option);
4645 (void) SetImageOption(_image_info,arg1+7,value);
4646 value=DestroyString(value);
4647 break;
4648 }
4649 if ( cli_wand->wand.images == (Image *) NULL )
4650 CLIWandExceptArgBreak(OptionError,"NoImagesFound",option,arg1);
4651 MagickResetIterator(&cli_wand->wand);
4652 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4653 {
4654 if (IfPlusOp) {
4655 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4656 (void) DeleteImageArtifact(_images,arg1+9);
4657 else if (LocaleNCompare(arg1,"property:",9) == 0)
4658 (void) DeleteImageProperty(_images,arg1+9);
4659 else
4660 (void) DeleteImageProperty(_images,arg1);
4661 break;
4662 }
4663 value=InterpretImageProperties(_image_info,_images,arg2,_exception);
4664 if (value == (char *) NULL)
4665 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4666 option);
4667 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4668 (void) SetImageArtifact(_images,arg1+9,value);
4669 else if (LocaleNCompare(arg1,"property:",9) == 0)
4670 (void) SetImageProperty(_images,arg1+9,value,_exception);
4671 else
4672 (void) SetImageProperty(_images,arg1,value,_exception);
4673 value=DestroyString(value);
4674 break;
4675 }
4676 MagickResetIterator(&cli_wand->wand);
4677 break;
4678 }
anthony4837ac22012-05-18 23:39:48 +00004679 if (LocaleCompare("clone",option+1) == 0) {
4680 Image
4681 *new_images;
4682
4683 if (*option == '+')
4684 arg1="-1";
4685 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4686 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
4687 if ( cli_wand->image_list_stack == (Stack *)NULL)
4688 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4689 new_images = (Image *)cli_wand->image_list_stack->data;
4690 if (new_images == (Image *) NULL)
4691 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4692 new_images=CloneImages(new_images,arg1,_exception);
4693 if (new_images == (Image *) NULL)
4694 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4695 AppendImageToList(&_images,new_images);
4696 break;
4697 }
4698 /*
4699 Informational Operations
4700
anthonyc7994672012-11-17 05:33:27 +00004701 Note that these do not require either a cli-wand or images!
4702 Though currently a cli-wand much be provided regardless.
anthony4837ac22012-05-18 23:39:48 +00004703 */
4704 if (LocaleCompare("version",option+1) == 0) {
4705 (void) FormatLocaleFile(stdout,"Version: %s\n",
4706 GetMagickVersion((size_t *) NULL));
4707 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4708 GetMagickCopyright());
4709 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4710 GetMagickFeatures());
4711 break;
4712 }
4713 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
4791#if 0
anthony4837ac22012-05-18 23:39:48 +00004792 /* clean up percent escape interpreted strings */
4793 if (arg1 != arg1n )
4794 arg1=DestroyString((char *)arg1);
4795 if (arg2 != arg2n )
4796 arg2=DestroyString((char *)arg2);
anthony43f425d2012-02-26 12:58:58 +00004797#endif
4798
anthony8226e722012-04-05 14:25:46 +00004799#undef _image_info
4800#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004801#undef _exception
anthony8226e722012-04-05 14:25:46 +00004802#undef IfNormalOp
4803#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004804}
anthony464f1c42012-04-22 08:51:01 +00004805
4806/*
4807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4808% %
4809% %
4810% %
anthony964d28e2012-05-17 23:39:46 +00004811+ C L I O p t i o n %
anthony464f1c42012-04-22 08:51:01 +00004812% %
4813% %
4814% %
4815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4816%
4817% CLIOption() Processes the given option using the given CLI Magick Wand.
anthony964d28e2012-05-17 23:39:46 +00004818% The option arguments can be variable in number, though at this time no more
4819% that two is actually used by any option (this may change). Excess options
4820% are simply ignored.
anthony464f1c42012-04-22 08:51:01 +00004821%
4822% If the cli_wand->command pointer is non-null, then it is assumed that the
4823% option has already been search for up from the CommandOptions[] table in
anthony964d28e2012-05-17 23:39:46 +00004824% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
4825% routine will do the lookup instead. The pointer is reset afterward.
4826%
4827% This action allows the caller to lookup and pre-handle any 'special'
4828% options, (such as implicit reads) before calling this general option
4829% handler to deal with 'standard' command line options.
anthony464f1c42012-04-22 08:51:01 +00004830%
4831% The format of the CLIOption method is:
4832%
4833% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
4834%
4835% A description of each parameter follows:
4836%
4837% o cli_wand: the main CLI Wand to use.
4838%
4839% o option: The special option (with any switch char) to process
4840%
anthony964d28e2012-05-17 23:39:46 +00004841% o args: any required arguments for an option (variable number)
anthony464f1c42012-04-22 08:51:01 +00004842%
4843% Example Usage...
4844%
4845% CLIoption(cli_wand,"-read","rose:");
4846% CLIoption(cli_wand,"-virtual-pixel","transparent");
4847% CLIoption(cli_wand,"-distort","SRT:","30");
4848% CLIoption(cli_wand,"-write","rotated_rose.png");
4849%
4850*/
4851WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
4852{
4853 const char
4854 *arg1,
4855 *arg2;
4856
4857 CommandOptionFlags
4858 option_type;
4859
4860 assert(cli_wand != (MagickCLI *) NULL);
4861 assert(cli_wand->signature == WandSignature);
4862 assert(cli_wand->wand.signature == WandSignature);
4863 if (IfMagickTrue(cli_wand->wand.debug))
4864 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4865
anthony964d28e2012-05-17 23:39:46 +00004866 do { /* Break Code Block for error handling */
4867
4868 /* get information about option */
4869 if ( cli_wand->command == (const OptionInfo *) NULL )
4870 cli_wand->command = GetCommandOptionInfo(option);
anthony464f1c42012-04-22 08:51:01 +00004871#if 0
anthony964d28e2012-05-17 23:39:46 +00004872 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
4873 option, cli_wand->command->mnemonic );
anthony464f1c42012-04-22 08:51:01 +00004874#endif
anthony964d28e2012-05-17 23:39:46 +00004875 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthony464f1c42012-04-22 08:51:01 +00004876
anthony964d28e2012-05-17 23:39:46 +00004877 if ( option_type == UndefinedOptionFlag )
4878 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
anthony464f1c42012-04-22 08:51:01 +00004879
anthony964d28e2012-05-17 23:39:46 +00004880 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
anthony464f1c42012-04-22 08:51:01 +00004881
anthony964d28e2012-05-17 23:39:46 +00004882 /* depreciated options */
4883 if ( (option_type & DeprecateOptionFlag) != 0 )
4884 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
anthony464f1c42012-04-22 08:51:01 +00004885
anthony964d28e2012-05-17 23:39:46 +00004886 /* options that this module does not handle */
4887 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
4888 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
anthony464f1c42012-04-22 08:51:01 +00004889
anthony964d28e2012-05-17 23:39:46 +00004890 /* Get argument strings from VarArgs
4891 How can you determine arguments is enough was supplied? */
4892 { size_t
4893 count = cli_wand->command->type;
anthony464f1c42012-04-22 08:51:01 +00004894
anthony964d28e2012-05-17 23:39:46 +00004895 va_list
4896 operands;
anthony464f1c42012-04-22 08:51:01 +00004897
anthony964d28e2012-05-17 23:39:46 +00004898 va_start(operands,option);
anthony464f1c42012-04-22 08:51:01 +00004899
anthony964d28e2012-05-17 23:39:46 +00004900 arg1=arg2=NULL;
4901 if ( count >= 1 )
4902 arg1=(const char *) va_arg(operands, const char *);
4903 if ( count >= 2 )
4904 arg2=(const char *) va_arg(operands, const char *);
anthony464f1c42012-04-22 08:51:01 +00004905
anthony964d28e2012-05-17 23:39:46 +00004906 va_end(operands);
anthony464f1c42012-04-22 08:51:01 +00004907
anthony52cb3df2012-04-24 03:29:32 +00004908#if 0
anthony964d28e2012-05-17 23:39:46 +00004909 (void) FormatLocaleFile(stderr,
4910 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
4911 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00004912#endif
anthony964d28e2012-05-17 23:39:46 +00004913 }
4914
4915 /*
4916 Call the appropriate option handler
4917 */
4918
4919 /* FUTURE: this is temporary - get 'settings' to handle distribution of
4920 settings to images attributes,proprieties,artifacts */
4921 if ( cli_wand->wand.images != (Image *)NULL )
4922 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4923 cli_wand->wand.exception);
4924
4925 if ( (option_type & SettingOptionFlags) != 0 ) {
4926 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
4927 // FUTURE: Sync Specific Settings into Image Properities (not global)
4928 }
4929
4930 /* Operators that do not need images - read, write, stack, clone */
4931 if ( (option_type & NoImageOperatorFlag) != 0)
4932 CLINoImageOperator(cli_wand, option, arg1, arg2);
4933
4934 /* FUTURE: The not a setting part below is a temporary hack due to
4935 * some options being both a Setting and a Simple operator.
4936 * Specifically -monitor, -depth, and -colorspace */
4937 if ( cli_wand->wand.images == (Image *)NULL )
4938 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
4939 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
4940 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
4941
4942 /* Operators work on single images, and needs a loop over the images */
4943 if ( (option_type & SimpleOperatorFlag) != 0)
4944 CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
4945
4946 /* Operators that work on the image list as a whole */
4947 if ( (option_type & ListOperatorFlag) != 0 )
4948 CLIListOperatorImages(cli_wand, option, arg1, arg2);
4949
4950 } while (0); /* end Break code block */
anthony464f1c42012-04-22 08:51:01 +00004951
4952 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
anthony464f1c42012-04-22 08:51:01 +00004953}