blob: 939002e1defbb3b75308b4e7de2cf0bb42967684 [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*/
cristyfe831852013-02-12 14:56:07 +0000402WandPrivate 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 {
cristy70e9f682013-03-12 22:31:22 +0000952 if (LocaleCompare("intensity",option+1) == 0)
953 {
954 arg1 = ArgOption("undefined");
955 parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,arg1);
956 if (parse < 0)
957 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",option,arg1);
958 (void) SetImageOption(_image_info,option+1,arg1);
959 break;
960 }
anthonyafa3dfc2012-03-03 11:31:30 +0000961 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000962 {
anthony72feaa62012-01-17 06:46:23 +0000963 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000964 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000965 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000966 */
cristy70e9f682013-03-12 22:31:22 +0000967 arg1 = ArgOption("undefined");
anthonyfe1aa782012-03-24 13:43:04 +0000968 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
969 if (parse < 0)
970 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
971 option,arg1);
972 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000973 break;
974 }
anthonyafa3dfc2012-03-03 11:31:30 +0000975 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000976 {
anthony92c93bd2012-03-19 14:02:47 +0000977 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +0000978 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000979 */
anthonyfe1aa782012-03-24 13:43:04 +0000980 arg1 = ArgOption("undefined");
981 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
982 if (parse < 0)
983 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
984 option,arg1);
985 _image_info->interlace=(InterlaceType) parse;
986 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000987 break;
988 }
anthonyafa3dfc2012-03-03 11:31:30 +0000989 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000990 {
anthony7bcfe7f2012-03-30 14:01:22 +0000991 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000992 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000993 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
994 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +0000995 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000996 break;
997 }
anthonyafa3dfc2012-03-03 11:31:30 +0000998 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000999 {
anthonyfd706f92012-01-19 04:22:02 +00001000 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001001 arg1 = ArgOption("undefined");
1002 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1003 if (parse < 0)
1004 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1005 option,arg1);
1006 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001007 break;
1008 }
anthonyafa3dfc2012-03-03 11:31:30 +00001009 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001010 {
anthony7bcfe7f2012-03-30 14:01:22 +00001011 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001012 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001013 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1014 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001015 break;
1016 }
anthonyebb73a22012-03-22 14:25:52 +00001017 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001018 }
1019 case 'k':
1020 {
anthonyafa3dfc2012-03-03 11:31:30 +00001021 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001022 {
anthony7bcfe7f2012-03-30 14:01:22 +00001023 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001024 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001025 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1026 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001027 break;
1028 }
anthonyebb73a22012-03-22 14:25:52 +00001029 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001030 }
1031 case 'l':
1032 {
anthonyafa3dfc2012-03-03 11:31:30 +00001033 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001034 {
anthony72feaa62012-01-17 06:46:23 +00001035 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001036 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001037 break;
1038 }
anthony756cd0d2012-04-08 12:41:44 +00001039 if (LocaleCompare("limit",option+1) == 0)
1040 {
1041 MagickSizeType
1042 limit;
1043
1044 limit=MagickResourceInfinity;
1045 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1046 if ( parse < 0 )
1047 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1048 option,arg1);
1049 if (LocaleCompare("unlimited",arg2) != 0)
1050 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1051 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1052 break;
1053 }
anthonyafa3dfc2012-03-03 11:31:30 +00001054 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001055 {
anthonyfe1aa782012-03-24 13:43:04 +00001056 if (IfSetOption) {
1057 if ((strchr(arg1,'%') == (char *) NULL))
1058 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001059 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001060 }
anthony805a2d42011-09-25 08:25:12 +00001061 break;
1062 }
anthony975a8d72012-04-12 13:54:36 +00001063 if (LocaleCompare("lowlight-color",option+1) == 0)
1064 {
anthonyb1d483a2012-04-14 12:53:56 +00001065 /* FUTURE: this is only used by CompareImages() which is used
1066 only by the "compare" CLI program at this time. */
anthony975a8d72012-04-12 13:54:36 +00001067 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1068 break;
1069 }
anthonyafa3dfc2012-03-03 11:31:30 +00001070 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001071 {
anthony72feaa62012-01-17 06:46:23 +00001072 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001073 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001074 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001075 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1076 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001077 break;
1078 }
anthonyebb73a22012-03-22 14:25:52 +00001079 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001080 }
1081 case 'm':
1082 {
anthonyafa3dfc2012-03-03 11:31:30 +00001083 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001084 {
anthony72feaa62012-01-17 06:46:23 +00001085 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001086 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001087 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001088 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001089 break;
anthonycd358fc2012-04-16 13:59:03 +00001090 }
anthonyb1d483a2012-04-14 12:53:56 +00001091 if (LocaleCompare("metric",option+1) == 0)
1092 {
1093 /* FUTURE: this is only used by CompareImages() which is used
1094 only by the "compare" CLI program at this time. */
1095 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1096 if ( parse < 0 )
1097 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1098 option,arg1);
1099 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthonycd358fc2012-04-16 13:59:03 +00001100 break;
anthony805a2d42011-09-25 08:25:12 +00001101 }
anthonyafa3dfc2012-03-03 11:31:30 +00001102 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001103 {
anthony92c93bd2012-03-19 14:02:47 +00001104 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001105 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001106 break;
1107 }
anthonyafa3dfc2012-03-03 11:31:30 +00001108 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001109 {
anthony24aa8822012-03-11 00:56:06 +00001110 /* Setting (used by some input coders!) -- why?
1111 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001112 */
anthony92c93bd2012-03-19 14:02:47 +00001113 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001114 break;
1115 }
anthonyebb73a22012-03-22 14:25:52 +00001116 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001117 }
1118 case 'o':
1119 {
anthonyafa3dfc2012-03-03 11:31:30 +00001120 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001121 {
anthony72feaa62012-01-17 06:46:23 +00001122 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001123 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001124 FUTURE: make set meta-data operator instead.
1125 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001126 */
anthony7bc87992012-03-25 02:32:51 +00001127 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1128 ArgOption("undefined"));
1129 if (parse < 0)
1130 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1131 option,arg1);
1132 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001133 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001134 break;
1135 }
anthonyebb73a22012-03-22 14:25:52 +00001136 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001137 }
1138 case 'p':
1139 {
anthonyafa3dfc2012-03-03 11:31:30 +00001140 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001141 {
anthony7bc87992012-03-25 02:32:51 +00001142 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001143 SyncImageSettings() used to set per-image attribute. ?????
1144 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001145 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001146 */
anthony805a2d42011-09-25 08:25:12 +00001147 char
1148 *canonical_page,
1149 page[MaxTextExtent];
1150
1151 const char
1152 *image_option;
1153
1154 MagickStatusType
1155 flags;
1156
1157 RectangleInfo
1158 geometry;
1159
anthonydcf510d2011-10-30 13:51:40 +00001160 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001161 {
anthony92c93bd2012-03-19 14:02:47 +00001162 (void) DeleteImageOption(_image_info,option+1);
1163 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001164 break;
1165 }
1166 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001167 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001168 if (image_option != (const char *) NULL)
1169 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001170 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001171 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1172 canonical_page=DestroyString(canonical_page);
1173 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1174 (unsigned long) geometry.width,(unsigned long) geometry.height);
1175 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1176 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1177 (unsigned long) geometry.width,(unsigned long) geometry.height,
1178 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001179 (void) SetImageOption(_image_info,option+1,page);
1180 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001181 break;
1182 }
anthonyafa3dfc2012-03-03 11:31:30 +00001183 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001184 {
anthony92c93bd2012-03-19 14:02:47 +00001185 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001186 break;
1187 }
anthonyafa3dfc2012-03-03 11:31:30 +00001188 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001189 {
anthonyf42014d2012-03-25 09:53:06 +00001190 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001191 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001192 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1193 _image_info->pointsize =
1194 _draw_info->pointsize =
1195 StringToDouble(arg1,(char **) NULL);
1196 }
1197 else {
1198 _image_info->pointsize=0.0; /* unset pointsize */
1199 _draw_info->pointsize=12.0;
1200 }
anthony805a2d42011-09-25 08:25:12 +00001201 break;
1202 }
anthonyafa3dfc2012-03-03 11:31:30 +00001203 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001204 {
anthonyf42014d2012-03-25 09:53:06 +00001205 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001206 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001207 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1208 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001209 break;
1210 }
anthonydcf510d2011-10-30 13:51:40 +00001211 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001212 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001213 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001214 {
anthony92c93bd2012-03-19 14:02:47 +00001215 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001216 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001217 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001218 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001219 break;
1220 }
anthonydcf510d2011-10-30 13:51:40 +00001221 */
anthonyebb73a22012-03-22 14:25:52 +00001222 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001223 }
1224 case 'q':
1225 {
anthonyafa3dfc2012-03-03 11:31:30 +00001226 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001227 {
anthony7bcfe7f2012-03-30 14:01:22 +00001228 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001229 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001230 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1231 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001232 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001233 break;
1234 }
anthonyafa3dfc2012-03-03 11:31:30 +00001235 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001236 {
anthony92c93bd2012-03-19 14:02:47 +00001237 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001238 arg1=ArgOption("undefined");
1239 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1240 if (parse < 0)
1241 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1242 option,arg1);
1243 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001244 break;
1245 }
anthonyafa3dfc2012-03-03 11:31:30 +00001246 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001247 {
anthonyf42014d2012-03-25 09:53:06 +00001248 /* FUTURE: if two -quiet is performed you can not do +quiet!
1249 This needs to be checked over thoughly.
1250 */
anthony805a2d42011-09-25 08:25:12 +00001251 static WarningHandler
1252 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001253
anthonyafbaed72011-10-26 12:05:04 +00001254 WarningHandler
1255 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001256
anthonyafbaed72011-10-26 12:05:04 +00001257 if ( tmp != (WarningHandler) NULL)
1258 warning_handler = tmp; /* remember the old handler */
1259 if (!IfSetOption) /* set the old handler */
1260 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001261 break;
1262 }
anthonyebb73a22012-03-22 14:25:52 +00001263 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001264 }
1265 case 'r':
1266 {
anthonyafa3dfc2012-03-03 11:31:30 +00001267 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001268 {
anthonydcf510d2011-10-30 13:51:40 +00001269 /* Image chromaticity X,Y NB: Y=X if Y not defined
1270 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001271 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001272 */
anthonyf42014d2012-03-25 09:53:06 +00001273 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001274 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001275 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001276 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001277 break;
1278 }
cristyb0f7a182012-04-06 23:33:11 +00001279 if (LocaleCompare("regard-warnings",option+1) == 0)
anthonye5fcd362012-04-09 04:02:09 +00001280 /* FUTURE: to be replaced by a 'fatal-level' type setting */
cristyb0f7a182012-04-06 23:33:11 +00001281 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001282 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001283 {
anthony92c93bd2012-03-19 14:02:47 +00001284 /* _draw_info only setting */
1285 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001286 break;
1287 }
anthony756cd0d2012-04-08 12:41:44 +00001288 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1289 {
1290 /* link image and setting stacks - option is itself saved on stack! */
1291 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1292 break;
1293 }
anthonyebb73a22012-03-22 14:25:52 +00001294 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001295 }
1296 case 's':
1297 {
anthonyafa3dfc2012-03-03 11:31:30 +00001298 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001299 {
anthonyafbaed72011-10-26 12:05:04 +00001300 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001301 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001302 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001303 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001304 break;
1305 }
anthonyafa3dfc2012-03-03 11:31:30 +00001306 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001307 {
anthonyf42014d2012-03-25 09:53:06 +00001308 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001309 What ??? Why ????
1310 */
anthony7bcfe7f2012-03-30 14:01:22 +00001311 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001312 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001313 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1314 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001315 break;
1316 }
anthonyafa3dfc2012-03-03 11:31:30 +00001317 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001318 {
anthony7bcfe7f2012-03-30 14:01:22 +00001319 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001320 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyd7761bb2012-04-14 01:42:05 +00001321 SetRandomSecretKey(
cristya30f8e62013-02-19 15:03:45 +00001322 IfSetOption ? (unsigned long) StringToUnsignedLong(arg1)
1323 : (unsigned long) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001324 break;
1325 }
anthonyafa3dfc2012-03-03 11:31:30 +00001326 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001327 {
anthony92c93bd2012-03-19 14:02:47 +00001328 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001329 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001330 */
anthony92c93bd2012-03-19 14:02:47 +00001331 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001332 break;
1333 }
anthonyafa3dfc2012-03-03 11:31:30 +00001334 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001335 {
anthonyf42014d2012-03-25 09:53:06 +00001336 arg1=ArgOption("undefined");
1337 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1338 if (parse < 0)
1339 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1340 option,arg1);
1341 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001342 break;
1343 }
anthonyafa3dfc2012-03-03 11:31:30 +00001344 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001345 {
anthonyafbaed72011-10-26 12:05:04 +00001346 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001347 UPDATE: ensure stroke color is not destroyed is a pattern
1348 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001349 */
anthony72feaa62012-01-17 06:46:23 +00001350 MagickBooleanType
1351 status;
anthonyafbaed72011-10-26 12:05:04 +00001352
1353 ExceptionInfo
1354 *sans;
1355
anthonyfd706f92012-01-19 04:22:02 +00001356 PixelInfo
1357 color;
1358
anthony2a0ec8c2012-03-24 04:35:56 +00001359 arg1 = ArgOption("none"); /* +fill turns it off! */
1360 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001361 if (_draw_info->stroke_pattern != (Image *) NULL)
1362 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001363
1364 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001365 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001366 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001367 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001368
anthony7bcfe7f2012-03-30 14:01:22 +00001369 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001370 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001371 else
anthony92c93bd2012-03-19 14:02:47 +00001372 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001373 break;
1374 }
anthonyafa3dfc2012-03-03 11:31:30 +00001375 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001376 {
anthony7bcfe7f2012-03-30 14:01:22 +00001377 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001378 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001379 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1380 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001381 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001382 break;
1383 }
anthonyafa3dfc2012-03-03 11:31:30 +00001384 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001385 {
anthonyf42014d2012-03-25 09:53:06 +00001386 arg1=ArgOption("undefined");
1387 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1388 if (parse < 0)
1389 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1390 option,arg1);
1391 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001392 break;
1393 }
anthonycd358fc2012-04-16 13:59:03 +00001394#if 0
anthonyb1d483a2012-04-14 12:53:56 +00001395 if (LocaleCompare("subimage-search",option+1) == 0)
1396 {
1397 /* FUTURE: this is only used by CompareImages() which is used
1398 only by the "compare" CLI program at this time. */
1399 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1400 break;
1401 }
anthonycd358fc2012-04-16 13:59:03 +00001402#endif
anthonyafa3dfc2012-03-03 11:31:30 +00001403 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001404 {
anthonyf42014d2012-03-25 09:53:06 +00001405 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001406 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001407 break;
1408 }
anthonyebb73a22012-03-22 14:25:52 +00001409 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001410 }
1411 case 't':
1412 {
anthonyafa3dfc2012-03-03 11:31:30 +00001413 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001414 {
anthony72feaa62012-01-17 06:46:23 +00001415 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001416 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001417 break;
1418 }
anthonyafa3dfc2012-03-03 11:31:30 +00001419 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001420 {
anthony4837ac22012-05-18 23:39:48 +00001421 /* Note: arguments do not have percent escapes expanded */
anthony52bef752012-03-27 13:54:47 +00001422 /* FUTURE: move _image_info string to option splay-tree
1423 Other than "montage" what uses "texture" ????
1424 */
anthony92c93bd2012-03-19 14:02:47 +00001425 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001426 break;
1427 }
anthonyafa3dfc2012-03-03 11:31:30 +00001428 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001429 {
anthony4837ac22012-05-18 23:39:48 +00001430 /* Note: arguments do not have percent escapes expanded */
anthony92c93bd2012-03-19 14:02:47 +00001431 _draw_info->fill_pattern=IfSetOption
1432 ?GetImageCache(_image_info,arg1,_exception)
1433 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001434 break;
1435 }
anthonyafa3dfc2012-03-03 11:31:30 +00001436 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001437 {
anthony72feaa62012-01-17 06:46:23 +00001438 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001439 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001440 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001441 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1442 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001443 break;
1444 }
anthonyafa3dfc2012-03-03 11:31:30 +00001445 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001446 {
anthony92c93bd2012-03-19 14:02:47 +00001447 /* FUTURE: both _image_info attribute & ImageOption in use!
1448 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001449 SyncImageSettings() used to set per-image attribute.
1450
anthonyafbaed72011-10-26 12:05:04 +00001451 Note that +transparent-color, means fall-back to image
1452 attribute so ImageOption is deleted, not set to a default.
1453 */
anthony7bcfe7f2012-03-30 14:01:22 +00001454 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001455 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001456 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001457 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001458 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001459 break;
1460 }
anthonyafa3dfc2012-03-03 11:31:30 +00001461 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001462 {
anthony92c93bd2012-03-19 14:02:47 +00001463 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1464 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001465 break;
1466 }
anthonyafa3dfc2012-03-03 11:31:30 +00001467 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001468 {
anthony72feaa62012-01-17 06:46:23 +00001469 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001470 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1471 ArgOption("undefined"));
1472 if (parse < 0)
1473 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1474 option,arg1);
1475 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001476 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001477 break;
1478 }
anthonyebb73a22012-03-22 14:25:52 +00001479 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001480 }
1481 case 'u':
1482 {
anthonyafa3dfc2012-03-03 11:31:30 +00001483 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001484 {
anthony92c93bd2012-03-19 14:02:47 +00001485 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001486 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001487 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001488 break;
1489 }
anthonyafa3dfc2012-03-03 11:31:30 +00001490 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001491 {
anthony72feaa62012-01-17 06:46:23 +00001492 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001493 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001494 FUTURE: this probably should be part of the density setting
1495 */
anthony52bef752012-03-27 13:54:47 +00001496 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1497 ArgOption("undefined"));
1498 if (parse < 0)
1499 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1500 option,arg1);
1501 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001502 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001503 break;
1504 }
anthonyebb73a22012-03-22 14:25:52 +00001505 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001506 }
1507 case 'v':
1508 {
anthonyafa3dfc2012-03-03 11:31:30 +00001509 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001510 {
anthony24aa8822012-03-11 00:56:06 +00001511 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001512 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001513 */
anthony92c93bd2012-03-19 14:02:47 +00001514 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1515 _image_info->verbose= ArgBoolean;
1516 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001517 break;
1518 }
anthonyafa3dfc2012-03-03 11:31:30 +00001519 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001520 {
anthony92c93bd2012-03-19 14:02:47 +00001521 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001522 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001523 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001524 */
anthony92c93bd2012-03-19 14:02:47 +00001525 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001526 break;
1527 }
anthonyafa3dfc2012-03-03 11:31:30 +00001528 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001529 {
anthonyfd706f92012-01-19 04:22:02 +00001530 /* SyncImageSettings() used to set per-image attribute.
1531 This is VERY deep in the image caching structure.
1532 */
anthony52bef752012-03-27 13:54:47 +00001533 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1534 ArgOption("undefined"));
1535 if (parse < 0)
1536 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1537 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001538 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001539 break;
1540 }
anthonyebb73a22012-03-22 14:25:52 +00001541 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001542 }
1543 case 'w':
1544 {
anthonyafa3dfc2012-03-03 11:31:30 +00001545 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001546 {
anthony72feaa62012-01-17 06:46:23 +00001547 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001548 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001549 */
anthony52bef752012-03-27 13:54:47 +00001550 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001551 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001552 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001553 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001554 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001555 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001556 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001557 if (_draw_info->weight <= 800)
1558 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001559 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001560 if (_draw_info->weight >= 100)
1561 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001562 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001563 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001564 break;
1565 }
anthonyafa3dfc2012-03-03 11:31:30 +00001566 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001567 {
anthony72feaa62012-01-17 06:46:23 +00001568 /* Used as a image chromaticity setting
1569 SyncImageSettings() used to set per-image attribute.
1570 */
anthony52bef752012-03-27 13:54:47 +00001571 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001572 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001573 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1574 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001575 break;
1576 }
anthonyebb73a22012-03-22 14:25:52 +00001577 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001578 }
1579 default:
anthonyebb73a22012-03-22 14:25:52 +00001580 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001581 }
anthony24aa8822012-03-11 00:56:06 +00001582
anthony4837ac22012-05-18 23:39:48 +00001583#if 0
1584 /* clean up percent escape interpreted strings */
1585 if (arg1 != arg1n )
1586 arg1=DestroyString((char *)arg1);
1587 if (arg2 != arg2n )
1588 arg2=DestroyString((char *)arg2);
1589#endif
1590
anthony92c93bd2012-03-19 14:02:47 +00001591#undef _image_info
1592#undef _exception
1593#undef _draw_info
1594#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001595#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001596#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001597#undef ArgBooleanNot
1598#undef ArgBooleanString
1599#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001600
anthony31f1bf72012-01-30 12:37:22 +00001601 return;
anthony805a2d42011-09-25 08:25:12 +00001602}
1603
1604/*
1605%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1606% %
1607% %
1608% %
anthony43f425d2012-02-26 12:58:58 +00001609+ 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 +00001610% %
1611% %
1612% %
1613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1614%
anthonyc7994672012-11-17 05:33:27 +00001615% CLISimpleOperatorImages() applys one simple image operation given to all
1616% the images in the CLI wand, using any per-image or global settings that was
1617% previously saved in the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001618%
anthonyc7994672012-11-17 05:33:27 +00001619% It is assumed that any such settings are up-to-date.
anthony805a2d42011-09-25 08:25:12 +00001620%
anthony7a4d6102012-07-01 09:48:25 +00001621% The format of the WandSimpleOperatorImages method is:
anthony805a2d42011-09-25 08:25:12 +00001622%
anthony43f425d2012-02-26 12:58:58 +00001623% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001624% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001625%
1626% A description of each parameter follows:
1627%
anthony43f425d2012-02-26 12:58:58 +00001628% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001629%
anthonyfd706f92012-01-19 04:22:02 +00001630% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001631%
anthonyfd706f92012-01-19 04:22:02 +00001632% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001633%
anthony805a2d42011-09-25 08:25:12 +00001634*/
anthony31f1bf72012-01-30 12:37:22 +00001635
1636/*
anthonyc7994672012-11-17 05:33:27 +00001637 CLISimpleOperatorImage() is an Internal subrountine to apply one simple
1638 image operation to the current image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001639
1640 The image in the list may be modified in three different ways...
1641 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1642 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1643 * one image replace by a list of images (-separate and -crop only!)
1644
anthonyafa3dfc2012-03-03 11:31:30 +00001645 In each case the result replaces the single original image in the list, as
1646 well as the pointer to the modified image (last image added if replaced by a
1647 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001648
1649 As the image pointed to may be replaced, the first image in the list may
1650 also change. GetFirstImageInList() should be used by caller if they wish
1651 return the Image pointer to the first image in list.
1652*/
cristyfe831852013-02-12 14:56:07 +00001653static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
anthony964d28e2012-05-17 23:39:46 +00001654 const char *option, const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00001655{
1656 Image *
1657 new_image;
1658
anthony805a2d42011-09-25 08:25:12 +00001659 GeometryInfo
1660 geometry_info;
1661
1662 RectangleInfo
1663 geometry;
1664
1665 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001666 flags;
1667
anthony92c93bd2012-03-19 14:02:47 +00001668 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001669 parse;
anthony92c93bd2012-03-19 14:02:47 +00001670
anthony964d28e2012-05-17 23:39:46 +00001671 const char /* For percent escape interpretImageProperties() */
1672 *arg1,
1673 *arg2;
1674
anthony2e4501b2012-03-30 04:41:54 +00001675#define _image_info (cli_wand->wand.image_info)
1676#define _image (cli_wand->wand.images)
1677#define _exception (cli_wand->wand.exception)
1678#define _draw_info (cli_wand->draw_info)
1679#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00001680#define _process_flags (cli_wand->process_flags)
1681#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00001682#define IfNormalOp (*option=='-')
1683#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00001684#define normal_op IsMagickTrue(IfNormalOp)
1685#define plus_alt_op IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001686
anthony43f425d2012-02-26 12:58:58 +00001687 assert(cli_wand != (MagickCLI *) NULL);
1688 assert(cli_wand->signature == WandSignature);
1689 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001690 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001691 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001692 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001693
anthony964d28e2012-05-17 23:39:46 +00001694 /* Interpret Percent Escapes in Arguments - using first image */
1695 arg1 = arg1n,
1696 arg2 = arg2n;
1697 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1698 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1699 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1700 /* Interpret Percent escapes in argument 1 */
1701 if (arg1n != (char *) NULL) {
1702 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1703 if (arg1 == (char *) NULL) {
1704 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1705 arg1=arg1n; /* use the given argument as is */
1706 }
1707 }
1708 if (arg2n != (char *) NULL) {
1709 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1710 if (arg2 == (char *) NULL) {
1711 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1712 arg2=arg2n; /* use the given argument as is */
1713 }
1714 }
1715 }
anthony4837ac22012-05-18 23:39:48 +00001716#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00001717#undef _option_type
1718
1719#if 0
1720 (void) FormatLocaleFile(stderr,
1721 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1722#endif
anthony805a2d42011-09-25 08:25:12 +00001723
anthony5330ae02012-03-20 14:17:01 +00001724 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony964d28e2012-05-17 23:39:46 +00001725 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001726
anthonyafa3dfc2012-03-03 11:31:30 +00001727 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001728 {
1729 case 'a':
1730 {
anthonyafa3dfc2012-03-03 11:31:30 +00001731 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001732 {
anthonyfd706f92012-01-19 04:22:02 +00001733 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001734 if ((flags & (RhoValue|SigmaValue)) == 0)
1735 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001736 if ((flags & SigmaValue) == 0)
1737 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001738 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001739 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001740 break;
1741 }
anthonyafa3dfc2012-03-03 11:31:30 +00001742 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001743 {
anthonyfe1aa782012-03-24 13:43:04 +00001744 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001745 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001746 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1747 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1748 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001749 _exception);
anthony805a2d42011-09-25 08:25:12 +00001750 break;
1751 }
anthonyafa3dfc2012-03-03 11:31:30 +00001752 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001753 {
anthonyfd706f92012-01-19 04:22:02 +00001754 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001755 if ((flags & (RhoValue|SigmaValue)) == 0)
1756 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001757 if ((flags & SigmaValue) == 0)
1758 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001759 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001760 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001761 break;
1762 }
anthonyafa3dfc2012-03-03 11:31:30 +00001763 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001764 {
cristy288a3532012-08-28 00:19:44 +00001765 parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001766 if (parse < 0)
cristyb15b06c2012-08-28 11:36:48 +00001767 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
anthony92c93bd2012-03-19 14:02:47 +00001768 option,arg1);
cristyb15b06c2012-08-28 11:36:48 +00001769 (void) SetImageAlphaChannel(_image,(AlphaChannelOption)parse,
anthony2a0ec8c2012-03-24 04:35:56 +00001770 _exception);
anthony805a2d42011-09-25 08:25:12 +00001771 break;
1772 }
anthonyafa3dfc2012-03-03 11:31:30 +00001773 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001774 {
1775 char
anthony805a2d42011-09-25 08:25:12 +00001776 geometry[MaxTextExtent];
1777
anthony805a2d42011-09-25 08:25:12 +00001778 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001779 flags=ParseGeometry(arg1,&geometry_info);
cristy8592b052013-02-07 01:24:54 +00001780 if (flags == 0)
anthony22de2722012-04-19 14:43:00 +00001781 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001782 if ((flags & SigmaValue) == 0)
1783 geometry_info.sigma=geometry_info.rho;
anthony964d28e2012-05-17 23:39:46 +00001784 (void) CloneString(&_draw_info->text,arg2);
anthony805a2d42011-09-25 08:25:12 +00001785 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1786 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001787 (void) CloneString(&_draw_info->geometry,geometry);
1788 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001789 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001790 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001791 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001792 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001793 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001794 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001795 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001796 (void) AnnotateImage(_image,_draw_info,_exception);
1797 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001798 break;
1799 }
anthonyafa3dfc2012-03-03 11:31:30 +00001800 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001801 {
anthony92c93bd2012-03-19 14:02:47 +00001802 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001803 break;
1804 }
anthonyafa3dfc2012-03-03 11:31:30 +00001805 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001806 {
anthony92c93bd2012-03-19 14:02:47 +00001807 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001808 break;
1809 }
anthonyafa3dfc2012-03-03 11:31:30 +00001810 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001811 {
cristyfa5f6c72013-01-01 14:37:35 +00001812 new_image=AutoOrientImage(_image,_image->orientation,_exception);
anthony805a2d42011-09-25 08:25:12 +00001813 break;
1814 }
anthonyebb73a22012-03-22 14:25:52 +00001815 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001816 }
1817 case 'b':
1818 {
anthonyafa3dfc2012-03-03 11:31:30 +00001819 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001820 {
anthony7bcfe7f2012-03-30 14:01:22 +00001821 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001822 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001823 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001824 break;
1825 }
anthonyafa3dfc2012-03-03 11:31:30 +00001826 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001827 {
anthony805a2d42011-09-25 08:25:12 +00001828 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001829 if (IfNormalOp) {
anthonyfd706f92012-01-19 04:22:02 +00001830 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001831 if ((flags & RhoValue) == 0)
1832 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony5330ae02012-03-20 14:17:01 +00001833 }
anthony92c93bd2012-03-19 14:02:47 +00001834 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001835 break;
1836 }
anthonyafa3dfc2012-03-03 11:31:30 +00001837 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001838 {
anthonyfd706f92012-01-19 04:22:02 +00001839 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001840 if ((flags & (RhoValue|SigmaValue)) == 0)
1841 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001842 if ((flags & SigmaValue) == 0)
1843 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001844 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1845 _exception);
anthony805a2d42011-09-25 08:25:12 +00001846 break;
1847 }
anthonyafa3dfc2012-03-03 11:31:30 +00001848 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001849 {
anthony31f1bf72012-01-30 12:37:22 +00001850 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001851 compose;
1852
1853 const char*
anthony5f867ae2011-10-09 10:28:34 +00001854 value;
1855
anthony22de2722012-04-19 14:43:00 +00001856 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
cristy64ad8f92012-08-03 00:58:24 +00001857 if ((flags & (WidthValue | HeightValue)) == 0)
anthony5330ae02012-03-20 14:17:01 +00001858 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristy64ad8f92012-08-03 00:58:24 +00001859 compose=OverCompositeOp;
anthony92c93bd2012-03-19 14:02:47 +00001860 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001861 if (value != (const char *) NULL)
cristy64ad8f92012-08-03 00:58:24 +00001862 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
1863 MagickFalse,value);
anthony92c93bd2012-03-19 14:02:47 +00001864 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001865 break;
1866 }
anthonyafa3dfc2012-03-03 11:31:30 +00001867 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001868 {
1869 double
1870 brightness,
1871 contrast;
1872
1873 GeometryInfo
1874 geometry_info;
1875
1876 MagickStatusType
1877 flags;
1878
anthonyfd706f92012-01-19 04:22:02 +00001879 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001880 if ((flags & RhoValue) == 0)
1881 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001882 brightness=geometry_info.rho;
1883 contrast=0.0;
1884 if ((flags & SigmaValue) != 0)
1885 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001886 (void) BrightnessContrastImage(_image,brightness,contrast,
1887 _exception);
anthony805a2d42011-09-25 08:25:12 +00001888 break;
1889 }
anthonyebb73a22012-03-22 14:25:52 +00001890 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001891 }
1892 case 'c':
1893 {
anthonyafa3dfc2012-03-03 11:31:30 +00001894 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001895 {
anthony4837ac22012-05-18 23:39:48 +00001896 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001897 char
1898 *color_correction_collection;
1899
1900 /*
1901 Color correct with a color decision list.
1902 */
anthony92c93bd2012-03-19 14:02:47 +00001903 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001904 if (color_correction_collection == (char *) NULL)
1905 break;
anthony92c93bd2012-03-19 14:02:47 +00001906 (void) ColorDecisionListImage(_image,color_correction_collection,
1907 _exception);
anthony805a2d42011-09-25 08:25:12 +00001908 break;
1909 }
anthonyafa3dfc2012-03-03 11:31:30 +00001910 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001911 {
anthonyfd706f92012-01-19 04:22:02 +00001912 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001913 if ((flags & (RhoValue|SigmaValue)) == 0)
1914 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001915 if ((flags & SigmaValue) == 0)
1916 geometry_info.sigma=1.0;
1917 if ((flags & XiValue) == 0)
1918 geometry_info.xi=1.0;
cristyee3f7522012-12-21 19:27:44 +00001919 new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
1920 _exception);
anthony805a2d42011-09-25 08:25:12 +00001921 break;
1922 }
anthonyafa3dfc2012-03-03 11:31:30 +00001923 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001924 {
anthony7bcfe7f2012-03-30 14:01:22 +00001925 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001926 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001927 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1928 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001929 break;
1930 }
anthonyafa3dfc2012-03-03 11:31:30 +00001931 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001932 {
anthony92c93bd2012-03-19 14:02:47 +00001933 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001934 break;
1935 }
anthonyafa3dfc2012-03-03 11:31:30 +00001936 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001937 {
anthonyafa3dfc2012-03-03 11:31:30 +00001938 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001939 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001940 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001941 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001942 break;
1943 }
anthonyafa3dfc2012-03-03 11:31:30 +00001944 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001945 {
anthony4837ac22012-05-18 23:39:48 +00001946 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001947 CacheView
1948 *mask_view;
1949
1950 Image
1951 *mask_image;
1952
1953 register Quantum
1954 *restrict q;
1955
1956 register ssize_t
1957 x;
1958
1959 ssize_t
1960 y;
1961
anthonyafa3dfc2012-03-03 11:31:30 +00001962 if (IfPlusOp) {
anthony4837ac22012-05-18 23:39:48 +00001963 /* use "+clip-mask" Remove the write mask for -clip-path */
anthony92c93bd2012-03-19 14:02:47 +00001964 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00001965 break;
1966 }
anthony92c93bd2012-03-19 14:02:47 +00001967 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001968 if (mask_image == (Image *) NULL)
1969 break;
anthony7bcfe7f2012-03-30 14:01:22 +00001970 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00001971 break;
anthony5330ae02012-03-20 14:17:01 +00001972 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00001973 /* FUTURE: use Alpha operations instead and create a Grey Image */
cristy46ff2672012-12-14 15:32:26 +00001974 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001975 for (y=0; y < (ssize_t) mask_image->rows; y++)
1976 {
1977 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00001978 _exception);
anthony805a2d42011-09-25 08:25:12 +00001979 if (q == (Quantum *) NULL)
1980 break;
1981 for (x=0; x < (ssize_t) mask_image->columns; x++)
1982 {
cristydc2d3272013-02-12 14:00:44 +00001983 if (mask_image->alpha_trait != BlendPixelTrait)
anthony805a2d42011-09-25 08:25:12 +00001984 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1985 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1986 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1987 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1988 q+=GetPixelChannels(mask_image);
1989 }
anthony7bcfe7f2012-03-30 14:01:22 +00001990 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00001991 break;
1992 }
anthonyfd706f92012-01-19 04:22:02 +00001993 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001994 mask_view=DestroyCacheView(mask_view);
cristy8a46d822012-08-28 23:32:39 +00001995 mask_image->alpha_trait=BlendPixelTrait;
anthony92c93bd2012-03-19 14:02:47 +00001996 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001997 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00001998 break;
1999 }
anthonyafa3dfc2012-03-03 11:31:30 +00002000 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002001 {
anthony92c93bd2012-03-19 14:02:47 +00002002 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony4837ac22012-05-18 23:39:48 +00002003 /* Note: Use "+clip-mask" remove the write mask added */
anthony805a2d42011-09-25 08:25:12 +00002004 break;
2005 }
anthonyafa3dfc2012-03-03 11:31:30 +00002006 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002007 {
anthony7bcfe7f2012-03-30 14:01:22 +00002008 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002009 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002010 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002011 break;
2012 }
anthonyafa3dfc2012-03-03 11:31:30 +00002013 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002014 {
2015 KernelInfo
2016 *kernel;
2017
anthonyfd706f92012-01-19 04:22:02 +00002018 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002019 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002020 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002021 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002022 kernel=DestroyKernelInfo(kernel);
2023 break;
2024 }
anthonyafa3dfc2012-03-03 11:31:30 +00002025 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002026 {
anthony5330ae02012-03-20 14:17:01 +00002027 /* Reduce the number of colors in the image.
2028 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002029 */
anthony92c93bd2012-03-19 14:02:47 +00002030 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2031 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002032 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002033 if ((_image->storage_class == DirectClass) ||
2034 _image->colors > _quantize_info->number_colors)
2035 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002036 else
anthony92c93bd2012-03-19 14:02:47 +00002037 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002038 break;
2039 }
anthonyafa3dfc2012-03-03 11:31:30 +00002040 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002041 {
anthony5330ae02012-03-20 14:17:01 +00002042 /* WARNING: this is both a image_info setting (already done)
2043 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002044
2045 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002046 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002047
anthonyd2cdc862011-10-07 14:07:17 +00002048 Note that +colorspace sets "undefined" or no effect on
2049 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002050 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002051 */
anthony92c93bd2012-03-19 14:02:47 +00002052 (void) TransformImageColorspace(_image,
2053 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2054 _exception);
anthony805a2d42011-09-25 08:25:12 +00002055 break;
2056 }
anthonyafa3dfc2012-03-03 11:31:30 +00002057 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002058 {
anthony464f1c42012-04-22 08:51:01 +00002059 CLIWandWarnReplaced(normal_op?"-level":"+level");
anthony92c93bd2012-03-19 14:02:47 +00002060 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002061 break;
2062 }
anthonyafa3dfc2012-03-03 11:31:30 +00002063 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002064 {
2065 double
2066 black_point,
2067 white_point;
2068
2069 MagickStatusType
2070 flags;
2071
anthonyfd706f92012-01-19 04:22:02 +00002072 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002073 if ((flags & RhoValue) == 0)
2074 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002075 black_point=geometry_info.rho;
2076 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2077 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002078 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002079 black_point*=(double) _image->columns*_image->rows/100.0;
2080 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002081 }
cristya19f1d72012-08-07 18:24:38 +00002082 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002083 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002084 (void) ContrastStretchImage(_image,black_point,white_point,
2085 _exception);
anthony805a2d42011-09-25 08:25:12 +00002086 break;
2087 }
anthonyafa3dfc2012-03-03 11:31:30 +00002088 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002089 {
2090 KernelInfo
2091 *kernel_info;
2092
anthonyfd706f92012-01-19 04:22:02 +00002093 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002094 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002095 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristya12d8ba2012-04-29 16:33:41 +00002096 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2097 _exception);
anthony805a2d42011-09-25 08:25:12 +00002098 kernel_info=DestroyKernelInfo(kernel_info);
2099 break;
2100 }
anthonyafa3dfc2012-03-03 11:31:30 +00002101 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002102 {
anthony31f1bf72012-01-30 12:37:22 +00002103 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002104 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002105 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002106 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002107 break;
2108 }
anthonyafa3dfc2012-03-03 11:31:30 +00002109 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002110 {
anthony7bcfe7f2012-03-30 14:01:22 +00002111 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002112 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002113 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2114 _exception);
anthony805a2d42011-09-25 08:25:12 +00002115 break;
2116 }
anthonyebb73a22012-03-22 14:25:52 +00002117 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002118 }
2119 case 'd':
2120 {
anthonyafa3dfc2012-03-03 11:31:30 +00002121 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002122 {
anthony4837ac22012-05-18 23:39:48 +00002123 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002124 StringInfo
2125 *passkey;
2126
anthony92c93bd2012-03-19 14:02:47 +00002127 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002128 if (passkey == (StringInfo *) NULL)
2129 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2130
2131 (void) PasskeyDecipherImage(_image,passkey,_exception);
2132 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002133 break;
2134 }
anthonyafa3dfc2012-03-03 11:31:30 +00002135 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002136 {
anthony92c93bd2012-03-19 14:02:47 +00002137 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002138 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002139
anthonydcf510d2011-10-30 13:51:40 +00002140 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2141 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002142
anthonyfd706f92012-01-19 04:22:02 +00002143 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002144 */
anthony92c93bd2012-03-19 14:02:47 +00002145 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002146 break;
2147 }
anthonyafa3dfc2012-03-03 11:31:30 +00002148 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002149 {
2150 double
2151 threshold;
2152
anthonyebb73a22012-03-22 14:25:52 +00002153 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002154 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002155 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002156 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002157 }
anthonyafa3dfc2012-03-03 11:31:30 +00002158 else
2159 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002160 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002161 break;
2162 }
anthonyafa3dfc2012-03-03 11:31:30 +00002163 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002164 {
anthony92c93bd2012-03-19 14:02:47 +00002165 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002166 break;
2167 }
anthonyafa3dfc2012-03-03 11:31:30 +00002168 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002169 {
anthony805a2d42011-09-25 08:25:12 +00002170 double
anthonyb1d483a2012-04-14 12:53:56 +00002171 *args;
anthony805a2d42011-09-25 08:25:12 +00002172
anthonyb1d483a2012-04-14 12:53:56 +00002173 ssize_t
2174 count;
anthony805a2d42011-09-25 08:25:12 +00002175
anthony2a0ec8c2012-03-24 04:35:56 +00002176 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2177 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002178 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2179 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002180 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002181 {
anthony80c37752012-01-16 01:03:11 +00002182 double
2183 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002184 /* Special Case - Argument is actually a resize geometry!
2185 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002186 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002187 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002188 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002189 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2190 option,arg2);
2191 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002192 resize_args[0]=(double) geometry.width;
2193 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002194 new_image=DistortImage(_image,(DistortImageMethod) parse,
2195 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002196 break;
2197 }
anthonyb1d483a2012-04-14 12:53:56 +00002198 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002199 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002200 if (args == (double *)NULL )
2201 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2202
2203 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
2204 plus_alt_op,_exception);
2205 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002206 break;
2207 }
anthonyafa3dfc2012-03-03 11:31:30 +00002208 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002209 {
anthony92c93bd2012-03-19 14:02:47 +00002210 (void) CloneString(&_draw_info->primitive,arg1);
2211 (void) DrawImage(_image,_draw_info,_exception);
2212 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002213 break;
2214 }
anthonyebb73a22012-03-22 14:25:52 +00002215 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002216 }
2217 case 'e':
2218 {
anthonyafa3dfc2012-03-03 11:31:30 +00002219 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002220 {
anthonyfd706f92012-01-19 04:22:02 +00002221 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002222 if ((flags & (RhoValue|SigmaValue)) == 0)
2223 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002224 if ((flags & SigmaValue) == 0)
2225 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002226 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2227 _exception);
anthony805a2d42011-09-25 08:25:12 +00002228 break;
2229 }
anthonyafa3dfc2012-03-03 11:31:30 +00002230 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002231 {
anthonyfd706f92012-01-19 04:22:02 +00002232 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002233 if ((flags & (RhoValue|SigmaValue)) == 0)
2234 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002235 if ((flags & SigmaValue) == 0)
2236 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002237 new_image=EmbossImage(_image,geometry_info.rho,
2238 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002239 break;
2240 }
anthonyafa3dfc2012-03-03 11:31:30 +00002241 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002242 {
anthony4837ac22012-05-18 23:39:48 +00002243 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002244 StringInfo
2245 *passkey;
2246
anthony92c93bd2012-03-19 14:02:47 +00002247 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002248 if (passkey != (StringInfo *) NULL)
2249 {
anthony92c93bd2012-03-19 14:02:47 +00002250 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002251 passkey=DestroyStringInfo(passkey);
2252 }
2253 break;
2254 }
anthonyafa3dfc2012-03-03 11:31:30 +00002255 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002256 {
anthony92c93bd2012-03-19 14:02:47 +00002257 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002258 break;
2259 }
anthonyafa3dfc2012-03-03 11:31:30 +00002260 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002261 {
anthony92c93bd2012-03-19 14:02:47 +00002262 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002263 break;
2264 }
anthonyafa3dfc2012-03-03 11:31:30 +00002265 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002266 {
2267 double
2268 constant;
2269
anthony2a0ec8c2012-03-24 04:35:56 +00002270 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2271 if ( parse < 0 )
2272 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2273 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002274 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002275 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002276 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002277 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2278 _exception);
anthony805a2d42011-09-25 08:25:12 +00002279 break;
2280 }
anthonyafa3dfc2012-03-03 11:31:30 +00002281 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002282 {
anthony7bcfe7f2012-03-30 14:01:22 +00002283 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002284 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002285 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002286 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002287 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002288 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002289 geometry.height=_image->rows;
2290 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002291 break;
2292 }
anthonyebb73a22012-03-22 14:25:52 +00002293 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002294 }
2295 case 'f':
2296 {
anthonyafa3dfc2012-03-03 11:31:30 +00002297 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002298 {
anthony31f1bf72012-01-30 12:37:22 +00002299 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002300 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002301 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002302 break;
2303 }
anthony92c93bd2012-03-19 14:02:47 +00002304 (void) SetImageArtifact(_image,"identify:features","true");
2305 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002306 break;
2307 }
anthonyafa3dfc2012-03-03 11:31:30 +00002308 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002309 {
anthony92c93bd2012-03-19 14:02:47 +00002310 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002311 break;
2312 }
anthonyafa3dfc2012-03-03 11:31:30 +00002313 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002314 {
anthony92c93bd2012-03-19 14:02:47 +00002315 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002316 break;
2317 }
anthonyafa3dfc2012-03-03 11:31:30 +00002318 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002319 {
2320 PixelInfo
2321 target;
2322
anthony7bcfe7f2012-03-30 14:01:22 +00002323 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002324 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002325 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2326 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2327 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
cristy4b892612012-08-03 19:31:31 +00002328 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002329 break;
2330 }
anthonyafa3dfc2012-03-03 11:31:30 +00002331 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002332 {
2333 FrameInfo
2334 frame_info;
2335
anthony31f1bf72012-01-30 12:37:22 +00002336 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002337 compose;
2338
2339 const char*
2340 value;
2341
anthony92c93bd2012-03-19 14:02:47 +00002342 value=GetImageOption(_image_info,"compose");
anthony92c93bd2012-03-19 14:02:47 +00002343 compose=OverCompositeOp; /* use Over not _image->compose */
cristy4b892612012-08-03 19:31:31 +00002344 if (value != (const char *) NULL)
2345 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2346 MagickFalse,value);
anthony7bcfe7f2012-03-30 14:01:22 +00002347 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002348 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002349 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002350 frame_info.width=geometry.width;
2351 frame_info.height=geometry.height;
anthony805a2d42011-09-25 08:25:12 +00002352 frame_info.outer_bevel=geometry.x;
2353 frame_info.inner_bevel=geometry.y;
2354 frame_info.x=(ssize_t) frame_info.width;
2355 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002356 frame_info.width=_image->columns+2*frame_info.width;
2357 frame_info.height=_image->rows+2*frame_info.height;
2358 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002359 break;
2360 }
anthonyafa3dfc2012-03-03 11:31:30 +00002361 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002362 {
anthony805a2d42011-09-25 08:25:12 +00002363 double
anthonyb1d483a2012-04-14 12:53:56 +00002364 *args;
anthony805a2d42011-09-25 08:25:12 +00002365
anthonyb1d483a2012-04-14 12:53:56 +00002366 ssize_t
2367 count;
anthony805a2d42011-09-25 08:25:12 +00002368
anthony2a0ec8c2012-03-24 04:35:56 +00002369 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2370 if ( parse < 0 )
2371 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2372 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002373 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002374 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002375 if (args == (double *)NULL )
2376 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2377
2378 (void) FunctionImage(_image,(MagickFunction)parse,count,args,
2379 _exception);
2380 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002381 break;
2382 }
anthonyebb73a22012-03-22 14:25:52 +00002383 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002384 }
2385 case 'g':
2386 {
anthonyafa3dfc2012-03-03 11:31:30 +00002387 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002388 {
anthony7a4d6102012-07-01 09:48:25 +00002389 double
2390 constant;
2391
anthony7bcfe7f2012-03-30 14:01:22 +00002392 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002393 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony7a4d6102012-07-01 09:48:25 +00002394 constant=StringToDouble(arg1,(char **) NULL);
2395#if 0
2396 /* Using Gamma, via a cache */
2397 if (IfPlusOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002398 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002399 (void) GammaImage(_image,constant,_exception);
2400#else
2401 /* Using Evaluate POW, direct update of values - more accurite */
anthonyafa3dfc2012-03-03 11:31:30 +00002402 if (IfNormalOp)
cristy3e3ec3a2012-11-03 23:11:06 +00002403 constant=PerceptibleReciprocal(constant);
anthony7a4d6102012-07-01 09:48:25 +00002404 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
2405#endif
2406 /* Set gamma setting -- Old meaning of "+gamma"
2407 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2408 */
anthony805a2d42011-09-25 08:25:12 +00002409 break;
2410 }
anthony975a8d72012-04-12 13:54:36 +00002411 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002412 {
anthonyfd706f92012-01-19 04:22:02 +00002413 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002414 if ((flags & (RhoValue|SigmaValue)) == 0)
2415 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002416 if ((flags & SigmaValue) == 0)
2417 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002418 new_image=GaussianBlurImage(_image,geometry_info.rho,
2419 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002420 break;
2421 }
anthony975a8d72012-04-12 13:54:36 +00002422 if (LocaleCompare("gaussian",option+1) == 0)
2423 {
anthony464f1c42012-04-22 08:51:01 +00002424 CLIWandWarnReplaced("-gaussian-blur");
anthony975a8d72012-04-12 13:54:36 +00002425 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
2426 }
anthonyafa3dfc2012-03-03 11:31:30 +00002427 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002428 {
anthonyfd706f92012-01-19 04:22:02 +00002429 /*
anthony31f1bf72012-01-30 12:37:22 +00002430 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002431 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002432 FUTURE: Why if no 'offset' does this resize ALL images?
2433 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002434 */
anthonyafa3dfc2012-03-03 11:31:30 +00002435 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002436 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002437 if (_image->geometry != (char *) NULL)
2438 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002439 break;
2440 }
anthony7bcfe7f2012-03-30 14:01:22 +00002441 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002442 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002443 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002444 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002445 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002446 else
anthony92c93bd2012-03-19 14:02:47 +00002447 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002448 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002449 break;
2450 }
anthonyebb73a22012-03-22 14:25:52 +00002451 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002452 }
anthony805a2d42011-09-25 08:25:12 +00002453 case 'i':
2454 {
anthonyafa3dfc2012-03-03 11:31:30 +00002455 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002456 {
anthony31f1bf72012-01-30 12:37:22 +00002457 const char
2458 *format,
anthony805a2d42011-09-25 08:25:12 +00002459 *text;
2460
anthony92c93bd2012-03-19 14:02:47 +00002461 format=GetImageOption(_image_info,"format");
anthony964d28e2012-05-17 23:39:46 +00002462 if (format == (char *) NULL) {
2463 (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception);
2464 break;
2465 }
anthony92c93bd2012-03-19 14:02:47 +00002466 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002467 if (text == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00002468 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
2469 option);
anthony805a2d42011-09-25 08:25:12 +00002470 (void) fputs(text,stdout);
2471 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002472 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002473 break;
2474 }
anthonyafa3dfc2012-03-03 11:31:30 +00002475 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002476 {
anthonyb1e21ed2012-04-20 12:43:12 +00002477 flags=ParseGeometry(arg1,&geometry_info);
2478 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002479 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002480 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2481 _exception);
anthony805a2d42011-09-25 08:25:12 +00002482 break;
2483 }
anthonyafa3dfc2012-03-03 11:31:30 +00002484 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002485 {
anthonyfe1aa782012-03-24 13:43:04 +00002486 /* FUTURE: New to IMv7
2487 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002488 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002489 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002490 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2491 new_image=InterpolativeResizeImage(_image,geometry.width,
2492 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002493 break;
2494 }
anthonyebb73a22012-03-22 14:25:52 +00002495 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002496 }
2497 case 'l':
2498 {
anthonyafa3dfc2012-03-03 11:31:30 +00002499 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002500 {
anthonyfd706f92012-01-19 04:22:02 +00002501 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002502 if ((flags & (RhoValue|SigmaValue)) == 0)
2503 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyb5c691e2012-09-14 17:12:40 +00002504 if ((flags & SigmaValue) == 0)
2505 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00002506 if ((flags & PercentValue) != 0)
2507 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002508 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002509 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002510 _exception);
anthony805a2d42011-09-25 08:25:12 +00002511 break;
2512 }
anthonyafa3dfc2012-03-03 11:31:30 +00002513 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002514 {
cristya19f1d72012-08-07 18:24:38 +00002515 double
anthony805a2d42011-09-25 08:25:12 +00002516 black_point,
2517 gamma,
2518 white_point;
2519
2520 MagickStatusType
2521 flags;
2522
anthonyfd706f92012-01-19 04:22:02 +00002523 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002524 if ((flags & RhoValue) == 0)
2525 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002526 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002527 white_point=(double) QuantumRange;
anthony805a2d42011-09-25 08:25:12 +00002528 if ((flags & SigmaValue) != 0)
2529 white_point=geometry_info.sigma;
2530 gamma=1.0;
2531 if ((flags & XiValue) != 0)
2532 gamma=geometry_info.xi;
2533 if ((flags & PercentValue) != 0)
2534 {
cristya19f1d72012-08-07 18:24:38 +00002535 black_point*=(double) (QuantumRange/100.0);
2536 white_point*=(double) (QuantumRange/100.0);
anthony805a2d42011-09-25 08:25:12 +00002537 }
2538 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002539 white_point=(double) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002540 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002541 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002542 else
anthony92c93bd2012-03-19 14:02:47 +00002543 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002544 break;
2545 }
anthonyafa3dfc2012-03-03 11:31:30 +00002546 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002547 {
2548 char
2549 token[MaxTextExtent];
2550
2551 const char
2552 *p;
2553
2554 PixelInfo
2555 black_point,
2556 white_point;
2557
anthonyfd706f92012-01-19 04:22:02 +00002558 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002559 GetMagickToken(p,&p,token); /* get black point color */
2560 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002561 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002562 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002563 else
cristy269c9412011-10-13 23:41:15 +00002564 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002565 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002566 if (isalpha((int) token[0]) || (token[0] == '#'))
2567 GetMagickToken(p,&p,token);
2568 if (*token == '\0')
2569 white_point=black_point; /* set everything to that color */
2570 else
2571 {
2572 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2573 GetMagickToken(p,&p,token); /* Get white point color. */
2574 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002575 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002576 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002577 else
cristy269c9412011-10-13 23:41:15 +00002578 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002579 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002580 }
anthony92c93bd2012-03-19 14:02:47 +00002581 (void) LevelImageColors(_image,&black_point,&white_point,
2582 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002583 break;
2584 }
anthonyafa3dfc2012-03-03 11:31:30 +00002585 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002586 {
2587 double
2588 black_point,
2589 white_point;
2590
2591 MagickStatusType
2592 flags;
2593
anthonyfd706f92012-01-19 04:22:02 +00002594 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002595 if ((flags & RhoValue) == 0)
2596 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002597 black_point=geometry_info.rho;
cristya19f1d72012-08-07 18:24:38 +00002598 white_point=(double) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002599 if ((flags & SigmaValue) != 0)
2600 white_point=geometry_info.sigma;
2601 if ((flags & PercentValue) != 0)
2602 {
anthony92c93bd2012-03-19 14:02:47 +00002603 black_point*=(double) _image->columns*_image->rows/100.0;
2604 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002605 }
2606 if ((flags & SigmaValue) == 0)
cristya19f1d72012-08-07 18:24:38 +00002607 white_point=(double) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002608 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002609 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002610 break;
2611 }
anthonyafa3dfc2012-03-03 11:31:30 +00002612 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002613 {
anthonyfe1aa782012-03-24 13:43:04 +00002614 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002615 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002616 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002617 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002618 if ((flags & XValue) == 0)
2619 geometry.x=1;
2620 if ((flags & YValue) == 0)
2621 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002622 new_image=LiquidRescaleImage(_image,geometry.width,
2623 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002624 break;
2625 }
anthonyebb73a22012-03-22 14:25:52 +00002626 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002627 }
2628 case 'm':
2629 {
anthonyafa3dfc2012-03-03 11:31:30 +00002630 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002631 {
anthony464f1c42012-04-22 08:51:01 +00002632 CLIWandWarnReplaced("-remap");
anthony975a8d72012-04-12 13:54:36 +00002633 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
anthony805a2d42011-09-25 08:25:12 +00002634 break;
2635 }
anthonyafa3dfc2012-03-03 11:31:30 +00002636 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002637 {
anthony4837ac22012-05-18 23:39:48 +00002638 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002639 Image
2640 *mask;
2641
anthonyafa3dfc2012-03-03 11:31:30 +00002642 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002643 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002644 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002645 break;
2646 }
anthony5330ae02012-03-20 14:17:01 +00002647 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002648 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002649 if (mask == (Image *) NULL)
2650 break;
anthony92c93bd2012-03-19 14:02:47 +00002651 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002652 mask=DestroyImage(mask);
2653 break;
2654 }
cristy52ad9e92013-02-08 23:23:29 +00002655 if (LocaleCompare("matte",option+1) == 0)
2656 {
2657 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2658 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2659 DeactivateAlphaChannel, _exception);
2660 break;
2661 }
2662 if (LocaleCompare("median",option+1) == 0)
2663 {
2664 CLIWandWarnReplaced("-statistic Median");
2665 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2666 break;
2667 }
2668 if (LocaleCompare("mode",option+1) == 0)
2669 {
2670 /* FUTURE: note this is also a special "montage" option */
2671 CLIWandWarnReplaced("-statistic Mode");
2672 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
2673 break;
2674 }
anthonyafa3dfc2012-03-03 11:31:30 +00002675 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002676 {
anthony7bcfe7f2012-03-30 14:01:22 +00002677 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002678 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002679 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002680 break;
2681 }
anthonyafa3dfc2012-03-03 11:31:30 +00002682 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002683 {
anthony92c93bd2012-03-19 14:02:47 +00002684 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002685 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002686 break;
2687 }
anthonyafa3dfc2012-03-03 11:31:30 +00002688 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002689 {
anthony92c93bd2012-03-19 14:02:47 +00002690 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002691 break;
2692 }
anthonyafa3dfc2012-03-03 11:31:30 +00002693 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002694 {
2695 char
2696 token[MaxTextExtent];
2697
2698 const char
2699 *p;
2700
2701 KernelInfo
2702 *kernel;
2703
anthony805a2d42011-09-25 08:25:12 +00002704 ssize_t
2705 iterations;
2706
anthonyfd706f92012-01-19 04:22:02 +00002707 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002708 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002709 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2710 if ( parse < 0 )
2711 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2712 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002713 iterations=1L;
2714 GetMagickToken(p,&p,token);
2715 if ((*p == ':') || (*p == ','))
2716 GetMagickToken(p,&p,token);
2717 if ((*p != '\0'))
2718 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002719 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002720 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002721 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2722 option,arg2);
2723 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2724 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002725 kernel=DestroyKernelInfo(kernel);
2726 break;
2727 }
anthonyafa3dfc2012-03-03 11:31:30 +00002728 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002729 {
anthonyfd706f92012-01-19 04:22:02 +00002730 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002731 if ((flags & (RhoValue|SigmaValue)) == 0)
2732 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002733 if ((flags & SigmaValue) == 0)
2734 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002735 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002736 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002737 break;
2738 }
anthonyebb73a22012-03-22 14:25:52 +00002739 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002740 }
2741 case 'n':
2742 {
anthonyafa3dfc2012-03-03 11:31:30 +00002743 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002744 {
anthony92c93bd2012-03-19 14:02:47 +00002745 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002746 break;
2747 }
anthonyafa3dfc2012-03-03 11:31:30 +00002748 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002749 {
anthony975a8d72012-04-12 13:54:36 +00002750 double
2751 attenuate;
2752
2753 const char*
2754 value;
2755
anthonyafa3dfc2012-03-03 11:31:30 +00002756 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002757 {
anthony464f1c42012-04-22 08:51:01 +00002758 CLIWandWarnReplaced("-statistic NonPeak");
anthony975a8d72012-04-12 13:54:36 +00002759 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
2760 break;
anthony805a2d42011-09-25 08:25:12 +00002761 }
anthony975a8d72012-04-12 13:54:36 +00002762 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2763 if ( parse < 0 )
2764 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2765 option,arg1);
2766 attenuate=1.0;
2767 value=GetImageOption(_image_info,"attenuate");
2768 if (value != (const char *) NULL)
2769 attenuate=StringToDouble(value,(char **) NULL);
2770 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2771 _exception);
anthony805a2d42011-09-25 08:25:12 +00002772 break;
2773 }
anthonyafa3dfc2012-03-03 11:31:30 +00002774 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002775 {
anthony92c93bd2012-03-19 14:02:47 +00002776 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002777 break;
2778 }
anthonyebb73a22012-03-22 14:25:52 +00002779 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002780 }
2781 case 'o':
2782 {
anthonyafa3dfc2012-03-03 11:31:30 +00002783 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002784 {
2785 PixelInfo
2786 target;
2787
anthony92c93bd2012-03-19 14:02:47 +00002788 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2789 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2790 _exception);
anthony805a2d42011-09-25 08:25:12 +00002791 break;
2792 }
anthonyafa3dfc2012-03-03 11:31:30 +00002793 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002794 {
anthony92c93bd2012-03-19 14:02:47 +00002795 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002796 break;
2797 }
anthonyebb73a22012-03-22 14:25:52 +00002798 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002799 }
2800 case 'p':
2801 {
anthonyafa3dfc2012-03-03 11:31:30 +00002802 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002803 {
anthony22de2722012-04-19 14:43:00 +00002804 flags=ParseGeometry(arg1,&geometry_info);
2805 if ((flags & (RhoValue|SigmaValue)) == 0)
2806 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002807 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2808 _exception);
anthony805a2d42011-09-25 08:25:12 +00002809 break;
2810 }
cristy7884a932012-11-04 14:33:51 +00002811 if (LocaleCompare("perceptible",option+1) == 0)
2812 {
2813 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2814 _exception);
2815 break;
2816 }
anthonyafa3dfc2012-03-03 11:31:30 +00002817 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002818 {
cristye9e3d382011-12-14 01:50:13 +00002819 const char
2820 *caption;
2821
anthony805a2d42011-09-25 08:25:12 +00002822 double
2823 angle;
2824
anthony7bc87992012-03-25 02:32:51 +00002825 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002826 RandomInfo
2827 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002828
anthonyf42014d2012-03-25 09:53:06 +00002829 random_info=AcquireRandomInfo();
2830 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2831 random_info=DestroyRandomInfo(random_info);
2832 }
anthony7bc87992012-03-25 02:32:51 +00002833 else {
anthonyf42014d2012-03-25 09:53:06 +00002834 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002835 if ((flags & RhoValue) == 0)
2836 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002837 angle=geometry_info.rho;
2838 }
anthony92c93bd2012-03-19 14:02:47 +00002839 caption=GetImageProperty(_image,"caption",_exception);
2840 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2841 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002842 break;
2843 }
anthonyafa3dfc2012-03-03 11:31:30 +00002844 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002845 {
anthony22de2722012-04-19 14:43:00 +00002846 flags=ParseGeometry(arg1,&geometry_info);
2847 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002848 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002849 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
cristycbda6112012-05-27 20:57:16 +00002850 _quantize_info->dither_method,_exception);
anthony805a2d42011-09-25 08:25:12 +00002851 break;
2852 }
anthonyafa3dfc2012-03-03 11:31:30 +00002853 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002854 {
anthony31f1bf72012-01-30 12:37:22 +00002855 /* FUTURE: should be a 'Genesis' option?
2856 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00002857 Why???
cristy947cb4c2011-10-20 18:41:46 +00002858 */
anthony7bc87992012-03-25 02:32:51 +00002859 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2860 if ( parse < 0 )
2861 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2862 option,arg1);
2863 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00002864 break;
2865 }
anthonyafa3dfc2012-03-03 11:31:30 +00002866 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002867 {
anthony4837ac22012-05-18 23:39:48 +00002868 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002869 const char
2870 *name;
2871
2872 const StringInfo
2873 *profile;
2874
2875 Image
2876 *profile_image;
2877
2878 ImageInfo
2879 *profile_info;
2880
anthonyafa3dfc2012-03-03 11:31:30 +00002881 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002882 { /* Remove a profile from the _image. */
2883 (void) ProfileImage(_image,arg1,(const unsigned char *)
2884 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002885 break;
2886 }
anthony92c93bd2012-03-19 14:02:47 +00002887 /* Associate a profile with the _image. */
2888 profile_info=CloneImageInfo(_image_info);
2889 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002890 if (profile != (StringInfo *) NULL)
2891 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002892 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002893 profile_info=DestroyImageInfo(profile_info);
2894 if (profile_image == (Image *) NULL)
2895 {
2896 StringInfo
2897 *profile;
2898
anthony92c93bd2012-03-19 14:02:47 +00002899 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002900 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002901 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002902 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002903 if (profile != (StringInfo *) NULL)
2904 {
anthony92c93bd2012-03-19 14:02:47 +00002905 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002906 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002907 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002908 profile=DestroyStringInfo(profile);
2909 }
2910 profile_info=DestroyImageInfo(profile_info);
2911 break;
2912 }
2913 ResetImageProfileIterator(profile_image);
2914 name=GetNextImageProfile(profile_image);
2915 while (name != (const char *) NULL)
2916 {
2917 profile=GetImageProfile(profile_image,name);
2918 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002919 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2920 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002921 name=GetNextImageProfile(profile_image);
2922 }
2923 profile_image=DestroyImage(profile_image);
2924 break;
2925 }
anthonyebb73a22012-03-22 14:25:52 +00002926 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002927 }
anthony805a2d42011-09-25 08:25:12 +00002928 case 'r':
2929 {
anthonyafa3dfc2012-03-03 11:31:30 +00002930 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002931 {
anthonyfd706f92012-01-19 04:22:02 +00002932 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002933 if ((flags & RhoValue) == 0)
2934 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyaa2c16c2012-03-25 22:21:35 +00002935 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002936 break;
2937 }
anthonyafa3dfc2012-03-03 11:31:30 +00002938 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002939 {
anthony7bcfe7f2012-03-30 14:01:22 +00002940 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002941 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002942 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00002943 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002944 break;
2945 }
anthonyafa3dfc2012-03-03 11:31:30 +00002946 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002947 {
anthony7bcfe7f2012-03-30 14:01:22 +00002948 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002949 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002950 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002951 break;
2952 }
anthony975a8d72012-04-12 13:54:36 +00002953 if (LocaleCompare("recolor",option+1) == 0)
2954 {
anthony464f1c42012-04-22 08:51:01 +00002955 CLIWandWarnReplaced("-color-matrix");
anthony975a8d72012-04-12 13:54:36 +00002956 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
2957 }
anthonyafa3dfc2012-03-03 11:31:30 +00002958 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002959 {
anthony4837ac22012-05-18 23:39:48 +00002960 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002961 Image
2962 *remap_image;
2963
anthony92c93bd2012-03-19 14:02:47 +00002964 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002965 if (remap_image == (Image *) NULL)
2966 break;
anthony92c93bd2012-03-19 14:02:47 +00002967 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002968 remap_image=DestroyImage(remap_image);
2969 break;
2970 }
anthonyafa3dfc2012-03-03 11:31:30 +00002971 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002972 {
anthonyafa3dfc2012-03-03 11:31:30 +00002973 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00002974 {
anthony7bcfe7f2012-03-30 14:01:22 +00002975 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00002976 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
2977 arg1);
2978 (void) ResetImagePage(_image,arg1);
2979 }
anthony31f1bf72012-01-30 12:37:22 +00002980 else
anthony92c93bd2012-03-19 14:02:47 +00002981 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00002982 break;
2983 }
anthonyafa3dfc2012-03-03 11:31:30 +00002984 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002985 {
anthonyf46d4262012-03-26 03:30:34 +00002986 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00002987 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002988 if ((flags & (RhoValue|SigmaValue)) == 0)
2989 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002990 if ((flags & SigmaValue) == 0)
2991 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002992 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002993 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002994 break;
2995 }
anthonyafa3dfc2012-03-03 11:31:30 +00002996 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002997 {
anthony7bcfe7f2012-03-30 14:01:22 +00002998 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002999 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003000 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3001 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003002 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003003 break;
3004 }
anthonyafa3dfc2012-03-03 11:31:30 +00003005 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003006 {
anthony7bcfe7f2012-03-30 14:01:22 +00003007 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003008 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003009 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3010 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003011 break;
3012 }
anthonyafa3dfc2012-03-03 11:31:30 +00003013 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003014 {
anthony22de2722012-04-19 14:43:00 +00003015 flags=ParseGeometry(arg1,&geometry_info);
3016 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003017 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00003018 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00003019 break;
3020 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3021 break;
anthony92c93bd2012-03-19 14:02:47 +00003022 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003023 break;
3024 }
anthonyebb73a22012-03-22 14:25:52 +00003025 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003026 }
3027 case 's':
3028 {
anthonyafa3dfc2012-03-03 11:31:30 +00003029 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003030 {
anthonyfe1aa782012-03-24 13:43:04 +00003031 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003032 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003033 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003034 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3035 new_image=SampleImage(_image,geometry.width,geometry.height,
3036 _exception);
anthony805a2d42011-09-25 08:25:12 +00003037 break;
3038 }
anthonyafa3dfc2012-03-03 11:31:30 +00003039 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003040 {
anthonyfe1aa782012-03-24 13:43:04 +00003041 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003042 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003043 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003044 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3045 new_image=ScaleImage(_image,geometry.width,geometry.height,
3046 _exception);
anthony805a2d42011-09-25 08:25:12 +00003047 break;
3048 }
anthonyf42014d2012-03-25 09:53:06 +00003049 if (LocaleCompare("segment",option+1) == 0)
3050 {
anthonyf42014d2012-03-25 09:53:06 +00003051 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003052 if ((flags & (RhoValue|SigmaValue)) == 0)
3053 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003054 if ((flags & SigmaValue) == 0)
3055 geometry_info.sigma=1.0;
3056 (void) SegmentImage(_image,_image->colorspace,
3057 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3058 _exception);
3059 break;
3060 }
anthonyafa3dfc2012-03-03 11:31:30 +00003061 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003062 {
anthonyfd706f92012-01-19 04:22:02 +00003063 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003064 if ((flags & (RhoValue|SigmaValue)) == 0)
3065 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3066 if ((flags & SigmaValue) == 0)
3067 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003068 if ((flags & PercentValue) != 0)
3069 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003070 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003071 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003072 break;
3073 }
anthonyafa3dfc2012-03-03 11:31:30 +00003074 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003075 {
anthony31f1bf72012-01-30 12:37:22 +00003076 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003077 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003078 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003079 break;
3080 }
anthonyafa3dfc2012-03-03 11:31:30 +00003081 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003082 {
anthony7bcfe7f2012-03-30 14:01:22 +00003083 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003084 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3085 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3086 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003087 break;
3088 }
anthonyafa3dfc2012-03-03 11:31:30 +00003089 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003090 {
anthonyfd706f92012-01-19 04:22:02 +00003091 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003092 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3093 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003094 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3095 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003096 break;
3097 }
anthonyafa3dfc2012-03-03 11:31:30 +00003098 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003099 {
anthonyfd706f92012-01-19 04:22:02 +00003100 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003101 if ((flags & (RhoValue|SigmaValue)) == 0)
3102 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003103 if ((flags & SigmaValue) == 0)
3104 geometry_info.sigma=1.0;
3105 if ((flags & XiValue) == 0)
3106 geometry_info.xi=4.0;
3107 if ((flags & PsiValue) == 0)
3108 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003109 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3110 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3111 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003112 break;
3113 }
anthonyafa3dfc2012-03-03 11:31:30 +00003114 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003115 {
anthonyfd706f92012-01-19 04:22:02 +00003116 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003117 if ((flags & (RhoValue|SigmaValue)) == 0)
3118 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003119 if ((flags & SigmaValue) == 0)
3120 geometry_info.sigma=1.0;
3121 if ((flags & XiValue) == 0)
3122 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003123 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3124 _exception);
anthony805a2d42011-09-25 08:25:12 +00003125 break;
3126 }
anthonyafa3dfc2012-03-03 11:31:30 +00003127 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003128 {
anthony7bcfe7f2012-03-30 14:01:22 +00003129 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003130 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003131 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3132 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003133 break;
3134 }
anthonyafa3dfc2012-03-03 11:31:30 +00003135 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003136 {
anthonyfd706f92012-01-19 04:22:02 +00003137 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003138 if ((flags & RhoValue) == 0)
3139 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003140 if ((flags & SigmaValue) == 0)
3141 geometry_info.sigma=geometry_info.rho;
cristy4b892612012-08-03 19:31:31 +00003142 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3143 _exception);
anthony805a2d42011-09-25 08:25:12 +00003144 break;
3145 }
anthonyafa3dfc2012-03-03 11:31:30 +00003146 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003147 {
anthonyfd706f92012-01-19 04:22:02 +00003148 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003149 if ((flags & RhoValue) == 0)
3150 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003151 if ((flags & SigmaValue) == 0)
3152 geometry_info.sigma=(double) QuantumRange/2.0;
3153 if ((flags & PercentValue) != 0)
3154 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3155 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003156 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003157 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003158 break;
3159 }
anthonyafa3dfc2012-03-03 11:31:30 +00003160 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003161 {
anthonyfd706f92012-01-19 04:22:02 +00003162 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003163 if ((flags & (RhoValue|SigmaValue)) == 0)
3164 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003165 if ((flags & SigmaValue) == 0)
3166 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003167 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003168 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003169 break;
3170 }
anthonyafa3dfc2012-03-03 11:31:30 +00003171 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003172 {
anthony7bcfe7f2012-03-30 14:01:22 +00003173 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003174 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003175 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3176 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003177 break;
3178 }
anthonyafa3dfc2012-03-03 11:31:30 +00003179 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003180 {
anthonyf42014d2012-03-25 09:53:06 +00003181 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3182 if ( parse < 0 )
3183 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3184 option,arg1);
anthony964d28e2012-05-17 23:39:46 +00003185 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3186 _exception);
anthony805a2d42011-09-25 08:25:12 +00003187 break;
3188 }
anthonyafa3dfc2012-03-03 11:31:30 +00003189 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003190 {
anthony7bcfe7f2012-03-30 14:01:22 +00003191 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003192 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003193 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003194 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003195 break;
3196 }
anthonyafa3dfc2012-03-03 11:31:30 +00003197 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003198 {
anthonyb1e21ed2012-04-20 12:43:12 +00003199 flags=ParseGeometry(arg1,&geometry_info);
3200 if ((flags & RhoValue) == 0)
3201 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003202 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3203 _exception);
anthony805a2d42011-09-25 08:25:12 +00003204 break;
3205 }
anthonyafa3dfc2012-03-03 11:31:30 +00003206 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003207 {
anthony7bc87992012-03-25 02:32:51 +00003208 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3209 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003210 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003211 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003212 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003213 if ((flags & RhoValue) == 0)
3214 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003215 if ((flags & SigmaValue) == 0)
3216 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003217 new_image=StatisticImage(_image,(StatisticType)parse,
3218 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3219 _exception);
anthony805a2d42011-09-25 08:25:12 +00003220 break;
3221 }
anthonyafa3dfc2012-03-03 11:31:30 +00003222 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003223 {
anthony92c93bd2012-03-19 14:02:47 +00003224 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003225 break;
3226 }
anthonyafa3dfc2012-03-03 11:31:30 +00003227 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003228 {
cristy898c6042012-06-24 00:36:34 +00003229 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00003230 if ((flags & RhoValue) == 0)
cristy898c6042012-06-24 00:36:34 +00003231 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003232 new_image=SwirlImage(_image,geometry_info.rho,
3233 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003234 break;
3235 }
anthonyebb73a22012-03-22 14:25:52 +00003236 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003237 }
3238 case 't':
3239 {
anthonyafa3dfc2012-03-03 11:31:30 +00003240 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003241 {
3242 double
3243 threshold;
3244
anthony52bef752012-03-27 13:54:47 +00003245 threshold=(double) QuantumRange/2;
3246 if (normal_op) {
anthony7bcfe7f2012-03-30 14:01:22 +00003247 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003248 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003249 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003250 }
anthony92c93bd2012-03-19 14:02:47 +00003251 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003252 break;
3253 }
anthonyafa3dfc2012-03-03 11:31:30 +00003254 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003255 {
anthony7bcfe7f2012-03-30 14:01:22 +00003256 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003257 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003258 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3259 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3260 _exception);
anthony805a2d42011-09-25 08:25:12 +00003261 break;
3262 }
anthonyafa3dfc2012-03-03 11:31:30 +00003263 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003264 {
anthony7bcfe7f2012-03-30 14:01:22 +00003265 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003266 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003267 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003268 break;
3269 }
anthonyafa3dfc2012-03-03 11:31:30 +00003270 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003271 {
anthony464f1c42012-04-22 08:51:01 +00003272 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003273 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003274 break;
3275 }
anthonyafa3dfc2012-03-03 11:31:30 +00003276 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003277 {
3278 PixelInfo
3279 target;
3280
anthony92c93bd2012-03-19 14:02:47 +00003281 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3282 (void) TransparentPaintImage(_image,&target,(Quantum)
3283 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003284 break;
3285 }
anthonyafa3dfc2012-03-03 11:31:30 +00003286 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003287 {
anthony92c93bd2012-03-19 14:02:47 +00003288 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003289 break;
3290 }
anthonyafa3dfc2012-03-03 11:31:30 +00003291 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003292 {
anthony92c93bd2012-03-19 14:02:47 +00003293 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003294 break;
3295 }
anthonyafa3dfc2012-03-03 11:31:30 +00003296 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003297 {
anthony92c93bd2012-03-19 14:02:47 +00003298 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003299 break;
3300 }
anthonyafa3dfc2012-03-03 11:31:30 +00003301 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003302 {
anthonyab3a50c2011-10-27 11:48:57 +00003303 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003304 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003305 break;
3306 }
anthonyebb73a22012-03-22 14:25:52 +00003307 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003308 }
3309 case 'u':
3310 {
anthonyafa3dfc2012-03-03 11:31:30 +00003311 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003312 {
anthony52bef752012-03-27 13:54:47 +00003313 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3314 Option is not documented, bt appears to be for "identify".
3315 We may need a identify specific verbose!
3316 */
3317 if (plus_alt_op) {
anthony92c93bd2012-03-19 14:02:47 +00003318 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003319 break;
3320 }
anthony92c93bd2012-03-19 14:02:47 +00003321 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3322 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003323 break;
3324 }
anthonyafa3dfc2012-03-03 11:31:30 +00003325 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003326 {
anthony92c93bd2012-03-19 14:02:47 +00003327 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003328 break;
3329 }
anthonyafa3dfc2012-03-03 11:31:30 +00003330 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003331 {
anthonyfd706f92012-01-19 04:22:02 +00003332 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003333 if ((flags & (RhoValue|SigmaValue)) == 0)
3334 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003335 if ((flags & SigmaValue) == 0)
3336 geometry_info.sigma=1.0;
3337 if ((flags & XiValue) == 0)
3338 geometry_info.xi=1.0;
3339 if ((flags & PsiValue) == 0)
3340 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003341 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3342 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003343 break;
3344 }
anthonyebb73a22012-03-22 14:25:52 +00003345 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003346 }
3347 case 'v':
3348 {
anthonyafa3dfc2012-03-03 11:31:30 +00003349 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003350 {
anthonyafa3dfc2012-03-03 11:31:30 +00003351 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003352 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003353 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003354 */
anthony92c93bd2012-03-19 14:02:47 +00003355 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003356 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003357 break;
3358 }
anthonyafa3dfc2012-03-03 11:31:30 +00003359 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003360 {
anthonyfd706f92012-01-19 04:22:02 +00003361 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003362 if ((flags & (RhoValue|SigmaValue)) == 0)
3363 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003364 if ((flags & SigmaValue) == 0)
3365 geometry_info.sigma=1.0;
3366 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003367 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003368 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003369 geometry_info.psi=0.1*_image->rows;
3370 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003371 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3372 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003373 break;
3374 }
anthonyebb73a22012-03-22 14:25:52 +00003375 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003376 }
3377 case 'w':
3378 {
anthonyafa3dfc2012-03-03 11:31:30 +00003379 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003380 {
anthonyfd706f92012-01-19 04:22:02 +00003381 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003382 if ((flags & (RhoValue|SigmaValue)) == 0)
3383 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003384 if ((flags & SigmaValue) == 0)
3385 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003386 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3387 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003388 break;
3389 }
anthonyafa3dfc2012-03-03 11:31:30 +00003390 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003391 {
anthony7bcfe7f2012-03-30 14:01:22 +00003392 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003393 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003394 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003395 break;
3396 }
anthonyebb73a22012-03-22 14:25:52 +00003397 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003398 }
3399 default:
anthonyebb73a22012-03-22 14:25:52 +00003400 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003401 }
anthony964d28e2012-05-17 23:39:46 +00003402 /* clean up percent escape interpreted strings */
3403 if (arg1 != arg1n )
3404 arg1=DestroyString((char *)arg1);
3405 if (arg2 != arg2n )
3406 arg2=DestroyString((char *)arg2);
3407
3408 /* Replace current image with any image that was generated
3409 and set image point to last image (so image->next is correct) */
anthony805a2d42011-09-25 08:25:12 +00003410 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003411 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003412
cristyfe831852013-02-12 14:56:07 +00003413 return(MagickTrue);
anthony92c93bd2012-03-19 14:02:47 +00003414#undef _image_info
3415#undef _draw_info
3416#undef _quantize_info
3417#undef _image
3418#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003419#undef IfNormalOp
3420#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003421#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003422#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003423}
anthonyfd706f92012-01-19 04:22:02 +00003424
cristyfe831852013-02-12 14:56:07 +00003425WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
3426 const char *option,const char *arg1,const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003427{
anthonyc7994672012-11-17 05:33:27 +00003428#if !USE_WAND_METHODS
anthony31f1bf72012-01-30 12:37:22 +00003429 size_t
anthony43f425d2012-02-26 12:58:58 +00003430 n,
anthony31f1bf72012-01-30 12:37:22 +00003431 i;
anthonyc7994672012-11-17 05:33:27 +00003432#endif
anthony31f1bf72012-01-30 12:37:22 +00003433
anthony43f425d2012-02-26 12:58:58 +00003434 assert(cli_wand != (MagickCLI *) NULL);
3435 assert(cli_wand->signature == WandSignature);
3436 assert(cli_wand->wand.signature == WandSignature);
3437 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003438 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003439 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003440
anthonyafa3dfc2012-03-03 11:31:30 +00003441#if !USE_WAND_METHODS
3442 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003443 i=0;
anthony43f425d2012-02-26 12:58:58 +00003444 n=GetImageListLength(cli_wand->wand.images);
3445 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003446 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003447 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003448 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003449 if ( cli_wand->wand.images->next == (Image *) NULL )
3450 break;
3451 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003452 }
anthony43f425d2012-02-26 12:58:58 +00003453 assert( i == n );
3454 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003455#else
3456 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003457 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
anthonyafa3dfc2012-03-03 11:31:30 +00003458 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3459 MagickResetIterator(&cli_wand->wand);
3460#endif
cristyfe831852013-02-12 14:56:07 +00003461 return(MagickTrue);
anthony805a2d42011-09-25 08:25:12 +00003462}
3463
3464/*
3465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3466% %
3467% %
3468% %
anthony43f425d2012-02-26 12:58:58 +00003469+ 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 +00003470% %
3471% %
3472% %
3473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3474%
anthony43f425d2012-02-26 12:58:58 +00003475% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003476% entire image list as a whole. The result is often a complete replacment
anthonyc7994672012-11-17 05:33:27 +00003477% of the image list with a completely new list, or with just a single image
3478% result.
anthony805a2d42011-09-25 08:25:12 +00003479%
3480% The format of the MogrifyImage method is:
3481%
cristyfe831852013-02-12 14:56:07 +00003482% MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3483% const char *option,const char *arg1,const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003484%
3485% A description of each parameter follows:
3486%
anthony43f425d2012-02-26 12:58:58 +00003487% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003488%
anthony36a8c2c2012-02-10 00:08:44 +00003489% o option: The option string for the operation
3490%
anthony31f1bf72012-01-30 12:37:22 +00003491% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003492% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003493%
anthony805a2d42011-09-25 08:25:12 +00003494*/
cristyfe831852013-02-12 14:56:07 +00003495WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3496 const char *option,const char *arg1n,const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00003497{
cristya30f8e62013-02-19 15:03:45 +00003498 const char /* For percent escape interpretImageProperties() */
3499 *arg1,
3500 *arg2;
anthony2a0ec8c2012-03-24 04:35:56 +00003501
anthony31f1bf72012-01-30 12:37:22 +00003502 Image
3503 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003504
cristya30f8e62013-02-19 15:03:45 +00003505 MagickStatusType
3506 status;
3507
3508 ssize_t
3509 parse;
anthony964d28e2012-05-17 23:39:46 +00003510
anthony2e4501b2012-03-30 04:41:54 +00003511#define _image_info (cli_wand->wand.image_info)
3512#define _images (cli_wand->wand.images)
3513#define _exception (cli_wand->wand.exception)
3514#define _draw_info (cli_wand->draw_info)
3515#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00003516#define _process_flags (cli_wand->process_flags)
3517#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00003518#define IfNormalOp (*option=='-')
3519#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00003520#define normal_op IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003521
anthony43f425d2012-02-26 12:58:58 +00003522 assert(cli_wand != (MagickCLI *) NULL);
3523 assert(cli_wand->signature == WandSignature);
3524 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003525 assert(_images != (Image *) NULL); /* _images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003526 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003527 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003528
anthony964d28e2012-05-17 23:39:46 +00003529 /* Interpret Percent Escapes in Arguments - using first image */
3530 arg1 = arg1n;
3531 arg2 = arg2n;
3532 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3533 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3534 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3535 /* Interpret Percent escapes in argument 1 */
3536 if (arg1n != (char *) NULL) {
3537 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3538 if (arg1 == (char *) NULL) {
3539 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3540 arg1=arg1n; /* use the given argument as is */
3541 }
3542 }
3543 if (arg2n != (char *) NULL) {
3544 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3545 if (arg2 == (char *) NULL) {
3546 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3547 arg2=arg2n; /* use the given argument as is */
3548 }
3549 }
3550 }
anthony4837ac22012-05-18 23:39:48 +00003551#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00003552#undef _option_type
3553
3554#if 0
3555 (void) FormatLocaleFile(stderr,
3556 "CLIListOperatorImages: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
3557#endif
3558
cristyfe831852013-02-12 14:56:07 +00003559 status=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00003560 new_images=NewImageList();
3561
anthonyafa3dfc2012-03-03 11:31:30 +00003562 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003563 {
3564 case 'a':
3565 {
anthonyafa3dfc2012-03-03 11:31:30 +00003566 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003567 {
anthony92c93bd2012-03-19 14:02:47 +00003568 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003569 break;
3570 }
cristy52ad9e92013-02-08 23:23:29 +00003571 if (LocaleCompare("average",option+1) == 0)
3572 {
3573 CLIWandWarnReplaced("-evaluate-sequence Mean");
3574 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
3575 break;
3576 }
anthonyebb73a22012-03-22 14:25:52 +00003577 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003578 }
3579 case 'c':
3580 {
cristy5f257b22012-03-07 00:27:29 +00003581 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003582 {
anthony92c93bd2012-03-19 14:02:47 +00003583 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003584 break;
3585 }
anthonyafa3dfc2012-03-03 11:31:30 +00003586 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003587 {
anthony805a2d42011-09-25 08:25:12 +00003588 Image
anthony31f1bf72012-01-30 12:37:22 +00003589 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003590
anthonyafa3dfc2012-03-03 11:31:30 +00003591 /* FUTURE - make this a compose option, and thus can be used
3592 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003593 _images.
cristy87c02f42012-02-24 00:19:10 +00003594 */
anthony92c93bd2012-03-19 14:02:47 +00003595 new_images=RemoveFirstImageFromList(&_images);
3596 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003597 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003598 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003599 break;
cristye52fb5e2012-04-06 23:30:20 +00003600 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003601 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003602 break;
3603 }
anthonyafa3dfc2012-03-03 11:31:30 +00003604 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003605 {
anthony92c93bd2012-03-19 14:02:47 +00003606 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003607 break;
3608 }
anthonyafa3dfc2012-03-03 11:31:30 +00003609 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003610 {
anthony43f425d2012-02-26 12:58:58 +00003611 /* FUTURE - this may be replaced by a 'channel' method */
cristy46f354c2012-07-04 13:31:29 +00003612 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
cristy8448a0d2013-02-15 18:20:53 +00003613 if (parse < 0)
3614 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
3615 arg1);
cristy46f354c2012-07-04 13:31:29 +00003616 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003617 break;
3618 }
anthonyafa3dfc2012-03-03 11:31:30 +00003619 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003620 {
cristyfeb3e962012-03-29 17:25:55 +00003621 CompositeOperator
3622 compose;
3623
3624 const char*
3625 value;
3626
3627 MagickBooleanType
3628 clip_to_self;
3629
anthony805a2d42011-09-25 08:25:12 +00003630 Image
3631 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003632 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003633
3634 RectangleInfo
3635 geometry;
3636
anthony7bcfe7f2012-03-30 14:01:22 +00003637 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003638 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003639 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003640 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003641 else
3642 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3643 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003644
anthony7bcfe7f2012-03-30 14:01:22 +00003645 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003646 value=GetImageOption(_image_info,"compose:clip-to-self");
3647 if (value == (const char *) NULL)
3648 clip_to_self=MagickTrue;
3649 else
3650 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3651 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003652 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003653 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003654 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003655 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003656 }
3657
anthony92c93bd2012-03-19 14:02:47 +00003658 new_images=RemoveFirstImageFromList(&_images);
3659 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003660 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003661 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003662
anthony31f1bf72012-01-30 12:37:22 +00003663 /* FUTURE - this should not be here! - should be part of -geometry */
3664 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003665 source_image->geometry,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003666 SetGeometry(source_image,&geometry);
3667 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3668 GravityAdjustGeometry(new_images->columns,new_images->rows,
cristyfe831852013-02-12 14:56:07 +00003669 new_images->gravity, &geometry);
anthony92c93bd2012-03-19 14:02:47 +00003670 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003671 if (mask_image != (Image *) NULL)
cristyfe831852013-02-12 14:56:07 +00003672 {
anthony5f867ae2011-10-09 10:28:34 +00003673 if ((compose == DisplaceCompositeOp) ||
cristyfe831852013-02-12 14:56:07 +00003674 (compose == DistortCompositeOp))
3675 status&=CompositeImage(source_image,mask_image,
anthony7bcfe7f2012-03-30 14:01:22 +00003676 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
cristyfe831852013-02-12 14:56:07 +00003677 else
cristy15007e82013-02-17 18:46:40 +00003678 {
3679 Image
3680 *image;
3681
3682 RectangleInfo
3683 source_geometry;
3684
3685 source_geometry.width=mask_image->columns;
3686 source_geometry.height=mask_image->rows;
3687 source_geometry.x=(-geometry.x);
3688 source_geometry.y=(-geometry.y);
3689 geometry.x=0;
3690 geometry.y=0;
3691 image=ExtentImage(source_image,&source_geometry,_exception);
3692 if (image != (Image *) NULL)
3693 {
3694 source_image=DestroyImage(source_image);
3695 source_image=image;
3696 }
3697 status&=CompositeImage(source_image,mask_image,
3698 IntensityCompositeOp,MagickTrue,0,0,_exception);
3699 }
cristyfe831852013-02-12 14:56:07 +00003700 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003701 }
cristyfe831852013-02-12 14:56:07 +00003702 status&=CompositeImage(new_images,source_image,compose,clip_to_self,
cristyfeb3e962012-03-29 17:25:55 +00003703 geometry.x,geometry.y,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003704 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003705 break;
3706 }
anthonyebb73a22012-03-22 14:25:52 +00003707 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003708 }
3709 case 'd':
3710 {
anthonyafa3dfc2012-03-03 11:31:30 +00003711 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003712 {
anthony464f1c42012-04-22 08:51:01 +00003713 CLIWandWarnReplaced("-layer CompareAny");
anthonyafa3dfc2012-03-03 11:31:30 +00003714 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003715 break;
3716 }
anthonyafa3dfc2012-03-03 11:31:30 +00003717 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003718 {
anthonyafa3dfc2012-03-03 11:31:30 +00003719 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003720 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003721 else
anthony92c93bd2012-03-19 14:02:47 +00003722 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003723 break;
3724 }
anthonyafa3dfc2012-03-03 11:31:30 +00003725 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003726 {
anthonyafa3dfc2012-03-03 11:31:30 +00003727 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003728 {
3729 const char
3730 *p;
3731
3732 size_t
3733 number_duplicates;
3734
anthony7bcfe7f2012-03-30 14:01:22 +00003735 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003736 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3737 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003738 number_duplicates=(size_t) StringToLong(arg1);
3739 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003740 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003741 new_images=DuplicateImages(_images,number_duplicates,"-1",
3742 _exception);
anthony805a2d42011-09-25 08:25:12 +00003743 else
anthony92c93bd2012-03-19 14:02:47 +00003744 new_images=DuplicateImages(_images,number_duplicates,p,
3745 _exception);
anthony805a2d42011-09-25 08:25:12 +00003746 }
anthonyafa3dfc2012-03-03 11:31:30 +00003747 else
anthony92c93bd2012-03-19 14:02:47 +00003748 new_images=DuplicateImages(_images,1,"-1",_exception);
3749 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003750 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003751 break;
3752 }
anthonyebb73a22012-03-22 14:25:52 +00003753 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003754 }
3755 case 'e':
3756 {
anthonyafa3dfc2012-03-03 11:31:30 +00003757 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003758 {
anthony2a0ec8c2012-03-24 04:35:56 +00003759 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3760 if ( parse < 0 )
3761 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3762 option,arg1);
3763 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3764 _exception);
anthony805a2d42011-09-25 08:25:12 +00003765 break;
3766 }
anthonyebb73a22012-03-22 14:25:52 +00003767 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003768 }
3769 case 'f':
3770 {
anthonyafa3dfc2012-03-03 11:31:30 +00003771 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003772 {
anthony92c93bd2012-03-19 14:02:47 +00003773 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003774 break;
3775 }
anthonyafa3dfc2012-03-03 11:31:30 +00003776 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003777 {
anthony319dac62012-03-06 04:12:44 +00003778 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003779 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003780 break;
3781 }
anthonyafa3dfc2012-03-03 11:31:30 +00003782 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003783 {
anthony92c93bd2012-03-19 14:02:47 +00003784 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003785 break;
3786 }
anthonyebb73a22012-03-22 14:25:52 +00003787 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003788 }
3789 case 'h':
3790 {
anthonyafa3dfc2012-03-03 11:31:30 +00003791 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003792 {
anthony31f1bf72012-01-30 12:37:22 +00003793 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003794 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003795 */
anthony805a2d42011-09-25 08:25:12 +00003796 Image
anthony31f1bf72012-01-30 12:37:22 +00003797 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003798
anthony92c93bd2012-03-19 14:02:47 +00003799 new_images=RemoveFirstImageFromList(&_images);
3800 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003801 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003802 break;
anthony92c93bd2012-03-19 14:02:47 +00003803 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003804 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003805 break;
3806 }
anthonyebb73a22012-03-22 14:25:52 +00003807 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003808 }
3809 case 'i':
3810 {
anthonyafa3dfc2012-03-03 11:31:30 +00003811 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003812 {
3813 Image
anthony805a2d42011-09-25 08:25:12 +00003814 *magnitude_image,
3815 *phase_image;
3816
anthony92c93bd2012-03-19 14:02:47 +00003817 magnitude_image=RemoveFirstImageFromList(&_images);
3818 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003819 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003820 if (phase_image == (Image *) NULL)
3821 break;
3822 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003823 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003824 magnitude_image=DestroyImage(magnitude_image);
3825 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003826 break;
3827 }
anthonyafa3dfc2012-03-03 11:31:30 +00003828 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003829 {
3830 Image
anthony31f1bf72012-01-30 12:37:22 +00003831 *insert_image,
3832 *index_image;
3833
3834 ssize_t
3835 index;
anthony805a2d42011-09-25 08:25:12 +00003836
anthony7bcfe7f2012-03-30 14:01:22 +00003837 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00003838 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003839 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003840 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003841 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003842 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003843 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003844 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003845 PrependImageToList(&_images,insert_image);
3846 else if (index == (ssize_t) GetImageListLength(_images))
3847 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003848 else
anthony43f425d2012-02-26 12:58:58 +00003849 {
anthony92c93bd2012-03-19 14:02:47 +00003850 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003851 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00003852 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00003853 InsertImageInList(&index_image,insert_image);
3854 }
anthony92c93bd2012-03-19 14:02:47 +00003855 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003856 break;
3857 }
anthonyebb73a22012-03-22 14:25:52 +00003858 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003859 }
3860 case 'l':
3861 {
anthonyafa3dfc2012-03-03 11:31:30 +00003862 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003863 {
anthonyfe1aa782012-03-24 13:43:04 +00003864 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3865 if ( parse < 0 )
3866 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3867 option,arg1);
cristya0417062012-09-02 23:34:56 +00003868 switch ((LayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00003869 {
3870 case CoalesceLayer:
3871 {
anthony92c93bd2012-03-19 14:02:47 +00003872 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003873 break;
3874 }
3875 case CompareAnyLayer:
3876 case CompareClearLayer:
3877 case CompareOverlayLayer:
3878 default:
3879 {
cristya0417062012-09-02 23:34:56 +00003880 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00003881 _exception);
anthony805a2d42011-09-25 08:25:12 +00003882 break;
3883 }
3884 case MergeLayer:
3885 case FlattenLayer:
3886 case MosaicLayer:
3887 case TrimBoundsLayer:
3888 {
cristya0417062012-09-02 23:34:56 +00003889 new_images=MergeImageLayers(_images,(LayerMethod) parse,
anthonyfe1aa782012-03-24 13:43:04 +00003890 _exception);
anthony805a2d42011-09-25 08:25:12 +00003891 break;
3892 }
3893 case DisposeLayer:
3894 {
anthony92c93bd2012-03-19 14:02:47 +00003895 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003896 break;
3897 }
3898 case OptimizeImageLayer:
3899 {
anthony92c93bd2012-03-19 14:02:47 +00003900 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003901 break;
3902 }
3903 case OptimizePlusLayer:
3904 {
anthony92c93bd2012-03-19 14:02:47 +00003905 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003906 break;
3907 }
3908 case OptimizeTransLayer:
3909 {
anthony92c93bd2012-03-19 14:02:47 +00003910 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003911 break;
3912 }
3913 case RemoveDupsLayer:
3914 {
anthony92c93bd2012-03-19 14:02:47 +00003915 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003916 break;
3917 }
3918 case RemoveZeroLayer:
3919 {
anthony92c93bd2012-03-19 14:02:47 +00003920 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003921 break;
3922 }
3923 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003924 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003925 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003926 if (new_images == (Image *) NULL)
3927 break;
anthony92c93bd2012-03-19 14:02:47 +00003928 _images=DestroyImageList(_images);
3929 _images=OptimizeImageLayers(new_images,_exception);
3930 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003931 break;
3932 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00003933 OptimizeImageTransparency(_images,_exception);
3934 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3935 _exception);
anthony805a2d42011-09-25 08:25:12 +00003936 break;
3937 }
3938 case CompositeLayer:
3939 {
anthony805a2d42011-09-25 08:25:12 +00003940 Image
3941 *source;
3942
3943 RectangleInfo
3944 geometry;
3945
anthony31f1bf72012-01-30 12:37:22 +00003946 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003947 compose;
3948
3949 const char*
3950 value;
3951
anthony92c93bd2012-03-19 14:02:47 +00003952 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003953 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003954 if (value != (const char *) NULL)
3955 compose=(CompositeOperator) ParseCommandOption(
3956 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003957
anthony31f1bf72012-01-30 12:37:22 +00003958 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00003959 source=_images;
anthony805a2d42011-09-25 08:25:12 +00003960 while (source != (Image *) NULL)
3961 {
3962 source=GetNextImageInList(source);
3963 if ((source != (Image *) NULL) &&
3964 (LocaleCompare(source->magick,"NULL") == 0))
3965 break;
3966 }
3967 if (source != (Image *) NULL)
3968 {
3969 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3970 (GetNextImageInList(source) == (Image *) NULL))
3971 source=(Image *) NULL;
3972 else
anthony31f1bf72012-01-30 12:37:22 +00003973 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003974 source=SplitImageList(source->previous);
3975 DeleteImageFromList(&source);
3976 }
3977 }
3978 if (source == (Image *) NULL)
3979 {
anthony92c93bd2012-03-19 14:02:47 +00003980 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00003981 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003982 break;
3983 }
anthony31f1bf72012-01-30 12:37:22 +00003984 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00003985 SetGeometry(_images,&geometry);
3986 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003987 geometry.width=source->page.width != 0 ?
3988 source->page.width : source->columns;
3989 geometry.height=source->page.height != 0 ?
3990 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00003991 GravityAdjustGeometry(_images->page.width != 0 ?
3992 _images->page.width : _images->columns,
3993 _images->page.height != 0 ? _images->page.height :
3994 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003995
anthony31f1bf72012-01-30 12:37:22 +00003996 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00003997 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
3998 _exception);
anthony805a2d42011-09-25 08:25:12 +00003999 source=DestroyImageList(source);
4000 break;
4001 }
4002 }
anthony805a2d42011-09-25 08:25:12 +00004003 break;
4004 }
anthonyebb73a22012-03-22 14:25:52 +00004005 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004006 }
4007 case 'm':
4008 {
anthonyafa3dfc2012-03-03 11:31:30 +00004009 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004010 {
anthony464f1c42012-04-22 08:51:01 +00004011 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00004012 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004013 break;
4014 }
anthonyafa3dfc2012-03-03 11:31:30 +00004015 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004016 {
4017 Image
4018 *morph_image;
4019
anthony7bcfe7f2012-03-30 14:01:22 +00004020 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004021 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004022 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4023 _exception);
anthony805a2d42011-09-25 08:25:12 +00004024 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004025 break;
anthony92c93bd2012-03-19 14:02:47 +00004026 _images=DestroyImageList(_images);
4027 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004028 break;
4029 }
anthonyafa3dfc2012-03-03 11:31:30 +00004030 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004031 {
anthony319dac62012-03-06 04:12:44 +00004032 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00004033 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004034 break;
4035 }
anthonyebb73a22012-03-22 14:25:52 +00004036 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004037 }
4038 case 'p':
4039 {
cristy02016cf2012-11-13 01:14:41 +00004040 if (LocaleCompare("poly",option+1) == 0)
4041 {
4042 double
4043 *args;
4044
4045 ssize_t
4046 count;
4047
4048 /* convert argument string into an array of doubles */
4049 args = StringToArrayOfDoubles(arg2,&count,_exception);
4050 if (args == (double *)NULL )
4051 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
4052 new_images=PolynomialImage(_images,count >> 1,args,_exception);
4053 args=(double *) RelinquishMagickMemory(args);
4054 break;
4055 }
anthonyafa3dfc2012-03-03 11:31:30 +00004056 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004057 {
anthony964d28e2012-05-17 23:39:46 +00004058 (void) FormatLocaleFile(stdout,"%s",arg1);
anthony24aa8822012-03-11 00:56:06 +00004059 break;
anthony805a2d42011-09-25 08:25:12 +00004060 }
anthonyafa3dfc2012-03-03 11:31:30 +00004061 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004062 {
anthonyb1d483a2012-04-14 12:53:56 +00004063 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00004064 char
4065 **arguments;
4066
4067 int
4068 j,
4069 number_arguments;
4070
anthony31f1bf72012-01-30 12:37:22 +00004071 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004072 if (arguments == (char **) NULL)
4073 break;
anthony31f1bf72012-01-30 12:37:22 +00004074 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004075 {
4076 char
4077 breaker,
4078 quote,
4079 *token;
4080
4081 const char
4082 *arguments;
4083
4084 int
4085 next,
4086 status;
4087
4088 size_t
4089 length;
4090
4091 TokenInfo
4092 *token_info;
4093
4094 /*
anthony24aa8822012-03-11 00:56:06 +00004095 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004096 */
anthony31f1bf72012-01-30 12:37:22 +00004097 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004098 token=(char *) NULL;
4099 if (~length >= (MaxTextExtent-1))
4100 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4101 sizeof(*token));
4102 if (token == (char *) NULL)
4103 break;
4104 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004105 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004106 token_info=AcquireTokenInfo();
4107 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4108 "\"",'\0',&breaker,&next,&quote);
4109 token_info=DestroyTokenInfo(token_info);
4110 if (status == 0)
4111 {
4112 const char
4113 *argv;
4114
4115 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004116 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4117 _exception);
anthony805a2d42011-09-25 08:25:12 +00004118 }
4119 token=DestroyString(token);
4120 break;
4121 }
4122 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004123 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4124 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004125 for (j=0; j < number_arguments; j++)
4126 arguments[j]=DestroyString(arguments[j]);
4127 arguments=(char **) RelinquishMagickMemory(arguments);
4128 break;
4129 }
anthonyebb73a22012-03-22 14:25:52 +00004130 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004131 }
4132 case 'r':
4133 {
anthonyafa3dfc2012-03-03 11:31:30 +00004134 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004135 {
anthony92c93bd2012-03-19 14:02:47 +00004136 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004137 break;
4138 }
anthonyafa3dfc2012-03-03 11:31:30 +00004139 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004140 {
anthony92c93bd2012-03-19 14:02:47 +00004141 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004142 break;
4143 }
anthonyebb73a22012-03-22 14:25:52 +00004144 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004145 }
4146 case 's':
4147 {
anthonyafa3dfc2012-03-03 11:31:30 +00004148 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004149 {
anthonycd358fc2012-04-16 13:59:03 +00004150 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004151 ssize_t
4152 offset;
4153
anthony7bcfe7f2012-03-30 14:01:22 +00004154 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004155 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004156 offset=(ssize_t) StringToLong(arg1);
anthonycd358fc2012-04-16 13:59:03 +00004157 new_images=SmushImages(_images,normal_op,offset,_exception);
4158 break;
4159 }
4160 if (LocaleCompare("subimage",option+1) == 0)
4161 {
4162 Image
4163 *base_image,
4164 *compare_image;
4165
4166 const char *
4167 value;
4168
4169 MetricType
4170 metric;
4171
4172 double
4173 similarity;
4174
4175 RectangleInfo
4176 offset;
4177
4178 base_image=GetImageFromList(_images,0);
4179 compare_image=GetImageFromList(_images,1);
4180
4181 /* Comparision Metric */
4182 metric=UndefinedMetric;
4183 value=GetImageOption(_image_info,"metric");
4184 if (value != (const char *) NULL)
4185 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4186 MagickFalse,value);
4187
4188 new_images=SimilarityImage(base_image,compare_image,metric,
4189 &offset,&similarity,_exception);
4190
4191 if ( new_images != (Image *)NULL ) {
4192 char
4193 result[MaxTextExtent];
4194
4195 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
4196 (void) SetImageProperty(new_images,"subimage:similarity",result,
4197 _exception);
4198 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4199 (long) offset.x);
4200 (void) SetImageProperty(new_images,"subimage:x",result,
4201 _exception);
4202 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4203 (long) offset.y);
4204 (void) SetImageProperty(new_images,"subimage:y",result,
4205 _exception);
4206 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
4207 (unsigned long) offset.width,(unsigned long) offset.height,
4208 (long) offset.x,(long) offset.y);
4209 (void) SetImageProperty(new_images,"subimage:offset",result,
4210 _exception);
4211 }
anthony805a2d42011-09-25 08:25:12 +00004212 break;
4213 }
anthony0ea037a2012-04-03 12:14:39 +00004214 if (LocaleCompare("swap",option+1) == 0) {
4215 Image
4216 *p,
4217 *q,
4218 *swap;
anthony805a2d42011-09-25 08:25:12 +00004219
anthony0ea037a2012-04-03 12:14:39 +00004220 ssize_t
4221 index,
4222 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004223
cristy6b36c942013-02-17 00:36:24 +00004224 index=(-1);
4225 swap_index=(-2);
anthony0ea037a2012-04-03 12:14:39 +00004226 if (IfNormalOp) {
4227 GeometryInfo
4228 geometry_info;
4229
4230 MagickStatusType
4231 flags;
4232
4233 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004234 flags=ParseGeometry(arg1,&geometry_info);
cristy90fbd1c2013-02-17 00:35:35 +00004235 if ((flags & RhoValue) == 0)
anthonyb1e21ed2012-04-20 12:43:12 +00004236 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004237 index=(ssize_t) geometry_info.rho;
4238 if ((flags & SigmaValue) != 0)
4239 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004240 }
anthony0ea037a2012-04-03 12:14:39 +00004241 p=GetImageFromList(_images,index);
4242 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004243 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4244 if (IfNormalOp)
4245 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4246 else
4247 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4248 }
anthony0ea037a2012-04-03 12:14:39 +00004249 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004250 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004251 swap=CloneImage(p,0,0,MagickTrue,_exception);
4252 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4253 ReplaceImageInList(&q,swap);
4254 _images=GetFirstImageInList(q);
4255 break;
4256 }
anthonyebb73a22012-03-22 14:25:52 +00004257 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004258 }
anthony805a2d42011-09-25 08:25:12 +00004259 default:
anthonyebb73a22012-03-22 14:25:52 +00004260 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004261 }
anthony964d28e2012-05-17 23:39:46 +00004262
4263 /* clean up percent escape interpreted strings */
4264 if (arg1 != arg1n )
4265 arg1=DestroyString((char *)arg1);
4266 if (arg2 != arg2n )
4267 arg2=DestroyString((char *)arg2);
4268
4269 /* if new image list generated, replace existing image list */
anthony31f1bf72012-01-30 12:37:22 +00004270 if (new_images == (Image *) NULL)
cristyfe831852013-02-12 14:56:07 +00004271 return(status);
anthony964d28e2012-05-17 23:39:46 +00004272 _images=DestroyImageList(_images);
anthony92c93bd2012-03-19 14:02:47 +00004273 _images=GetFirstImageInList(new_images);
cristyfe831852013-02-12 14:56:07 +00004274 return(status);
anthony31f1bf72012-01-30 12:37:22 +00004275
anthony92c93bd2012-03-19 14:02:47 +00004276#undef _image_info
4277#undef _images
4278#undef _exception
4279#undef _draw_info
4280#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004281#undef IfNormalOp
4282#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004283#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004284}
anthony43f425d2012-02-26 12:58:58 +00004285
4286/*
4287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4288% %
4289% %
4290% %
anthony964d28e2012-05-17 23:39:46 +00004291+ 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 +00004292% %
4293% %
4294% %
4295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4296%
anthony464f1c42012-04-22 08:51:01 +00004297% CLINoImageOperator() Applies operations that may not actually need images
anthony964d28e2012-05-17 23:39:46 +00004298% in an image list.
anthony43f425d2012-02-26 12:58:58 +00004299%
anthony4837ac22012-05-18 23:39:48 +00004300% The classic operators of this type is "-read", which actually creates
4301% images even when no images are present. Or image stack operators, which
4302% can be applied (push or pop) to an empty image list.
anthonyafa3dfc2012-03-03 11:31:30 +00004303%
anthony4837ac22012-05-18 23:39:48 +00004304% Note that these operators may involve other special 'option' prefix
4305% characters other than '-' or '+', namely parenthesis and braces.
anthony43f425d2012-02-26 12:58:58 +00004306%
anthony464f1c42012-04-22 08:51:01 +00004307% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004308%
anthony464f1c42012-04-22 08:51:01 +00004309% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4310% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004311%
4312% A description of each parameter follows:
4313%
anthonyc7994672012-11-17 05:33:27 +00004314% o cli_wand: the main CLI Wand to use. (sometimes not required)
anthony43f425d2012-02-26 12:58:58 +00004315%
4316% o option: The special option (with any switch char) to process
4317%
anthony464f1c42012-04-22 08:51:01 +00004318% o arg1 & arg2: Argument for option, if required
4319% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004320%
4321*/
cristyfe831852013-02-12 14:56:07 +00004322WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
4323 const char *option,const char *arg1,const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004324{
anthony4837ac22012-05-18 23:39:48 +00004325#if 0
4326 const char /* For percent escape interpretImageProperties() */
4327 *arg1,
4328 *arg2;
4329#endif
4330
anthony8226e722012-04-05 14:25:46 +00004331#define _image_info (cli_wand->wand.image_info)
4332#define _images (cli_wand->wand.images)
4333#define _exception (cli_wand->wand.exception)
4334#define IfNormalOp (*option=='-')
4335#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004336
4337 assert(cli_wand != (MagickCLI *) NULL);
4338 assert(cli_wand->signature == WandSignature);
4339 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +00004340 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00004341 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4342
anthonyde897b72012-04-27 00:16:17 +00004343#if 0
anthony4837ac22012-05-18 23:39:48 +00004344 Not able to be used as their may not be any images!
4345 Also the only option that may have arguments that can be percent escaped is
4346 "-clone".
anthony52bef752012-03-27 13:54:47 +00004347
anthony4837ac22012-05-18 23:39:48 +00004348#define _process_flags (cli_wand->process_flags)
4349#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
4350 /* Interpret Percent Escapes in Arguments - using first image */
4351 arg1 = arg1n;
4352 arg2 = arg2n;
4353 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4354 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4355 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4356 /* Interpret Percent escapes in argument 1 */
4357 if (arg1n != (char *) NULL) {
4358 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4359 if (arg1 == (char *) NULL) {
4360 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4361 arg1=arg1n; /* use the given argument as is */
4362 }
4363 }
4364 if (arg2n != (char *) NULL) {
4365 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4366 if (arg2 == (char *) NULL) {
4367 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4368 arg2=arg2n; /* use the given argument as is */
4369 }
4370 }
4371 }
4372#undef _process_flags
4373#undef _option_type
anthonyde897b72012-04-27 00:16:17 +00004374#endif
anthony4837ac22012-05-18 23:39:48 +00004375
4376 do { /* break to exit code */
4377 /*
4378 No-op options (ignore these)
4379 */
anthonyc7994672012-11-17 05:33:27 +00004380 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
anthony4837ac22012-05-18 23:39:48 +00004381 break;
4382 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4383 break;
anthonyc7994672012-11-17 05:33:27 +00004384 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4385 break;
4386 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
anthony4837ac22012-05-18 23:39:48 +00004387 break;
4388 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4389 break;
4390 /*
4391 Image Reading
4392 */
4393 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4394 ( LocaleCompare("--",option) == 0 ) ) {
4395 /* Do Glob filename Expansion for 'arg1' then read all images.
4396 *
4397 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4398 * (but attaching to the filenames in the generated argument list) any
4399 * [...] read modifiers that may be present.
4400 *
4401 * For example: It will expand '*.gif[20x20]' into a list such as
4402 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4403 *
4404 * NOTE: In IMv6 this was done globally across all images. This
4405 * meant you could include IM options in '@filename' lists, but you
4406 * could not include comments. Doing it only for image read makes
4407 * it far more secure.
4408 *
4409 * Note: arguments do not have percent escapes expanded for security
4410 * reasons.
4411 */
4412 int argc;
4413 char **argv;
4414 ssize_t i;
4415
4416 argc = 1;
4417 argv = (char **) &arg1;
4418
4419 /* Expand 'glob' expressions in the given filename.
4420 Expansion handles any 'coder:' prefix, or read modifiers attached
4421 to the filename, including them in the resulting expanded list.
4422 */
4423 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4424 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4425 option,GetExceptionMessage(errno));
4426
4427 /* loop over expanded filename list, and read then all in */
4428 for (i=0; i<argc; i++) {
4429 Image *
4430 new_images;
4431 if (IfMagickTrue(_image_info->ping))
4432 new_images=PingImages(_image_info,argv[i],_exception);
4433 else
4434 new_images=ReadImages(_image_info,argv[i],_exception);
4435 AppendImageToList(&_images, new_images);
4436 }
4437 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4438 break;
4439 }
4440 /*
4441 Image Writing
4442 Note: Writing a empty image list is valid in specific cases
4443 */
4444 if (LocaleCompare("write",option+1) == 0) {
4445 /* Note: arguments do not have percent escapes expanded */
4446 char
4447 key[MaxTextExtent];
4448
4449 Image
4450 *write_images;
4451
4452 ImageInfo
4453 *write_info;
4454
4455 /* Need images, unless a "null:" output coder is used */
4456 if ( cli_wand->wand.images == (Image *) NULL ) {
4457 if ( LocaleCompare(arg1,"null:") == 0 )
4458 break;
4459 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4460 }
4461
4462 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4463 (void) DeleteImageRegistry(key);
4464 write_images=_images;
4465 if (IfPlusOp)
4466 write_images=CloneImageList(_images,_exception);
4467 write_info=CloneImageInfo(_image_info);
4468 (void) WriteImages(write_info,write_images,arg1,_exception);
4469 write_info=DestroyImageInfo(write_info);
4470 if (IfPlusOp)
4471 write_images=DestroyImageList(write_images);
4472 break;
4473 }
4474 /*
4475 Parenthesis and Brace operations
4476 */
4477 if (LocaleCompare("(",option) == 0) {
4478 /* stack 'push' images */
4479 Stack
4480 *node;
4481
4482 size_t
4483 size;
4484
4485 size=0;
4486 node=cli_wand->image_list_stack;
4487 for ( ; node != (Stack *)NULL; node=node->next)
4488 size++;
4489 if ( size >= MAX_STACK_DEPTH )
4490 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4491 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4492 if (node == (Stack *) NULL)
4493 CLIWandExceptionBreak(ResourceLimitFatalError,
4494 "MemoryAllocationFailed",option);
4495 node->data = (void *)cli_wand->wand.images;
4496 cli_wand->wand.images = NewImageList();
4497 node->next = cli_wand->image_list_stack;
4498 cli_wand->image_list_stack = node;
4499
4500 /* handle respect-parenthesis */
4501 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4502 "respect-parenthesis"))))
4503 option="{"; /* fall-thru so as to push image settings too */
anthony52bef752012-03-27 13:54:47 +00004504 else
anthony4837ac22012-05-18 23:39:48 +00004505 break;
4506 /* fall thru to next if */
anthony52bef752012-03-27 13:54:47 +00004507 }
anthony4837ac22012-05-18 23:39:48 +00004508 if (LocaleCompare("{",option) == 0) {
4509 /* stack 'push' of image_info settings */
4510 Stack
4511 *node;
anthony8226e722012-04-05 14:25:46 +00004512
anthony4837ac22012-05-18 23:39:48 +00004513 size_t
4514 size;
anthony8226e722012-04-05 14:25:46 +00004515
anthony4837ac22012-05-18 23:39:48 +00004516 size=0;
4517 node=cli_wand->image_info_stack;
4518 for ( ; node != (Stack *)NULL; node=node->next)
4519 size++;
4520 if ( size >= MAX_STACK_DEPTH )
4521 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4522 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4523 if (node == (Stack *) NULL)
4524 CLIWandExceptionBreak(ResourceLimitFatalError,
4525 "MemoryAllocationFailed",option);
anthony8226e722012-04-05 14:25:46 +00004526
anthony4837ac22012-05-18 23:39:48 +00004527 node->data = (void *)cli_wand->wand.image_info;
4528 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4529 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4530 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4531 option);
4532 cli_wand->wand.image_info = (ImageInfo *)node->data;
4533 node = (Stack *)RelinquishMagickMemory(node);
4534 break;
4535 }
4536
4537 node->next = cli_wand->image_info_stack;
4538 cli_wand->image_info_stack = node;
4539
4540 break;
anthony8226e722012-04-05 14:25:46 +00004541 }
anthony4837ac22012-05-18 23:39:48 +00004542 if (LocaleCompare(")",option) == 0) {
4543 /* pop images from stack */
4544 Stack
4545 *node;
anthony8226e722012-04-05 14:25:46 +00004546
anthony4837ac22012-05-18 23:39:48 +00004547 node = (Stack *)cli_wand->image_list_stack;
4548 if ( node == (Stack *)NULL)
4549 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4550 cli_wand->image_list_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004551
anthony4837ac22012-05-18 23:39:48 +00004552 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4553 cli_wand->wand.images= (Image *)node->data;
4554 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004555
anthony4837ac22012-05-18 23:39:48 +00004556 /* handle respect-parenthesis - of the previous 'pushed' settings */
4557 node = cli_wand->image_info_stack;
4558 if ( node != (Stack *)NULL)
4559 {
4560 if (IfMagickTrue(IsStringTrue(GetImageOption(
4561 cli_wand->wand.image_info,"respect-parenthesis"))))
4562 option="}"; /* fall-thru so as to pop image settings too */
4563 else
4564 break;
4565 }
4566 else
4567 break;
4568 /* fall thru to next if */
4569 }
4570 if (LocaleCompare("}",option) == 0) {
4571 /* pop image_info settings from stack */
4572 Stack
4573 *node;
anthony43f425d2012-02-26 12:58:58 +00004574
anthony4837ac22012-05-18 23:39:48 +00004575 node = (Stack *)cli_wand->image_info_stack;
4576 if ( node == (Stack *)NULL)
4577 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4578 cli_wand->image_info_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004579
anthony4837ac22012-05-18 23:39:48 +00004580 (void) DestroyImageInfo(cli_wand->wand.image_info);
anthony43f425d2012-02-26 12:58:58 +00004581 cli_wand->wand.image_info = (ImageInfo *)node->data;
4582 node = (Stack *)RelinquishMagickMemory(node);
anthony4837ac22012-05-18 23:39:48 +00004583
4584 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4585 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4586 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4587
4588 break;
4589 }
anthonyc7994672012-11-17 05:33:27 +00004590 if (LocaleCompare("set",option+1) == 0)
4591 {
4592 /* Note: arguments are not percent escapes expanded yet */
4593 /* Some settings are applied to each image in memory in turn.
4594 While others only need to be applied once globally.
4595 */
4596 char
4597 *value;
4598
4599 if (LocaleNCompare(arg1,"registry:",9) == 0)
4600 {
4601 if (IfPlusOp)
4602 {
4603 (void) DeleteImageRegistry(arg1+9);
4604 break;
4605 }
4606 value=InterpretImageProperties(_image_info,_images,arg2,_exception);
4607 if (value == (char *) NULL)
4608 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4609 option);
4610 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
4611 value=DestroyString(value);
4612 break;
4613 }
4614 if (LocaleNCompare(arg1,"option:",7) == 0)
4615 {
4616 /* delete equivelent artifact from all images (if any) */
4617 MagickResetIterator(&cli_wand->wand);
4618 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4619 (void) DeleteImageArtifact(_images,arg1+7);
4620 MagickResetIterator(&cli_wand->wand);
4621 /* now set/delete the global option as needed */
4622 if (IfPlusOp) {
4623 (void) DeleteImageOption(_image_info,arg1+7);
4624 break;
4625 }
4626 value=InterpretImageProperties(_image_info,_images,arg2,_exception);
4627 if (value == (char *) NULL)
4628 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
cristy1a780952013-02-10 17:15:30 +00004629 option);
anthonyc7994672012-11-17 05:33:27 +00004630 (void) SetImageOption(_image_info,arg1+7,value);
4631 value=DestroyString(value);
4632 break;
4633 }
4634 if ( cli_wand->wand.images == (Image *) NULL )
4635 CLIWandExceptArgBreak(OptionError,"NoImagesFound",option,arg1);
4636 MagickResetIterator(&cli_wand->wand);
4637 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4638 {
cristyb3cc75d2013-02-05 14:47:44 +00004639 Image
4640 *next;
4641
anthonyc7994672012-11-17 05:33:27 +00004642 if (IfPlusOp) {
4643 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4644 (void) DeleteImageArtifact(_images,arg1+9);
4645 else if (LocaleNCompare(arg1,"property:",9) == 0)
4646 (void) DeleteImageProperty(_images,arg1+9);
4647 else
4648 (void) DeleteImageProperty(_images,arg1);
4649 break;
4650 }
cristyb3cc75d2013-02-05 14:47:44 +00004651 next=_images;
4652 for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
4653 {
4654 value=InterpretImageProperties(_image_info,next,arg2,_exception);
4655 if (value == (char *) NULL)
4656 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4657 option);
4658 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4659 (void) SetImageArtifact(next,arg1+9,value);
4660 else
4661 if (LocaleNCompare(arg1,"property:",9) == 0)
4662 (void) SetImageProperty(next,arg1+9,value,_exception);
4663 else
4664 (void) SetImageProperty(next,arg1,value,_exception);
4665 value=DestroyString(value);
4666 }
anthonyc7994672012-11-17 05:33:27 +00004667 break;
4668 }
4669 MagickResetIterator(&cli_wand->wand);
4670 break;
4671 }
anthony4837ac22012-05-18 23:39:48 +00004672 if (LocaleCompare("clone",option+1) == 0) {
4673 Image
4674 *new_images;
4675
4676 if (*option == '+')
4677 arg1="-1";
4678 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4679 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
4680 if ( cli_wand->image_list_stack == (Stack *)NULL)
4681 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4682 new_images = (Image *)cli_wand->image_list_stack->data;
4683 if (new_images == (Image *) NULL)
4684 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4685 new_images=CloneImages(new_images,arg1,_exception);
4686 if (new_images == (Image *) NULL)
4687 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4688 AppendImageToList(&_images,new_images);
4689 break;
4690 }
4691 /*
cristy422d5502012-12-22 22:20:57 +00004692 Informational Operations.
anthony4837ac22012-05-18 23:39:48 +00004693
anthonyc7994672012-11-17 05:33:27 +00004694 Note that these do not require either a cli-wand or images!
4695 Though currently a cli-wand much be provided regardless.
anthony4837ac22012-05-18 23:39:48 +00004696 */
cristy422d5502012-12-22 22:20:57 +00004697 if (LocaleCompare("version",option+1) == 0)
4698 {
cristy4f7a6132012-12-23 00:35:19 +00004699 ListMagickVersion(stdout);
cristy422d5502012-12-22 22:20:57 +00004700 break;
4701 }
anthony4837ac22012-05-18 23:39:48 +00004702 if (LocaleCompare("list",option+1) == 0) {
4703 /*
anthonyc7994672012-11-17 05:33:27 +00004704 FUTURE: This 'switch' should really be part of MagickCore
anthony4837ac22012-05-18 23:39:48 +00004705 */
4706 ssize_t
4707 list;
4708
4709 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4710 if ( list < 0 ) {
4711 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4712 break;
4713 }
4714 switch (list)
4715 {
4716 case MagickCoderOptions:
4717 {
4718 (void) ListCoderInfo((FILE *) NULL,_exception);
4719 break;
4720 }
4721 case MagickColorOptions:
4722 {
4723 (void) ListColorInfo((FILE *) NULL,_exception);
4724 break;
4725 }
4726 case MagickConfigureOptions:
4727 {
4728 (void) ListConfigureInfo((FILE *) NULL,_exception);
4729 break;
4730 }
4731 case MagickDelegateOptions:
4732 {
4733 (void) ListDelegateInfo((FILE *) NULL,_exception);
4734 break;
4735 }
4736 case MagickFontOptions:
4737 {
4738 (void) ListTypeInfo((FILE *) NULL,_exception);
4739 break;
4740 }
4741 case MagickFormatOptions:
4742 (void) ListMagickInfo((FILE *) NULL,_exception);
4743 break;
4744 case MagickLocaleOptions:
4745 (void) ListLocaleInfo((FILE *) NULL,_exception);
4746 break;
4747 case MagickLogOptions:
4748 (void) ListLogInfo((FILE *) NULL,_exception);
4749 break;
4750 case MagickMagicOptions:
4751 (void) ListMagicInfo((FILE *) NULL,_exception);
4752 break;
4753 case MagickMimeOptions:
4754 (void) ListMimeInfo((FILE *) NULL,_exception);
4755 break;
4756 case MagickModuleOptions:
4757 (void) ListModuleInfo((FILE *) NULL,_exception);
4758 break;
4759 case MagickPolicyOptions:
4760 (void) ListPolicyInfo((FILE *) NULL,_exception);
4761 break;
4762 case MagickResourceOptions:
4763 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4764 break;
4765 case MagickThresholdOptions:
4766 (void) ListThresholdMaps((FILE *) NULL,_exception);
4767 break;
4768 default:
4769 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4770 _exception);
4771 break;
4772 }
4773 break;
anthony43f425d2012-02-26 12:58:58 +00004774 }
anthony8226e722012-04-05 14:25:46 +00004775
anthony4837ac22012-05-18 23:39:48 +00004776 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony8226e722012-04-05 14:25:46 +00004777
anthony4837ac22012-05-18 23:39:48 +00004778 } while (0); /* break to exit code. */
anthony43f425d2012-02-26 12:58:58 +00004779
4780#if 0
anthony4837ac22012-05-18 23:39:48 +00004781 /* clean up percent escape interpreted strings */
4782 if (arg1 != arg1n )
4783 arg1=DestroyString((char *)arg1);
4784 if (arg2 != arg2n )
4785 arg2=DestroyString((char *)arg2);
anthony43f425d2012-02-26 12:58:58 +00004786#endif
4787
anthony8226e722012-04-05 14:25:46 +00004788#undef _image_info
4789#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004790#undef _exception
anthony8226e722012-04-05 14:25:46 +00004791#undef IfNormalOp
4792#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004793}
anthony464f1c42012-04-22 08:51:01 +00004794
4795/*
4796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4797% %
4798% %
4799% %
anthony964d28e2012-05-17 23:39:46 +00004800+ C L I O p t i o n %
anthony464f1c42012-04-22 08:51:01 +00004801% %
4802% %
4803% %
4804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4805%
4806% CLIOption() Processes the given option using the given CLI Magick Wand.
anthony964d28e2012-05-17 23:39:46 +00004807% The option arguments can be variable in number, though at this time no more
4808% that two is actually used by any option (this may change). Excess options
4809% are simply ignored.
anthony464f1c42012-04-22 08:51:01 +00004810%
4811% If the cli_wand->command pointer is non-null, then it is assumed that the
4812% option has already been search for up from the CommandOptions[] table in
anthony964d28e2012-05-17 23:39:46 +00004813% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
4814% routine will do the lookup instead. The pointer is reset afterward.
4815%
4816% This action allows the caller to lookup and pre-handle any 'special'
4817% options, (such as implicit reads) before calling this general option
4818% handler to deal with 'standard' command line options.
anthony464f1c42012-04-22 08:51:01 +00004819%
4820% The format of the CLIOption method is:
4821%
4822% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
4823%
4824% A description of each parameter follows:
4825%
4826% o cli_wand: the main CLI Wand to use.
4827%
4828% o option: The special option (with any switch char) to process
4829%
anthony964d28e2012-05-17 23:39:46 +00004830% o args: any required arguments for an option (variable number)
anthony464f1c42012-04-22 08:51:01 +00004831%
4832% Example Usage...
4833%
4834% CLIoption(cli_wand,"-read","rose:");
4835% CLIoption(cli_wand,"-virtual-pixel","transparent");
4836% CLIoption(cli_wand,"-distort","SRT:","30");
4837% CLIoption(cli_wand,"-write","rotated_rose.png");
4838%
4839*/
4840WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
4841{
4842 const char
4843 *arg1,
4844 *arg2;
4845
4846 CommandOptionFlags
4847 option_type;
4848
4849 assert(cli_wand != (MagickCLI *) NULL);
4850 assert(cli_wand->signature == WandSignature);
4851 assert(cli_wand->wand.signature == WandSignature);
4852 if (IfMagickTrue(cli_wand->wand.debug))
4853 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4854
anthony964d28e2012-05-17 23:39:46 +00004855 do { /* Break Code Block for error handling */
4856
4857 /* get information about option */
4858 if ( cli_wand->command == (const OptionInfo *) NULL )
4859 cli_wand->command = GetCommandOptionInfo(option);
anthony464f1c42012-04-22 08:51:01 +00004860#if 0
anthony964d28e2012-05-17 23:39:46 +00004861 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
4862 option, cli_wand->command->mnemonic );
anthony464f1c42012-04-22 08:51:01 +00004863#endif
anthony964d28e2012-05-17 23:39:46 +00004864 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthony464f1c42012-04-22 08:51:01 +00004865
anthony964d28e2012-05-17 23:39:46 +00004866 if ( option_type == UndefinedOptionFlag )
4867 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
anthony464f1c42012-04-22 08:51:01 +00004868
anthony964d28e2012-05-17 23:39:46 +00004869 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
anthony464f1c42012-04-22 08:51:01 +00004870
anthony964d28e2012-05-17 23:39:46 +00004871 /* depreciated options */
4872 if ( (option_type & DeprecateOptionFlag) != 0 )
4873 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
anthony464f1c42012-04-22 08:51:01 +00004874
anthony964d28e2012-05-17 23:39:46 +00004875 /* options that this module does not handle */
4876 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
4877 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
anthony464f1c42012-04-22 08:51:01 +00004878
anthony964d28e2012-05-17 23:39:46 +00004879 /* Get argument strings from VarArgs
4880 How can you determine arguments is enough was supplied? */
4881 { size_t
4882 count = cli_wand->command->type;
anthony464f1c42012-04-22 08:51:01 +00004883
anthony964d28e2012-05-17 23:39:46 +00004884 va_list
4885 operands;
anthony464f1c42012-04-22 08:51:01 +00004886
anthony964d28e2012-05-17 23:39:46 +00004887 va_start(operands,option);
anthony464f1c42012-04-22 08:51:01 +00004888
anthony964d28e2012-05-17 23:39:46 +00004889 arg1=arg2=NULL;
4890 if ( count >= 1 )
4891 arg1=(const char *) va_arg(operands, const char *);
4892 if ( count >= 2 )
4893 arg2=(const char *) va_arg(operands, const char *);
anthony464f1c42012-04-22 08:51:01 +00004894
anthony964d28e2012-05-17 23:39:46 +00004895 va_end(operands);
anthony464f1c42012-04-22 08:51:01 +00004896
anthony52cb3df2012-04-24 03:29:32 +00004897#if 0
anthony964d28e2012-05-17 23:39:46 +00004898 (void) FormatLocaleFile(stderr,
4899 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
4900 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00004901#endif
anthony964d28e2012-05-17 23:39:46 +00004902 }
4903
4904 /*
4905 Call the appropriate option handler
4906 */
4907
4908 /* FUTURE: this is temporary - get 'settings' to handle distribution of
4909 settings to images attributes,proprieties,artifacts */
4910 if ( cli_wand->wand.images != (Image *)NULL )
4911 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4912 cli_wand->wand.exception);
4913
4914 if ( (option_type & SettingOptionFlags) != 0 ) {
4915 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
4916 // FUTURE: Sync Specific Settings into Image Properities (not global)
4917 }
4918
4919 /* Operators that do not need images - read, write, stack, clone */
4920 if ( (option_type & NoImageOperatorFlag) != 0)
4921 CLINoImageOperator(cli_wand, option, arg1, arg2);
4922
4923 /* FUTURE: The not a setting part below is a temporary hack due to
4924 * some options being both a Setting and a Simple operator.
4925 * Specifically -monitor, -depth, and -colorspace */
4926 if ( cli_wand->wand.images == (Image *)NULL )
4927 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
4928 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
4929 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
4930
4931 /* Operators work on single images, and needs a loop over the images */
4932 if ( (option_type & SimpleOperatorFlag) != 0)
4933 CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
4934
4935 /* Operators that work on the image list as a whole */
4936 if ( (option_type & ListOperatorFlag) != 0 )
4937 CLIListOperatorImages(cli_wand, option, arg1, arg2);
4938
4939 } while (0); /* end Break code block */
anthony464f1c42012-04-22 08:51:01 +00004940
4941 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
anthony464f1c42012-04-22 08:51:01 +00004942}