blob: 9821315c87614442af8d08d03e3274c1ae2b0d90 [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% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 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"
60
61/*
62 Define declarations.
63*/
anthonyafa3dfc2012-03-03 11:31:30 +000064#define USE_WAND_METHODS 0
65#define MAX_STACK_DEPTH 32
66#define UNDEFINED_COMPRESSION_QUALITY 0UL
67
anthonyb1d483a2012-04-14 12:53:56 +000068/* FUTURE: why is this default so specific? */
69#define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
70
anthony805a2d42011-09-25 08:25:12 +000071/*
72 Constant declaration. (temporary exports)
73*/
74static const char
75 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000076 BorderColor[] = "#dfdfdf", /* sRGB gray */
77 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony22de2722012-04-19 14:43:00 +000078
79/* For Debugging Geometry Input */
80#define ReportGeometry(flags,info) \
81 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
82 flags, info.rho, info.sigma, info.xi, info.psi )
anthony805a2d42011-09-25 08:25:12 +000083
84/*
85** Function to report on the progress of image operations
86*/
87static MagickBooleanType MonitorProgress(const char *text,
88 const MagickOffsetType offset,const MagickSizeType extent,
anthony43f425d2012-02-26 12:58:58 +000089 void *wand_unused(cli_wandent_data))
anthony805a2d42011-09-25 08:25:12 +000090{
91 char
92 message[MaxTextExtent],
93 tag[MaxTextExtent];
94
95 const char
96 *locale_message;
97
98 register char
99 *p;
100
101 if (extent < 2)
102 return(MagickTrue);
103 (void) CopyMagickMemory(tag,text,MaxTextExtent);
104 p=strrchr(tag,'/');
105 if (p != (char *) NULL)
106 *p='\0';
107 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
108 locale_message=GetLocaleMessage(message);
109 if (locale_message == message)
110 locale_message=tag;
111 if (p == (char *) NULL)
112 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
113 locale_message,(long) offset,(unsigned long) extent,(long)
114 (100L*offset/(extent-1)));
115 else
116 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
117 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
118 (100L*offset/(extent-1)));
119 if (offset == (MagickOffsetType) (extent-1))
120 (void) FormatLocaleFile(stderr,"\n");
121 (void) fflush(stderr);
122 return(MagickTrue);
123}
124
125/*
126** GetImageCache() will read an image into a image cache if not already
127** present then return the image that is in the cache under that filename.
128*/
129static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
130 ExceptionInfo *exception)
131{
132 char
133 key[MaxTextExtent];
134
135 ExceptionInfo
136 *sans_exception;
137
138 Image
139 *image;
140
141 ImageInfo
142 *read_info;
143
144 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
145 sans_exception=AcquireExceptionInfo();
146 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
147 sans_exception=DestroyExceptionInfo(sans_exception);
148 if (image != (Image *) NULL)
149 return(image);
150 read_info=CloneImageInfo(image_info);
151 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
152 image=ReadImage(read_info,exception);
153 read_info=DestroyImageInfo(read_info);
154 if (image != (Image *) NULL)
155 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
156 return(image);
157}
158
anthony756cd0d2012-04-08 12:41:44 +0000159/*
anthonya89dd172011-10-04 13:29:35 +0000160 SparseColorOption() parse the complex -sparse-color argument into an
161 an array of floating point values than call SparseColorImage().
162 Argument is a complex mix of floating-point pixel coodinates, and color
163 specifications (or direct floating point numbers). The number of floats
164 needed to represent a color varies depending on teh current channel
165 setting.
anthony43f425d2012-02-26 12:58:58 +0000166
167 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000168*/
169static Image *SparseColorOption(const Image *image,
170 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000171 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000172{
173 char
174 token[MaxTextExtent];
175
176 const char
177 *p;
178
179 double
180 *sparse_arguments;
181
182 Image
183 *sparse_image;
184
185 PixelInfo
186 color;
187
188 MagickBooleanType
189 error;
190
191 register size_t
192 x;
193
194 size_t
195 number_arguments,
196 number_colors;
197
198 assert(image != (Image *) NULL);
199 assert(image->signature == MagickSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000200 if (IfMagickTrue(image->debug))
anthony805a2d42011-09-25 08:25:12 +0000201 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
202 assert(exception != (ExceptionInfo *) NULL);
203 assert(exception->signature == MagickSignature);
204 /*
anthonyb1d483a2012-04-14 12:53:56 +0000205 Limit channels according to image
206 add up number of values needed per color.
anthony805a2d42011-09-25 08:25:12 +0000207 */
208 number_colors=0;
209 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
210 number_colors++;
211 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
212 number_colors++;
213 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
214 number_colors++;
215 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
216 (image->colorspace == CMYKColorspace))
217 number_colors++;
218 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000219 IfMagickTrue(image->matte))
anthony805a2d42011-09-25 08:25:12 +0000220 number_colors++;
221
222 /*
223 Read string, to determine number of arguments needed,
224 */
225 p=arguments;
226 x=0;
227 while( *p != '\0' )
228 {
229 GetMagickToken(p,&p,token);
230 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000231 if ( isalpha((int) token[0]) || token[0] == '#' )
232 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000233 else
anthony805a2d42011-09-25 08:25:12 +0000234 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000235 }
anthony31f1bf72012-01-30 12:37:22 +0000236 /* control points and color values */
anthony7bcfe7f2012-03-30 14:01:22 +0000237 error = IsMagickTrue( x % (2+number_colors) );
anthony31f1bf72012-01-30 12:37:22 +0000238 number_arguments=x;
anthony7bcfe7f2012-03-30 14:01:22 +0000239 if ( IfMagickTrue(error) ) {
anthony805a2d42011-09-25 08:25:12 +0000240 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000241 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000242 "Invalid number of Arguments");
243 return( (Image *)NULL);
244 }
245
246 /* Allocate and fill in the floating point arguments */
247 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
248 sizeof(*sparse_arguments));
249 if (sparse_arguments == (double *) NULL) {
250 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
251 "MemoryAllocationFailed","%s","SparseColorOption");
252 return( (Image *)NULL);
253 }
254 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
255 sizeof(*sparse_arguments));
256 p=arguments;
257 x=0;
258 while( *p != '\0' && x < number_arguments ) {
259 /* X coordinate */
260 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
261 if ( token[0] == '\0' ) break;
262 if ( isalpha((int) token[0]) || token[0] == '#' ) {
263 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000264 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000265 "Color found, instead of X-coord");
266 error = MagickTrue;
267 break;
268 }
cristydbdd0e32011-11-04 23:29:40 +0000269 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000270 /* Y coordinate */
271 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
272 if ( token[0] == '\0' ) break;
273 if ( isalpha((int) token[0]) || token[0] == '#' ) {
274 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000275 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000276 "Color found, instead of Y-coord");
277 error = MagickTrue;
278 break;
279 }
cristydbdd0e32011-11-04 23:29:40 +0000280 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000281 /* color name or function given in string argument */
282 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
283 if ( token[0] == '\0' ) break;
284 if ( isalpha((int) token[0]) || token[0] == '#' ) {
285 /* Color string given */
286 (void) QueryColorCompliance(token,AllCompliance,&color,
287 exception);
288 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
289 sparse_arguments[x++] = QuantumScale*color.red;
290 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
291 sparse_arguments[x++] = QuantumScale*color.green;
292 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
293 sparse_arguments[x++] = QuantumScale*color.blue;
294 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
295 (image->colorspace == CMYKColorspace))
296 sparse_arguments[x++] = QuantumScale*color.black;
297 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000298 IfMagickTrue(image->matte))
anthony31f1bf72012-01-30 12:37:22 +0000299 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000300 }
anthony31f1bf72012-01-30 12:37:22 +0000301 else {
302 /* Colors given as a set of floating point values - experimental */
303 /* NB: token contains the first floating point value to use! */
304 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
305 {
306 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
307 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
308 break;
309 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
310 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000311 }
anthony31f1bf72012-01-30 12:37:22 +0000312 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
313 {
314 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
315 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
316 break;
317 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
318 token[0] = ','; /* used this token - get another */
319 }
320 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
321 {
322 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324 break;
325 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
326 token[0] = ','; /* used this token - get another */
327 }
328 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
329 (image->colorspace == CMYKColorspace))
330 {
331 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
332 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
333 break;
334 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
335 token[0] = ','; /* used this token - get another */
336 }
337 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000338 IfMagickTrue(image->matte))
anthony31f1bf72012-01-30 12:37:22 +0000339 {
340 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
341 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
342 break;
343 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
344 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000345 }
346 }
347 }
348 if ( number_arguments != x && !error ) {
349 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000350 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000351 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
352 return( (Image *)NULL);
353 }
354 if ( error )
355 return( (Image *)NULL);
356
anthony31f1bf72012-01-30 12:37:22 +0000357 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000358 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
359 exception);
360 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
361 return( sparse_image );
362}
363
364/*
365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366% %
367% %
368% %
anthony464f1c42012-04-22 08:51:01 +0000369% C L I S e t t i n g O p t i o n I n f o %
anthony43f425d2012-02-26 12:58:58 +0000370% %
371% %
372% %
373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374%
375% CLISettingOptionInfo() applies a single settings option into a CLI wand
376% holding the image_info, draw_info, quantize_info structures that will be
377% used when processing the images.
378%
379% These options do no require images to be present in the CLI wand for them
380% to be able to be set, in which case they will generally be applied to image
381% that are read in later
anthony80c37752012-01-16 01:03:11 +0000382%
383% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000384% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000385%
anthony2052d272012-02-28 12:48:29 +0000386% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000387%
anthonyafa3dfc2012-03-03 11:31:30 +0000388% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000389% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000390%
391% A description of each parameter follows:
392%
anthony43f425d2012-02-26 12:58:58 +0000393% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000394%
anthonydcf510d2011-10-30 13:51:40 +0000395% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000396%
anthonye5fcd362012-04-09 04:02:09 +0000397% o arg1, arg2: optional argument strings to the operation
398% arg2 is currently only used by "-limit"
anthonydcf510d2011-10-30 13:51:40 +0000399%
anthony805a2d42011-09-25 08:25:12 +0000400*/
anthonyafa3dfc2012-03-03 11:31:30 +0000401WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000402 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000403{
anthony30b912a2012-03-22 01:20:28 +0000404 ssize_t
405 parse; /* option argument parsing (string to value table lookup) */
406
anthony43f425d2012-02-26 12:58:58 +0000407 assert(cli_wand != (MagickCLI *) NULL);
408 assert(cli_wand->signature == WandSignature);
409 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000410 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +0000411 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000412
anthony2e4501b2012-03-30 04:41:54 +0000413#define _image_info (cli_wand->wand.image_info)
414#define _exception (cli_wand->wand.exception)
415#define _draw_info (cli_wand->draw_info)
416#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000417#define IfSetOption (*option=='-')
anthony7bcfe7f2012-03-30 14:01:22 +0000418#define ArgBoolean IsMagickTrue(IfSetOption)
419#define ArgBooleanNot IsMagickFalse(IfSetOption)
anthony24aa8822012-03-11 00:56:06 +0000420#define ArgBooleanString (IfSetOption?"true":"false")
421#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000422
anthony4837ac22012-05-18 23:39:48 +0000423#if 0
424Setting are not directly involved with images, so can not
425interpret Percent Escapes in Arguments, At least not yet */
426
427#define _process_flags (cli_wand->process_flags)
428#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
429 /* Interpret Percent Escapes in Arguments - using first image */
430 arg1 = arg1n,
431 arg2 = arg2n;
432 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
433 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
434 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
435 /* Interpret Percent escapes in argument 1 */
436 if (arg1n != (char *) NULL) {
437 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
438 if (arg1 == (char *) NULL) {
439 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
440 arg1=arg1n; /* use the given argument as is */
441 }
442 }
443 if (arg2n != (char *) NULL) {
444 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
445 if (arg2 == (char *) NULL) {
446 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
447 arg2=arg2n; /* use the given argument as is */
448 }
449 }
450 }
451#undef _process_flags
452#undef _option_type
453#endif
454
anthonyafa3dfc2012-03-03 11:31:30 +0000455 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000456 {
457 case 'a':
458 {
anthonyafa3dfc2012-03-03 11:31:30 +0000459 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000460 {
anthony92c93bd2012-03-19 14:02:47 +0000461 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000462 break;
463 }
anthonyafa3dfc2012-03-03 11:31:30 +0000464 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000465 {
anthony464f1c42012-04-22 08:51:01 +0000466 CLIWandWarnReplaced("-draw 'affine ...'");
anthony74b1cfc2011-10-06 12:44:16 +0000467 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000468 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000469 else
anthony92c93bd2012-03-19 14:02:47 +0000470 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000471 break;
472 }
anthonyafa3dfc2012-03-03 11:31:30 +0000473 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000474 {
anthony92c93bd2012-03-19 14:02:47 +0000475 _image_info->antialias =
476 _draw_info->stroke_antialias =
477 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000478 break;
479 }
anthony31f1bf72012-01-30 12:37:22 +0000480 if (LocaleCompare("attenuate",option+1) == 0)
481 {
anthony7bcfe7f2012-03-30 14:01:22 +0000482 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +0000483 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
484 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000485 break;
486 }
anthonyafa3dfc2012-03-03 11:31:30 +0000487 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000488 {
anthony92c93bd2012-03-19 14:02:47 +0000489 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000490 break;
491 }
anthonyebb73a22012-03-22 14:25:52 +0000492 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000493 }
494 case 'b':
495 {
anthonyafa3dfc2012-03-03 11:31:30 +0000496 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000497 {
anthony92c93bd2012-03-19 14:02:47 +0000498 /* FUTURE: both _image_info attribute & ImageOption in use!
499 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000500 SyncImageSettings() used to set per-image attribute.
501
anthony92c93bd2012-03-19 14:02:47 +0000502 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000503 we should fall back to per-image background_color
504
505 At this time -background will 'wipe out' the per-image
506 background color!
507
508 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000509 */
anthony92c93bd2012-03-19 14:02:47 +0000510 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000511 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000512 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000513 break;
514 }
anthonyafa3dfc2012-03-03 11:31:30 +0000515 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000516 {
anthony52bef752012-03-27 13:54:47 +0000517 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000518 as it is actually rarely used except in direct convolve operations
519 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000520
521 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000522 */
anthony7bcfe7f2012-03-30 14:01:22 +0000523 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000524 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000525 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000526 break;
527 }
anthonyafa3dfc2012-03-03 11:31:30 +0000528 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000529 {
anthony72feaa62012-01-17 06:46:23 +0000530 /* Used as a image chromaticity setting
531 SyncImageSettings() used to set per-image attribute.
532 */
anthony92c93bd2012-03-19 14:02:47 +0000533 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000534 break;
535 }
anthonyafa3dfc2012-03-03 11:31:30 +0000536 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000537 {
anthonyafbaed72011-10-26 12:05:04 +0000538 /* Image chromaticity X,Y NB: Y=X if Y not defined
539 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000540 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000541 */
anthonyf42014d2012-03-25 09:53:06 +0000542 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000543 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000544 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000545 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000546 break;
547 }
anthonyafa3dfc2012-03-03 11:31:30 +0000548 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000549 {
anthony92c93bd2012-03-19 14:02:47 +0000550 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000551 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000552 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000553 */
anthony74b1cfc2011-10-06 12:44:16 +0000554 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000555 {
anthony92c93bd2012-03-19 14:02:47 +0000556 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000557 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000558 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000559 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000560 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000561 break;
562 }
anthony92c93bd2012-03-19 14:02:47 +0000563 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000564 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000565 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000566 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000567 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000568 break;
569 }
anthonyafa3dfc2012-03-03 11:31:30 +0000570 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000571 {
anthony464f1c42012-04-22 08:51:01 +0000572 CLIWandWarnReplaced("-undercolor");
anthony975a8d72012-04-12 13:54:36 +0000573 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
anthonyfd706f92012-01-19 04:22:02 +0000574 break;
anthony805a2d42011-09-25 08:25:12 +0000575 }
anthonyebb73a22012-03-22 14:25:52 +0000576 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000577 }
578 case 'c':
579 {
anthonyafa3dfc2012-03-03 11:31:30 +0000580 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000581 {
582 MagickSizeType
583 limit;
584
anthony7bcfe7f2012-03-30 14:01:22 +0000585 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000586 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000587 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000588 if (LocaleCompare("unlimited",arg1) != 0)
589 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000590 (void) SetMagickResourceLimit(MemoryResource,limit);
591 (void) SetMagickResourceLimit(MapResource,2*limit);
592 break;
593 }
anthonyafa3dfc2012-03-03 11:31:30 +0000594 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000595 {
anthony92c93bd2012-03-19 14:02:47 +0000596 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000597 break;
598 }
anthonyafa3dfc2012-03-03 11:31:30 +0000599 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000600 {
anthony30b912a2012-03-22 01:20:28 +0000601 arg1=ArgOption("default");
602 parse=ParseChannelOption(arg1);
603 if (parse < 0)
604 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
605 option,arg1);
606 _image_info->channel=(ChannelType) parse;
607 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000608 break;
609 }
anthonyafa3dfc2012-03-03 11:31:30 +0000610 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000611 {
anthonyafbaed72011-10-26 12:05:04 +0000612 /* Setting used for new images via AquireImage()
613 But also used as a SimpleImageOperator
614 Undefined colorspace means don't modify images on
615 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000616 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
617 ArgOption("undefined"));
618 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000619 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
620 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000621 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000622 break;
623 }
anthonyafa3dfc2012-03-03 11:31:30 +0000624 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000625 {
anthony92c93bd2012-03-19 14:02:47 +0000626 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000627 break;
628 }
anthonyafa3dfc2012-03-03 11:31:30 +0000629 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000630 {
anthony92c93bd2012-03-19 14:02:47 +0000631 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000632 SyncImageSettings() used to set per-image attribute. - REMOVE
633
anthonyafbaed72011-10-26 12:05:04 +0000634 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000635 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000636 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000637 */
anthonyebb73a22012-03-22 14:25:52 +0000638 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
639 ArgOption("undefined"));
640 if (parse < 0)
641 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
642 option,arg1);
643 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000644 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000645 break;
646 }
anthonyafa3dfc2012-03-03 11:31:30 +0000647 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000648 {
anthony92c93bd2012-03-19 14:02:47 +0000649 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000650 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000651 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000652
anthony92c93bd2012-03-19 14:02:47 +0000653 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000654 however the image attribute (for save) is set from the
655 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000656
657 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000658 */
anthonyebb73a22012-03-22 14:25:52 +0000659 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
660 ArgOption("undefined"));
661 if (parse < 0)
662 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
663 option,arg1);
664 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000665 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000666 break;
667 }
anthonyebb73a22012-03-22 14:25:52 +0000668 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000669 }
670 case 'd':
671 {
anthonyafa3dfc2012-03-03 11:31:30 +0000672 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000673 {
anthony72feaa62012-01-17 06:46:23 +0000674 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000675 arg1=ArgOption("none");
676 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
677 if (parse < 0)
678 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
679 option,arg1);
680 (void) SetLogEventMask(arg1);
681 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000682 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000683 break;
684 }
anthonyafa3dfc2012-03-03 11:31:30 +0000685 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000686 {
anthony24aa8822012-03-11 00:56:06 +0000687 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000688 {
anthony5f867ae2011-10-09 10:28:34 +0000689 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000690 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000691 else
anthony24aa8822012-03-11 00:56:06 +0000692 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000693 break;
694 }
anthony24aa8822012-03-11 00:56:06 +0000695 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000696 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000697 (void) DefineImageOption(_image_info,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +0000698 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000699 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000700 break;
701 }
anthonyafa3dfc2012-03-03 11:31:30 +0000702 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000703 {
anthonyafbaed72011-10-26 12:05:04 +0000704 /* Only used for new images via AcquireImage()
705 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000706 */
anthonyebb73a22012-03-22 14:25:52 +0000707 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000708 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000709 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
710 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000711 break;
712 }
anthonyafa3dfc2012-03-03 11:31:30 +0000713 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000714 {
anthony92c93bd2012-03-19 14:02:47 +0000715 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000716 Basically as density can be in a XxY form!
717
718 SyncImageSettings() used to set per-image attribute.
719 */
anthony7bcfe7f2012-03-30 14:01:22 +0000720 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000721 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000722 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
723 (void) CloneString(&_image_info->density,ArgOption(NULL));
724 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000725 break;
726 }
anthonyafa3dfc2012-03-03 11:31:30 +0000727 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000728 {
anthony72feaa62012-01-17 06:46:23 +0000729 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
730 SyncImageSettings() used to set per-image attribute.
731 */
anthony7bcfe7f2012-03-30 14:01:22 +0000732 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000733 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000734 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000735 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000736 break;
737 }
anthonyafa3dfc2012-03-03 11:31:30 +0000738 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000739 {
anthony92c93bd2012-03-19 14:02:47 +0000740 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000741 arg1=ArgOption("undefined");
742 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
743 if (parse < 0)
744 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
745 option,arg1);
746 _draw_info->direction=(DirectionType) parse;
747 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000748 break;
749 }
anthonyafa3dfc2012-03-03 11:31:30 +0000750 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000751 {
anthony92c93bd2012-03-19 14:02:47 +0000752 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
753 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000754 break;
755 }
anthonyafa3dfc2012-03-03 11:31:30 +0000756 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000757 {
anthony72feaa62012-01-17 06:46:23 +0000758 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000759 arg1=ArgOption("undefined");
760 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
761 if (parse < 0)
762 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
763 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000764 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000765 break;
766 }
anthonyb1d483a2012-04-14 12:53:56 +0000767 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
768 {
769 /* FUTURE: this is only used by CompareImages() which is used
770 only by the "compare" CLI program at this time. */
771 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
772 if (IfMagickFalse(IsGeometry(arg1)))
773 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
774 (void) SetImageOption(_image_info,option+1,arg1);
775 break;
776 }
anthonyafa3dfc2012-03-03 11:31:30 +0000777 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000778 {
anthony92c93bd2012-03-19 14:02:47 +0000779 /* _image_info attr (on/off), _quantize_info attr (on/off)
780 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000781 FUTURE: merge the duality of the dithering options
782 */
cristycbda6112012-05-27 20:57:16 +0000783 _image_info->dither = ArgBoolean;
anthony92c93bd2012-03-19 14:02:47 +0000784 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
785 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
cristycbda6112012-05-27 20:57:16 +0000786 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000787 if (_quantize_info->dither_method == NoDitherMethod)
cristycbda6112012-05-27 20:57:16 +0000788 _image_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000789 break;
790 }
anthonyebb73a22012-03-22 14:25:52 +0000791 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000792 }
793 case 'e':
794 {
anthonyafa3dfc2012-03-03 11:31:30 +0000795 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000796 {
anthony92c93bd2012-03-19 14:02:47 +0000797 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
798 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000799 break;
800 }
anthonyafa3dfc2012-03-03 11:31:30 +0000801 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000802 {
anthony92c93bd2012-03-19 14:02:47 +0000803 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000804 arg1 = ArgOption("undefined");
805 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
806 if (parse < 0)
807 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
808 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000809 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000810 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000811 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000812 break;
813 }
anthonyafa3dfc2012-03-03 11:31:30 +0000814 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000815 {
anthony92c93bd2012-03-19 14:02:47 +0000816 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000817 break;
818 }
anthonyebb73a22012-03-22 14:25:52 +0000819 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000820 }
821 case 'f':
822 {
anthonyafa3dfc2012-03-03 11:31:30 +0000823 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000824 {
anthony92c93bd2012-03-19 14:02:47 +0000825 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000826 break;
827 }
anthonyafa3dfc2012-03-03 11:31:30 +0000828 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000829 {
anthony92c93bd2012-03-19 14:02:47 +0000830 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000831 The original fill color is preserved if a fill-pattern is given.
832 That way it does not effect other operations that directly using
833 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000834 */
anthony72feaa62012-01-17 06:46:23 +0000835 MagickBooleanType
836 status;
anthony6dc09cd2011-10-12 08:56:49 +0000837
838 ExceptionInfo
839 *sans;
840
anthonyfd706f92012-01-19 04:22:02 +0000841 PixelInfo
842 color;
843
anthony2a0ec8c2012-03-24 04:35:56 +0000844 arg1 = ArgOption("none"); /* +fill turns it off! */
845 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000846 if (_draw_info->fill_pattern != (Image *) NULL)
847 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000848
849 /* is it a color or a image? -- ignore exceptions */
850 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +0000851 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000852 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000853
anthony7bcfe7f2012-03-30 14:01:22 +0000854 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +0000855 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000856 else
anthony92c93bd2012-03-19 14:02:47 +0000857 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000858 break;
859 }
anthonyafa3dfc2012-03-03 11:31:30 +0000860 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000861 {
anthony72feaa62012-01-17 06:46:23 +0000862 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +0000863 arg1 = ArgOption("undefined");
864 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
865 if (parse < 0)
866 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
867 option,arg1);
868 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000869 break;
870 }
anthonyafa3dfc2012-03-03 11:31:30 +0000871 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000872 {
anthony92c93bd2012-03-19 14:02:47 +0000873 (void) CloneString(&_draw_info->font,ArgOption(NULL));
874 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000875 break;
876 }
anthonyafa3dfc2012-03-03 11:31:30 +0000877 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000878 {
anthonydcf510d2011-10-30 13:51:40 +0000879 /* FUTURE: why the ping test, you could set ping after this! */
880 /*
anthony805a2d42011-09-25 08:25:12 +0000881 register const char
882 *q;
883
anthony24aa8822012-03-11 00:56:06 +0000884 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000885 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +0000886 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000887 */
anthony92c93bd2012-03-19 14:02:47 +0000888 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000889 break;
890 }
anthonyafa3dfc2012-03-03 11:31:30 +0000891 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000892 {
anthony72feaa62012-01-17 06:46:23 +0000893 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000894 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000895 SyncImageSettings() used to set per-image attribute.
896
anthony2a0ec8c2012-03-24 04:35:56 +0000897 FUTURE: Can't find anything else using _image_info->fuzz directly!
898 remove direct sttribute from image_info
anthony6613bf32011-10-15 07:24:44 +0000899 */
anthony2a0ec8c2012-03-24 04:35:56 +0000900 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000901 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +0000902 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
903 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +0000904 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +0000905 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000906 break;
907 }
anthonyebb73a22012-03-22 14:25:52 +0000908 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000909 }
910 case 'g':
911 {
anthonyafa3dfc2012-03-03 11:31:30 +0000912 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000913 {
anthony72feaa62012-01-17 06:46:23 +0000914 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000915 arg1 = ArgOption("none");
916 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
917 if (parse < 0)
918 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
919 option,arg1);
anthonyfe1aa782012-03-24 13:43:04 +0000920 _draw_info->gravity=(GravityType) parse;
anthonye8490972012-04-03 13:16:01 +0000921 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000922 break;
923 }
anthonyafa3dfc2012-03-03 11:31:30 +0000924 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000925 {
anthonydcf510d2011-10-30 13:51:40 +0000926 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000927 SyncImageSettings() used to set per-image attribute.
928 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000929 */
anthonyf42014d2012-03-25 09:53:06 +0000930 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000931 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000932 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000933 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000934 break;
935 }
anthonyebb73a22012-03-22 14:25:52 +0000936 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000937 }
anthonyb1d483a2012-04-14 12:53:56 +0000938 case 'h':
939 {
940 if (LocaleCompare("highlight-color",option+1) == 0)
941 {
942 /* FUTURE: this is only used by CompareImages() which is used
943 only by the "compare" CLI program at this time. */
944 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
945 break;
946 }
947 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
948 }
anthony805a2d42011-09-25 08:25:12 +0000949 case 'i':
950 {
anthonyafa3dfc2012-03-03 11:31:30 +0000951 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000952 {
anthony72feaa62012-01-17 06:46:23 +0000953 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000954 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000955 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000956 */
anthonyfe1aa782012-03-24 13:43:04 +0000957 arg1 = ArgOption("indefined");
958 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
959 if (parse < 0)
960 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
961 option,arg1);
962 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000963 break;
964 }
anthonyafa3dfc2012-03-03 11:31:30 +0000965 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000966 {
anthony92c93bd2012-03-19 14:02:47 +0000967 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +0000968 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000969 */
anthonyfe1aa782012-03-24 13:43:04 +0000970 arg1 = ArgOption("undefined");
971 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
972 if (parse < 0)
973 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
974 option,arg1);
975 _image_info->interlace=(InterlaceType) parse;
976 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000977 break;
978 }
anthonyafa3dfc2012-03-03 11:31:30 +0000979 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000980 {
anthony7bcfe7f2012-03-30 14:01:22 +0000981 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000982 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000983 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
984 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +0000985 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000986 break;
987 }
anthonyafa3dfc2012-03-03 11:31:30 +0000988 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000989 {
anthonyfd706f92012-01-19 04:22:02 +0000990 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000991 arg1 = ArgOption("undefined");
992 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
993 if (parse < 0)
994 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
995 option,arg1);
996 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000997 break;
998 }
anthonyafa3dfc2012-03-03 11:31:30 +0000999 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001000 {
anthony7bcfe7f2012-03-30 14:01:22 +00001001 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001002 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001003 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1004 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001005 break;
1006 }
anthonyebb73a22012-03-22 14:25:52 +00001007 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001008 }
1009 case 'k':
1010 {
anthonyafa3dfc2012-03-03 11:31:30 +00001011 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001012 {
anthony7bcfe7f2012-03-30 14:01:22 +00001013 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001014 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001015 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1016 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001017 break;
1018 }
anthonyebb73a22012-03-22 14:25:52 +00001019 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001020 }
1021 case 'l':
1022 {
anthonyafa3dfc2012-03-03 11:31:30 +00001023 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001024 {
anthony72feaa62012-01-17 06:46:23 +00001025 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001026 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001027 break;
1028 }
anthony756cd0d2012-04-08 12:41:44 +00001029 if (LocaleCompare("limit",option+1) == 0)
1030 {
1031 MagickSizeType
1032 limit;
1033
1034 limit=MagickResourceInfinity;
1035 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1036 if ( parse < 0 )
1037 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1038 option,arg1);
1039 if (LocaleCompare("unlimited",arg2) != 0)
1040 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1041 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1042 break;
1043 }
anthonyafa3dfc2012-03-03 11:31:30 +00001044 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001045 {
anthonyfe1aa782012-03-24 13:43:04 +00001046 if (IfSetOption) {
1047 if ((strchr(arg1,'%') == (char *) NULL))
1048 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001049 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001050 }
anthony805a2d42011-09-25 08:25:12 +00001051 break;
1052 }
anthony975a8d72012-04-12 13:54:36 +00001053 if (LocaleCompare("lowlight-color",option+1) == 0)
1054 {
anthonyb1d483a2012-04-14 12:53:56 +00001055 /* FUTURE: this is only used by CompareImages() which is used
1056 only by the "compare" CLI program at this time. */
anthony975a8d72012-04-12 13:54:36 +00001057 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1058 break;
1059 }
anthonyafa3dfc2012-03-03 11:31:30 +00001060 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001061 {
anthony72feaa62012-01-17 06:46:23 +00001062 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001063 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001064 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001065 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1066 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001067 break;
1068 }
anthonyebb73a22012-03-22 14:25:52 +00001069 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001070 }
1071 case 'm':
1072 {
anthonyafa3dfc2012-03-03 11:31:30 +00001073 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001074 {
anthony72feaa62012-01-17 06:46:23 +00001075 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001076 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001077 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001078 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001079 break;
anthonycd358fc2012-04-16 13:59:03 +00001080 }
anthonyb1d483a2012-04-14 12:53:56 +00001081 if (LocaleCompare("metric",option+1) == 0)
1082 {
1083 /* FUTURE: this is only used by CompareImages() which is used
1084 only by the "compare" CLI program at this time. */
1085 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1086 if ( parse < 0 )
1087 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1088 option,arg1);
1089 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthonycd358fc2012-04-16 13:59:03 +00001090 break;
anthony805a2d42011-09-25 08:25:12 +00001091 }
anthonyafa3dfc2012-03-03 11:31:30 +00001092 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001093 {
anthony92c93bd2012-03-19 14:02:47 +00001094 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001095 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001096 break;
1097 }
anthonyafa3dfc2012-03-03 11:31:30 +00001098 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001099 {
anthony24aa8822012-03-11 00:56:06 +00001100 /* Setting (used by some input coders!) -- why?
1101 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001102 */
anthony92c93bd2012-03-19 14:02:47 +00001103 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001104 break;
1105 }
anthonyebb73a22012-03-22 14:25:52 +00001106 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001107 }
1108 case 'o':
1109 {
anthonyafa3dfc2012-03-03 11:31:30 +00001110 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001111 {
anthony72feaa62012-01-17 06:46:23 +00001112 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001113 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001114 FUTURE: make set meta-data operator instead.
1115 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001116 */
anthony7bc87992012-03-25 02:32:51 +00001117 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1118 ArgOption("undefined"));
1119 if (parse < 0)
1120 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1121 option,arg1);
1122 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001123 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001124 break;
1125 }
anthonyebb73a22012-03-22 14:25:52 +00001126 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001127 }
1128 case 'p':
1129 {
anthonyafa3dfc2012-03-03 11:31:30 +00001130 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001131 {
anthony7bc87992012-03-25 02:32:51 +00001132 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001133 SyncImageSettings() used to set per-image attribute. ?????
1134 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001135 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001136 */
anthony805a2d42011-09-25 08:25:12 +00001137 char
1138 *canonical_page,
1139 page[MaxTextExtent];
1140
1141 const char
1142 *image_option;
1143
1144 MagickStatusType
1145 flags;
1146
1147 RectangleInfo
1148 geometry;
1149
anthonydcf510d2011-10-30 13:51:40 +00001150 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001151 {
anthony92c93bd2012-03-19 14:02:47 +00001152 (void) DeleteImageOption(_image_info,option+1);
1153 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001154 break;
1155 }
1156 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001157 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001158 if (image_option != (const char *) NULL)
1159 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001160 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001161 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1162 canonical_page=DestroyString(canonical_page);
1163 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1164 (unsigned long) geometry.width,(unsigned long) geometry.height);
1165 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1166 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1167 (unsigned long) geometry.width,(unsigned long) geometry.height,
1168 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001169 (void) SetImageOption(_image_info,option+1,page);
1170 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001171 break;
1172 }
anthonyafa3dfc2012-03-03 11:31:30 +00001173 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001174 {
anthony92c93bd2012-03-19 14:02:47 +00001175 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001176 break;
1177 }
anthonyafa3dfc2012-03-03 11:31:30 +00001178 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001179 {
anthonyf42014d2012-03-25 09:53:06 +00001180 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001181 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001182 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1183 _image_info->pointsize =
1184 _draw_info->pointsize =
1185 StringToDouble(arg1,(char **) NULL);
1186 }
1187 else {
1188 _image_info->pointsize=0.0; /* unset pointsize */
1189 _draw_info->pointsize=12.0;
1190 }
anthony805a2d42011-09-25 08:25:12 +00001191 break;
1192 }
anthonyafa3dfc2012-03-03 11:31:30 +00001193 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001194 {
anthonyf42014d2012-03-25 09:53:06 +00001195 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001196 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001197 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1198 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001199 break;
1200 }
anthonydcf510d2011-10-30 13:51:40 +00001201 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001202 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001203 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001204 {
anthony92c93bd2012-03-19 14:02:47 +00001205 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001206 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001207 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001208 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001209 break;
1210 }
anthonydcf510d2011-10-30 13:51:40 +00001211 */
anthonyebb73a22012-03-22 14:25:52 +00001212 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001213 }
1214 case 'q':
1215 {
anthonyafa3dfc2012-03-03 11:31:30 +00001216 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001217 {
anthony7bcfe7f2012-03-30 14:01:22 +00001218 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001219 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001220 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1221 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001222 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001223 break;
1224 }
anthonyafa3dfc2012-03-03 11:31:30 +00001225 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001226 {
anthony92c93bd2012-03-19 14:02:47 +00001227 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001228 arg1=ArgOption("undefined");
1229 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1230 if (parse < 0)
1231 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1232 option,arg1);
1233 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001234 break;
1235 }
anthonyafa3dfc2012-03-03 11:31:30 +00001236 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001237 {
anthonyf42014d2012-03-25 09:53:06 +00001238 /* FUTURE: if two -quiet is performed you can not do +quiet!
1239 This needs to be checked over thoughly.
1240 */
anthony805a2d42011-09-25 08:25:12 +00001241 static WarningHandler
1242 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001243
anthonyafbaed72011-10-26 12:05:04 +00001244 WarningHandler
1245 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001246
anthonyafbaed72011-10-26 12:05:04 +00001247 if ( tmp != (WarningHandler) NULL)
1248 warning_handler = tmp; /* remember the old handler */
1249 if (!IfSetOption) /* set the old handler */
1250 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001251 break;
1252 }
anthonyebb73a22012-03-22 14:25:52 +00001253 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001254 }
1255 case 'r':
1256 {
anthonyafa3dfc2012-03-03 11:31:30 +00001257 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001258 {
anthonydcf510d2011-10-30 13:51:40 +00001259 /* Image chromaticity X,Y NB: Y=X if Y not defined
1260 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001261 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001262 */
anthonyf42014d2012-03-25 09:53:06 +00001263 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001264 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001265 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001266 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001267 break;
1268 }
cristyb0f7a182012-04-06 23:33:11 +00001269 if (LocaleCompare("regard-warnings",option+1) == 0)
anthonye5fcd362012-04-09 04:02:09 +00001270 /* FUTURE: to be replaced by a 'fatal-level' type setting */
cristyb0f7a182012-04-06 23:33:11 +00001271 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001272 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001273 {
anthony92c93bd2012-03-19 14:02:47 +00001274 /* _draw_info only setting */
1275 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001276 break;
1277 }
anthony756cd0d2012-04-08 12:41:44 +00001278 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1279 {
1280 /* link image and setting stacks - option is itself saved on stack! */
1281 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1282 break;
1283 }
anthonyebb73a22012-03-22 14:25:52 +00001284 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001285 }
1286 case 's':
1287 {
anthonyafa3dfc2012-03-03 11:31:30 +00001288 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001289 {
anthonyafbaed72011-10-26 12:05:04 +00001290 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001291 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001292 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001293 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001294 break;
1295 }
anthonyafa3dfc2012-03-03 11:31:30 +00001296 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001297 {
anthonyf42014d2012-03-25 09:53:06 +00001298 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001299 What ??? Why ????
1300 */
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) SetImageOption(_image_info,option+1,ArgOption(NULL));
1304 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001305 break;
1306 }
anthonyafa3dfc2012-03-03 11:31:30 +00001307 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001308 {
anthony7bcfe7f2012-03-30 14:01:22 +00001309 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001310 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyd7761bb2012-04-14 01:42:05 +00001311 SetRandomSecretKey(
anthony24aa8822012-03-11 00:56:06 +00001312 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001313 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001314 break;
1315 }
anthonyafa3dfc2012-03-03 11:31:30 +00001316 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001317 {
anthony92c93bd2012-03-19 14:02:47 +00001318 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001319 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001320 */
anthony92c93bd2012-03-19 14:02:47 +00001321 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001322 break;
1323 }
anthonyafa3dfc2012-03-03 11:31:30 +00001324 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001325 {
anthonyf42014d2012-03-25 09:53:06 +00001326 arg1=ArgOption("undefined");
1327 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1328 if (parse < 0)
1329 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1330 option,arg1);
1331 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001332 break;
1333 }
anthonyafa3dfc2012-03-03 11:31:30 +00001334 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001335 {
anthonyafbaed72011-10-26 12:05:04 +00001336 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001337 UPDATE: ensure stroke color is not destroyed is a pattern
1338 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001339 */
anthony72feaa62012-01-17 06:46:23 +00001340 MagickBooleanType
1341 status;
anthonyafbaed72011-10-26 12:05:04 +00001342
1343 ExceptionInfo
1344 *sans;
1345
anthonyfd706f92012-01-19 04:22:02 +00001346 PixelInfo
1347 color;
1348
anthony2a0ec8c2012-03-24 04:35:56 +00001349 arg1 = ArgOption("none"); /* +fill turns it off! */
1350 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001351 if (_draw_info->stroke_pattern != (Image *) NULL)
1352 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001353
1354 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001355 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001356 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001357 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001358
anthony7bcfe7f2012-03-30 14:01:22 +00001359 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001360 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001361 else
anthony92c93bd2012-03-19 14:02:47 +00001362 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001363 break;
1364 }
anthonyafa3dfc2012-03-03 11:31:30 +00001365 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001366 {
anthony7bcfe7f2012-03-30 14:01:22 +00001367 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001368 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001369 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1370 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001371 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001372 break;
1373 }
anthonyafa3dfc2012-03-03 11:31:30 +00001374 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001375 {
anthonyf42014d2012-03-25 09:53:06 +00001376 arg1=ArgOption("undefined");
1377 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1378 if (parse < 0)
1379 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1380 option,arg1);
1381 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001382 break;
1383 }
anthonycd358fc2012-04-16 13:59:03 +00001384#if 0
anthonyb1d483a2012-04-14 12:53:56 +00001385 if (LocaleCompare("subimage-search",option+1) == 0)
1386 {
1387 /* FUTURE: this is only used by CompareImages() which is used
1388 only by the "compare" CLI program at this time. */
1389 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1390 break;
1391 }
anthonycd358fc2012-04-16 13:59:03 +00001392#endif
anthonyafa3dfc2012-03-03 11:31:30 +00001393 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001394 {
anthonyf42014d2012-03-25 09:53:06 +00001395 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001396 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001397 break;
1398 }
anthonyebb73a22012-03-22 14:25:52 +00001399 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001400 }
1401 case 't':
1402 {
anthonyafa3dfc2012-03-03 11:31:30 +00001403 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001404 {
anthony72feaa62012-01-17 06:46:23 +00001405 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001406 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001407 break;
1408 }
anthonyafa3dfc2012-03-03 11:31:30 +00001409 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001410 {
anthony4837ac22012-05-18 23:39:48 +00001411 /* Note: arguments do not have percent escapes expanded */
anthony52bef752012-03-27 13:54:47 +00001412 /* FUTURE: move _image_info string to option splay-tree
1413 Other than "montage" what uses "texture" ????
1414 */
anthony92c93bd2012-03-19 14:02:47 +00001415 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001416 break;
1417 }
anthonyafa3dfc2012-03-03 11:31:30 +00001418 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001419 {
anthony4837ac22012-05-18 23:39:48 +00001420 /* Note: arguments do not have percent escapes expanded */
anthony92c93bd2012-03-19 14:02:47 +00001421 _draw_info->fill_pattern=IfSetOption
1422 ?GetImageCache(_image_info,arg1,_exception)
1423 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001424 break;
1425 }
anthonyafa3dfc2012-03-03 11:31:30 +00001426 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001427 {
anthony72feaa62012-01-17 06:46:23 +00001428 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001429 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001430 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001431 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1432 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001433 break;
1434 }
anthonyafa3dfc2012-03-03 11:31:30 +00001435 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001436 {
anthony92c93bd2012-03-19 14:02:47 +00001437 /* FUTURE: both _image_info attribute & ImageOption in use!
1438 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001439 SyncImageSettings() used to set per-image attribute.
1440
anthonyafbaed72011-10-26 12:05:04 +00001441 Note that +transparent-color, means fall-back to image
1442 attribute so ImageOption is deleted, not set to a default.
1443 */
anthony7bcfe7f2012-03-30 14:01:22 +00001444 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001445 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001446 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001447 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001448 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001449 break;
1450 }
anthonyafa3dfc2012-03-03 11:31:30 +00001451 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001452 {
anthony92c93bd2012-03-19 14:02:47 +00001453 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1454 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001455 break;
1456 }
anthonyafa3dfc2012-03-03 11:31:30 +00001457 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001458 {
anthony72feaa62012-01-17 06:46:23 +00001459 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001460 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1461 ArgOption("undefined"));
1462 if (parse < 0)
1463 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1464 option,arg1);
1465 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001466 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001467 break;
1468 }
anthonyebb73a22012-03-22 14:25:52 +00001469 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001470 }
1471 case 'u':
1472 {
anthonyafa3dfc2012-03-03 11:31:30 +00001473 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001474 {
anthony92c93bd2012-03-19 14:02:47 +00001475 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001476 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001477 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001478 break;
1479 }
anthonyafa3dfc2012-03-03 11:31:30 +00001480 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001481 {
anthony72feaa62012-01-17 06:46:23 +00001482 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001483 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001484 FUTURE: this probably should be part of the density setting
1485 */
anthony52bef752012-03-27 13:54:47 +00001486 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1487 ArgOption("undefined"));
1488 if (parse < 0)
1489 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1490 option,arg1);
1491 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001492 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001493 break;
1494 }
anthonyebb73a22012-03-22 14:25:52 +00001495 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001496 }
1497 case 'v':
1498 {
anthonyafa3dfc2012-03-03 11:31:30 +00001499 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001500 {
anthony24aa8822012-03-11 00:56:06 +00001501 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001502 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001503 */
anthony92c93bd2012-03-19 14:02:47 +00001504 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1505 _image_info->verbose= ArgBoolean;
1506 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001507 break;
1508 }
anthonyafa3dfc2012-03-03 11:31:30 +00001509 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001510 {
anthony92c93bd2012-03-19 14:02:47 +00001511 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001512 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001513 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001514 */
anthony92c93bd2012-03-19 14:02:47 +00001515 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001516 break;
1517 }
anthonyafa3dfc2012-03-03 11:31:30 +00001518 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001519 {
anthonyfd706f92012-01-19 04:22:02 +00001520 /* SyncImageSettings() used to set per-image attribute.
1521 This is VERY deep in the image caching structure.
1522 */
anthony52bef752012-03-27 13:54:47 +00001523 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1524 ArgOption("undefined"));
1525 if (parse < 0)
1526 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1527 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001528 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001529 break;
1530 }
anthonyebb73a22012-03-22 14:25:52 +00001531 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001532 }
1533 case 'w':
1534 {
anthonyafa3dfc2012-03-03 11:31:30 +00001535 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001536 {
anthony72feaa62012-01-17 06:46:23 +00001537 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001538 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001539 */
anthony52bef752012-03-27 13:54:47 +00001540 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001541 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001542 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001543 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001544 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001545 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001546 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001547 if (_draw_info->weight <= 800)
1548 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001549 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001550 if (_draw_info->weight >= 100)
1551 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001552 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001553 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001554 break;
1555 }
anthonyafa3dfc2012-03-03 11:31:30 +00001556 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001557 {
anthony72feaa62012-01-17 06:46:23 +00001558 /* Used as a image chromaticity setting
1559 SyncImageSettings() used to set per-image attribute.
1560 */
anthony52bef752012-03-27 13:54:47 +00001561 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001562 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001563 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1564 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001565 break;
1566 }
anthonyebb73a22012-03-22 14:25:52 +00001567 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001568 }
1569 default:
anthonyebb73a22012-03-22 14:25:52 +00001570 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001571 }
anthony24aa8822012-03-11 00:56:06 +00001572
anthony4837ac22012-05-18 23:39:48 +00001573#if 0
1574 /* clean up percent escape interpreted strings */
1575 if (arg1 != arg1n )
1576 arg1=DestroyString((char *)arg1);
1577 if (arg2 != arg2n )
1578 arg2=DestroyString((char *)arg2);
1579#endif
1580
anthony92c93bd2012-03-19 14:02:47 +00001581#undef _image_info
1582#undef _exception
1583#undef _draw_info
1584#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001585#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001586#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001587#undef ArgBooleanNot
1588#undef ArgBooleanString
1589#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001590
anthony31f1bf72012-01-30 12:37:22 +00001591 return;
anthony805a2d42011-09-25 08:25:12 +00001592}
1593
1594/*
1595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1596% %
1597% %
1598% %
anthony43f425d2012-02-26 12:58:58 +00001599+ 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 +00001600% %
1601% %
1602% %
1603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1604%
anthony31f1bf72012-01-30 12:37:22 +00001605% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001606% the images in the CLI wand, with the settings that was previously saved in
1607% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001608%
1609% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001610% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001611%
anthonyd1447672012-01-19 05:33:53 +00001612% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001613%
anthony43f425d2012-02-26 12:58:58 +00001614% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001615% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001616%
1617% A description of each parameter follows:
1618%
anthony43f425d2012-02-26 12:58:58 +00001619% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001620%
anthonyfd706f92012-01-19 04:22:02 +00001621% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001622%
anthonyfd706f92012-01-19 04:22:02 +00001623% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001624%
anthony805a2d42011-09-25 08:25:12 +00001625*/
anthony31f1bf72012-01-30 12:37:22 +00001626
1627/*
1628 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001629 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001630
1631 The image in the list may be modified in three different ways...
1632 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1633 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1634 * one image replace by a list of images (-separate and -crop only!)
1635
anthonyafa3dfc2012-03-03 11:31:30 +00001636 In each case the result replaces the single original image in the list, as
1637 well as the pointer to the modified image (last image added if replaced by a
1638 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001639
1640 As the image pointed to may be replaced, the first image in the list may
1641 also change. GetFirstImageInList() should be used by caller if they wish
1642 return the Image pointer to the first image in list.
1643*/
anthony43f425d2012-02-26 12:58:58 +00001644static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthony964d28e2012-05-17 23:39:46 +00001645 const char *option, const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00001646{
1647 Image *
1648 new_image;
1649
anthony805a2d42011-09-25 08:25:12 +00001650 GeometryInfo
1651 geometry_info;
1652
1653 RectangleInfo
1654 geometry;
1655
1656 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001657 flags;
1658
anthony92c93bd2012-03-19 14:02:47 +00001659 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001660 parse;
anthony92c93bd2012-03-19 14:02:47 +00001661
anthony964d28e2012-05-17 23:39:46 +00001662 const char /* For percent escape interpretImageProperties() */
1663 *arg1,
1664 *arg2;
1665
anthony2e4501b2012-03-30 04:41:54 +00001666#define _image_info (cli_wand->wand.image_info)
1667#define _image (cli_wand->wand.images)
1668#define _exception (cli_wand->wand.exception)
1669#define _draw_info (cli_wand->draw_info)
1670#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00001671#define _process_flags (cli_wand->process_flags)
1672#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00001673#define IfNormalOp (*option=='-')
1674#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00001675#define normal_op IsMagickTrue(IfNormalOp)
1676#define plus_alt_op IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001677
anthony43f425d2012-02-26 12:58:58 +00001678 assert(cli_wand != (MagickCLI *) NULL);
1679 assert(cli_wand->signature == WandSignature);
1680 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001681 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001682 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001683 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001684
anthony964d28e2012-05-17 23:39:46 +00001685 /* Interpret Percent Escapes in Arguments - using first image */
1686 arg1 = arg1n,
1687 arg2 = arg2n;
1688 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1689 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1690 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1691 /* Interpret Percent escapes in argument 1 */
1692 if (arg1n != (char *) NULL) {
1693 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1694 if (arg1 == (char *) NULL) {
1695 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1696 arg1=arg1n; /* use the given argument as is */
1697 }
1698 }
1699 if (arg2n != (char *) NULL) {
1700 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1701 if (arg2 == (char *) NULL) {
1702 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1703 arg2=arg2n; /* use the given argument as is */
1704 }
1705 }
1706 }
anthony4837ac22012-05-18 23:39:48 +00001707#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00001708#undef _option_type
1709
1710#if 0
1711 (void) FormatLocaleFile(stderr,
1712 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1713#endif
anthony805a2d42011-09-25 08:25:12 +00001714
anthony5330ae02012-03-20 14:17:01 +00001715 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony964d28e2012-05-17 23:39:46 +00001716 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001717
anthonyafa3dfc2012-03-03 11:31:30 +00001718 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001719 {
1720 case 'a':
1721 {
anthonyafa3dfc2012-03-03 11:31:30 +00001722 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001723 {
anthonyfd706f92012-01-19 04:22:02 +00001724 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001725 if ((flags & (RhoValue|SigmaValue)) == 0)
1726 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001727 if ((flags & SigmaValue) == 0)
1728 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001729 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001730 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001731 break;
1732 }
anthonyafa3dfc2012-03-03 11:31:30 +00001733 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001734 {
anthonyfe1aa782012-03-24 13:43:04 +00001735 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001736 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001737 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1738 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1739 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001740 _exception);
anthony805a2d42011-09-25 08:25:12 +00001741 break;
1742 }
anthonyafa3dfc2012-03-03 11:31:30 +00001743 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001744 {
anthonyfd706f92012-01-19 04:22:02 +00001745 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001746 if ((flags & (RhoValue|SigmaValue)) == 0)
1747 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001748 if ((flags & SigmaValue) == 0)
1749 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001750 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001751 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001752 break;
1753 }
anthonyafa3dfc2012-03-03 11:31:30 +00001754 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001755 {
anthony2a0ec8c2012-03-24 04:35:56 +00001756 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1757 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001758 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1759 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001760 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1761 _exception);
anthony805a2d42011-09-25 08:25:12 +00001762 break;
1763 }
anthonyafa3dfc2012-03-03 11:31:30 +00001764 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001765 {
1766 char
anthony805a2d42011-09-25 08:25:12 +00001767 geometry[MaxTextExtent];
1768
anthony805a2d42011-09-25 08:25:12 +00001769 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001770 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001771 if ((flags & RhoValue) == 0)
1772 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001773 if ((flags & SigmaValue) == 0)
1774 geometry_info.sigma=geometry_info.rho;
anthony964d28e2012-05-17 23:39:46 +00001775 (void) CloneString(&_draw_info->text,arg2);
anthony805a2d42011-09-25 08:25:12 +00001776 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1777 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001778 (void) CloneString(&_draw_info->geometry,geometry);
1779 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001780 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001781 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001782 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001783 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001784 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001785 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001786 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001787 (void) AnnotateImage(_image,_draw_info,_exception);
1788 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001789 break;
1790 }
anthonyafa3dfc2012-03-03 11:31:30 +00001791 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001792 {
anthony92c93bd2012-03-19 14:02:47 +00001793 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001794 break;
1795 }
anthonyafa3dfc2012-03-03 11:31:30 +00001796 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001797 {
anthony92c93bd2012-03-19 14:02:47 +00001798 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001799 break;
1800 }
anthonyafa3dfc2012-03-03 11:31:30 +00001801 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001802 {
anthony5330ae02012-03-20 14:17:01 +00001803 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001804 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001805 {
1806 case TopRightOrientation:
1807 {
anthony92c93bd2012-03-19 14:02:47 +00001808 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001809 break;
1810 }
1811 case BottomRightOrientation:
1812 {
anthony92c93bd2012-03-19 14:02:47 +00001813 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001814 break;
1815 }
1816 case BottomLeftOrientation:
1817 {
anthony92c93bd2012-03-19 14:02:47 +00001818 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001819 break;
1820 }
1821 case LeftTopOrientation:
1822 {
anthony92c93bd2012-03-19 14:02:47 +00001823 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001824 break;
1825 }
1826 case RightTopOrientation:
1827 {
anthony92c93bd2012-03-19 14:02:47 +00001828 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001829 break;
1830 }
1831 case RightBottomOrientation:
1832 {
anthony92c93bd2012-03-19 14:02:47 +00001833 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001834 break;
1835 }
1836 case LeftBottomOrientation:
1837 {
anthony92c93bd2012-03-19 14:02:47 +00001838 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001839 break;
1840 }
1841 default:
1842 break;
1843 }
1844 if (new_image != (Image *) NULL)
1845 new_image->orientation=TopLeftOrientation;
1846 break;
1847 }
anthonyebb73a22012-03-22 14:25:52 +00001848 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001849 }
1850 case 'b':
1851 {
anthonyafa3dfc2012-03-03 11:31:30 +00001852 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001853 {
anthony7bcfe7f2012-03-30 14:01:22 +00001854 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001855 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001856 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001857 break;
1858 }
anthonyafa3dfc2012-03-03 11:31:30 +00001859 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001860 {
anthony805a2d42011-09-25 08:25:12 +00001861 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001862 if (IfNormalOp) {
anthonyfd706f92012-01-19 04:22:02 +00001863 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001864 if ((flags & RhoValue) == 0)
1865 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony5330ae02012-03-20 14:17:01 +00001866 }
anthony92c93bd2012-03-19 14:02:47 +00001867 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001868 break;
1869 }
anthonyafa3dfc2012-03-03 11:31:30 +00001870 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001871 {
anthonyfd706f92012-01-19 04:22:02 +00001872 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001873 if ((flags & (RhoValue|SigmaValue)) == 0)
1874 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001875 if ((flags & SigmaValue) == 0)
1876 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001877 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1878 _exception);
anthony805a2d42011-09-25 08:25:12 +00001879 break;
1880 }
anthonyafa3dfc2012-03-03 11:31:30 +00001881 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001882 {
anthony31f1bf72012-01-30 12:37:22 +00001883 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001884 compose;
1885
1886 const char*
anthony5f867ae2011-10-09 10:28:34 +00001887 value;
1888
anthony22de2722012-04-19 14:43:00 +00001889 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
1890 if ((flags & RhoValue) == 0)
anthony5330ae02012-03-20 14:17:01 +00001891 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony22de2722012-04-19 14:43:00 +00001892 if ((flags & SigmaValue) == 0)
1893 geometry.height=geometry.width;
anthony5330ae02012-03-20 14:17:01 +00001894
anthony92c93bd2012-03-19 14:02:47 +00001895 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001896 if (value != (const char *) NULL)
1897 compose=(CompositeOperator) ParseCommandOption(
1898 MagickComposeOptions,MagickFalse,value);
1899 else
anthony92c93bd2012-03-19 14:02:47 +00001900 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001901
anthony92c93bd2012-03-19 14:02:47 +00001902 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001903 break;
1904 }
anthonyafa3dfc2012-03-03 11:31:30 +00001905 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001906 {
1907 double
1908 brightness,
1909 contrast;
1910
1911 GeometryInfo
1912 geometry_info;
1913
1914 MagickStatusType
1915 flags;
1916
anthonyfd706f92012-01-19 04:22:02 +00001917 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001918 if ((flags & RhoValue) == 0)
1919 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001920 brightness=geometry_info.rho;
1921 contrast=0.0;
1922 if ((flags & SigmaValue) != 0)
1923 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001924 (void) BrightnessContrastImage(_image,brightness,contrast,
1925 _exception);
anthony805a2d42011-09-25 08:25:12 +00001926 break;
1927 }
anthonyebb73a22012-03-22 14:25:52 +00001928 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001929 }
1930 case 'c':
1931 {
anthonyafa3dfc2012-03-03 11:31:30 +00001932 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001933 {
anthony4837ac22012-05-18 23:39:48 +00001934 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001935 char
1936 *color_correction_collection;
1937
1938 /*
1939 Color correct with a color decision list.
1940 */
anthony92c93bd2012-03-19 14:02:47 +00001941 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001942 if (color_correction_collection == (char *) NULL)
1943 break;
anthony92c93bd2012-03-19 14:02:47 +00001944 (void) ColorDecisionListImage(_image,color_correction_collection,
1945 _exception);
anthony805a2d42011-09-25 08:25:12 +00001946 break;
1947 }
anthonyafa3dfc2012-03-03 11:31:30 +00001948 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001949 {
anthonyfd706f92012-01-19 04:22:02 +00001950 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001951 if ((flags & (RhoValue|SigmaValue)) == 0)
1952 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001953 if ((flags & SigmaValue) == 0)
1954 geometry_info.sigma=1.0;
1955 if ((flags & XiValue) == 0)
1956 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001957 new_image=CharcoalImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001958 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001959 break;
1960 }
anthonyafa3dfc2012-03-03 11:31:30 +00001961 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001962 {
anthony7bcfe7f2012-03-30 14:01:22 +00001963 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001964 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001965 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1966 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001967 break;
1968 }
anthonyafa3dfc2012-03-03 11:31:30 +00001969 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001970 {
anthony92c93bd2012-03-19 14:02:47 +00001971 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001972 break;
1973 }
anthonyafa3dfc2012-03-03 11:31:30 +00001974 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001975 {
anthonyafa3dfc2012-03-03 11:31:30 +00001976 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001977 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001978 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001979 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001980 break;
1981 }
anthonyafa3dfc2012-03-03 11:31:30 +00001982 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001983 {
anthony4837ac22012-05-18 23:39:48 +00001984 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001985 CacheView
1986 *mask_view;
1987
1988 Image
1989 *mask_image;
1990
1991 register Quantum
1992 *restrict q;
1993
1994 register ssize_t
1995 x;
1996
1997 ssize_t
1998 y;
1999
anthonyafa3dfc2012-03-03 11:31:30 +00002000 if (IfPlusOp) {
anthony4837ac22012-05-18 23:39:48 +00002001 /* use "+clip-mask" Remove the write mask for -clip-path */
anthony92c93bd2012-03-19 14:02:47 +00002002 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002003 break;
2004 }
anthony92c93bd2012-03-19 14:02:47 +00002005 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002006 if (mask_image == (Image *) NULL)
2007 break;
anthony7bcfe7f2012-03-30 14:01:22 +00002008 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00002009 break;
anthony5330ae02012-03-20 14:17:01 +00002010 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002011 /* FUTURE: use Alpha operations instead and create a Grey Image */
cristydb070952012-04-20 14:33:00 +00002012 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002013 for (y=0; y < (ssize_t) mask_image->rows; y++)
2014 {
2015 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002016 _exception);
anthony805a2d42011-09-25 08:25:12 +00002017 if (q == (Quantum *) NULL)
2018 break;
2019 for (x=0; x < (ssize_t) mask_image->columns; x++)
2020 {
anthony7bcfe7f2012-03-30 14:01:22 +00002021 if (IfMagickFalse(mask_image->matte))
anthony805a2d42011-09-25 08:25:12 +00002022 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2023 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2024 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2025 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2026 q+=GetPixelChannels(mask_image);
2027 }
anthony7bcfe7f2012-03-30 14:01:22 +00002028 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00002029 break;
2030 }
anthonyfd706f92012-01-19 04:22:02 +00002031 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002032 mask_view=DestroyCacheView(mask_view);
2033 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002034 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002035 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002036 break;
2037 }
anthonyafa3dfc2012-03-03 11:31:30 +00002038 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002039 {
anthony92c93bd2012-03-19 14:02:47 +00002040 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony4837ac22012-05-18 23:39:48 +00002041 /* Note: Use "+clip-mask" remove the write mask added */
anthony805a2d42011-09-25 08:25:12 +00002042 break;
2043 }
anthonyafa3dfc2012-03-03 11:31:30 +00002044 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002045 {
anthony7bcfe7f2012-03-30 14:01:22 +00002046 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002047 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002048 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002049 break;
2050 }
anthonyafa3dfc2012-03-03 11:31:30 +00002051 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002052 {
2053 KernelInfo
2054 *kernel;
2055
anthonyfd706f92012-01-19 04:22:02 +00002056 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002057 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002058 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002059 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002060 kernel=DestroyKernelInfo(kernel);
2061 break;
2062 }
anthonyafa3dfc2012-03-03 11:31:30 +00002063 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002064 {
anthony5330ae02012-03-20 14:17:01 +00002065 /* Reduce the number of colors in the image.
2066 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002067 */
anthony92c93bd2012-03-19 14:02:47 +00002068 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2069 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002070 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002071 if ((_image->storage_class == DirectClass) ||
2072 _image->colors > _quantize_info->number_colors)
2073 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002074 else
anthony92c93bd2012-03-19 14:02:47 +00002075 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002076 break;
2077 }
anthonyafa3dfc2012-03-03 11:31:30 +00002078 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002079 {
anthony5330ae02012-03-20 14:17:01 +00002080 /* WARNING: this is both a image_info setting (already done)
2081 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002082
2083 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002084 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002085
anthonyd2cdc862011-10-07 14:07:17 +00002086 Note that +colorspace sets "undefined" or no effect on
2087 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002088 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002089 */
anthony92c93bd2012-03-19 14:02:47 +00002090 (void) TransformImageColorspace(_image,
2091 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2092 _exception);
anthony805a2d42011-09-25 08:25:12 +00002093 break;
2094 }
anthonyafa3dfc2012-03-03 11:31:30 +00002095 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002096 {
anthony464f1c42012-04-22 08:51:01 +00002097 CLIWandWarnReplaced(normal_op?"-level":"+level");
anthony92c93bd2012-03-19 14:02:47 +00002098 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002099 break;
2100 }
anthonyafa3dfc2012-03-03 11:31:30 +00002101 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002102 {
2103 double
2104 black_point,
2105 white_point;
2106
2107 MagickStatusType
2108 flags;
2109
anthonyfd706f92012-01-19 04:22:02 +00002110 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002111 if ((flags & RhoValue) == 0)
2112 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002113 black_point=geometry_info.rho;
2114 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2115 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002116 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002117 black_point*=(double) _image->columns*_image->rows/100.0;
2118 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002119 }
anthony92c93bd2012-03-19 14:02:47 +00002120 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002121 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002122 (void) ContrastStretchImage(_image,black_point,white_point,
2123 _exception);
anthony805a2d42011-09-25 08:25:12 +00002124 break;
2125 }
anthonyafa3dfc2012-03-03 11:31:30 +00002126 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002127 {
2128 KernelInfo
2129 *kernel_info;
2130
anthonyfd706f92012-01-19 04:22:02 +00002131 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002132 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002133 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristya12d8ba2012-04-29 16:33:41 +00002134 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2135 _exception);
anthony805a2d42011-09-25 08:25:12 +00002136 kernel_info=DestroyKernelInfo(kernel_info);
2137 break;
2138 }
anthonyafa3dfc2012-03-03 11:31:30 +00002139 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002140 {
anthony31f1bf72012-01-30 12:37:22 +00002141 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002142 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002143 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002144 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002145 break;
2146 }
anthonyafa3dfc2012-03-03 11:31:30 +00002147 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002148 {
anthony7bcfe7f2012-03-30 14:01:22 +00002149 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002150 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002151 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2152 _exception);
anthony805a2d42011-09-25 08:25:12 +00002153 break;
2154 }
anthonyebb73a22012-03-22 14:25:52 +00002155 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002156 }
2157 case 'd':
2158 {
anthonyafa3dfc2012-03-03 11:31:30 +00002159 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002160 {
anthony4837ac22012-05-18 23:39:48 +00002161 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002162 StringInfo
2163 *passkey;
2164
anthony92c93bd2012-03-19 14:02:47 +00002165 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002166 if (passkey == (StringInfo *) NULL)
2167 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2168
2169 (void) PasskeyDecipherImage(_image,passkey,_exception);
2170 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002171 break;
2172 }
anthonyafa3dfc2012-03-03 11:31:30 +00002173 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002174 {
anthony92c93bd2012-03-19 14:02:47 +00002175 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002176 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002177
anthonydcf510d2011-10-30 13:51:40 +00002178 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2179 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002180
anthonyfd706f92012-01-19 04:22:02 +00002181 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002182 */
anthony92c93bd2012-03-19 14:02:47 +00002183 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002184 break;
2185 }
anthonyafa3dfc2012-03-03 11:31:30 +00002186 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002187 {
2188 double
2189 threshold;
2190
anthonyebb73a22012-03-22 14:25:52 +00002191 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002192 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002193 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002194 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002195 }
anthonyafa3dfc2012-03-03 11:31:30 +00002196 else
2197 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002198 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002199 break;
2200 }
anthonyafa3dfc2012-03-03 11:31:30 +00002201 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002202 {
anthony92c93bd2012-03-19 14:02:47 +00002203 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002204 break;
2205 }
anthonyafa3dfc2012-03-03 11:31:30 +00002206 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002207 {
anthony805a2d42011-09-25 08:25:12 +00002208 double
anthonyb1d483a2012-04-14 12:53:56 +00002209 *args;
anthony805a2d42011-09-25 08:25:12 +00002210
anthonyb1d483a2012-04-14 12:53:56 +00002211 ssize_t
2212 count;
anthony805a2d42011-09-25 08:25:12 +00002213
anthony2a0ec8c2012-03-24 04:35:56 +00002214 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2215 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002216 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2217 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002218 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002219 {
anthony80c37752012-01-16 01:03:11 +00002220 double
2221 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002222 /* Special Case - Argument is actually a resize geometry!
2223 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002224 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002225 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002226 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002227 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2228 option,arg2);
2229 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002230 resize_args[0]=(double) geometry.width;
2231 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002232 new_image=DistortImage(_image,(DistortImageMethod) parse,
2233 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002234 break;
2235 }
anthonyb1d483a2012-04-14 12:53:56 +00002236 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002237 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002238 if (args == (double *)NULL )
2239 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2240
2241 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
2242 plus_alt_op,_exception);
2243 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002244 break;
2245 }
anthonyafa3dfc2012-03-03 11:31:30 +00002246 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002247 {
anthony92c93bd2012-03-19 14:02:47 +00002248 (void) CloneString(&_draw_info->primitive,arg1);
2249 (void) DrawImage(_image,_draw_info,_exception);
2250 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002251 break;
2252 }
anthonyebb73a22012-03-22 14:25:52 +00002253 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002254 }
2255 case 'e':
2256 {
anthonyafa3dfc2012-03-03 11:31:30 +00002257 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002258 {
anthonyfd706f92012-01-19 04:22:02 +00002259 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002260 if ((flags & (RhoValue|SigmaValue)) == 0)
2261 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002262 if ((flags & SigmaValue) == 0)
2263 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002264 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2265 _exception);
anthony805a2d42011-09-25 08:25:12 +00002266 break;
2267 }
anthonyafa3dfc2012-03-03 11:31:30 +00002268 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002269 {
anthonyfd706f92012-01-19 04:22:02 +00002270 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002271 if ((flags & (RhoValue|SigmaValue)) == 0)
2272 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002273 if ((flags & SigmaValue) == 0)
2274 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002275 new_image=EmbossImage(_image,geometry_info.rho,
2276 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002277 break;
2278 }
anthonyafa3dfc2012-03-03 11:31:30 +00002279 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002280 {
anthony4837ac22012-05-18 23:39:48 +00002281 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002282 StringInfo
2283 *passkey;
2284
anthony92c93bd2012-03-19 14:02:47 +00002285 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002286 if (passkey != (StringInfo *) NULL)
2287 {
anthony92c93bd2012-03-19 14:02:47 +00002288 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002289 passkey=DestroyStringInfo(passkey);
2290 }
2291 break;
2292 }
anthonyafa3dfc2012-03-03 11:31:30 +00002293 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002294 {
anthony92c93bd2012-03-19 14:02:47 +00002295 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002296 break;
2297 }
anthonyafa3dfc2012-03-03 11:31:30 +00002298 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002299 {
anthony92c93bd2012-03-19 14:02:47 +00002300 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002301 break;
2302 }
anthonyafa3dfc2012-03-03 11:31:30 +00002303 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002304 {
2305 double
2306 constant;
2307
anthony2a0ec8c2012-03-24 04:35:56 +00002308 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2309 if ( parse < 0 )
2310 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2311 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002312 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002313 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002314 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002315 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2316 _exception);
anthony805a2d42011-09-25 08:25:12 +00002317 break;
2318 }
anthonyafa3dfc2012-03-03 11:31:30 +00002319 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002320 {
anthony7bcfe7f2012-03-30 14:01:22 +00002321 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002322 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002323 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002324 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002325 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002326 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002327 geometry.height=_image->rows;
2328 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002329 break;
2330 }
anthonyebb73a22012-03-22 14:25:52 +00002331 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002332 }
2333 case 'f':
2334 {
anthonyafa3dfc2012-03-03 11:31:30 +00002335 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002336 {
anthony31f1bf72012-01-30 12:37:22 +00002337 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002338 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002339 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002340 break;
2341 }
anthony92c93bd2012-03-19 14:02:47 +00002342 (void) SetImageArtifact(_image,"identify:features","true");
2343 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002344 break;
2345 }
anthonyafa3dfc2012-03-03 11:31:30 +00002346 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002347 {
anthony92c93bd2012-03-19 14:02:47 +00002348 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002349 break;
2350 }
anthonyafa3dfc2012-03-03 11:31:30 +00002351 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002352 {
anthony92c93bd2012-03-19 14:02:47 +00002353 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002354 break;
2355 }
anthonyafa3dfc2012-03-03 11:31:30 +00002356 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002357 {
2358 PixelInfo
2359 target;
2360
anthony7bcfe7f2012-03-30 14:01:22 +00002361 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002362 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002363 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2364 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2365 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2366 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002367 break;
2368 }
anthonyafa3dfc2012-03-03 11:31:30 +00002369 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002370 {
2371 FrameInfo
2372 frame_info;
2373
anthony31f1bf72012-01-30 12:37:22 +00002374 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002375 compose;
2376
2377 const char*
2378 value;
2379
anthony92c93bd2012-03-19 14:02:47 +00002380 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002381 if (value != (const char *) NULL)
2382 compose=(CompositeOperator) ParseCommandOption(
2383 MagickComposeOptions,MagickFalse,value);
2384 else
anthony92c93bd2012-03-19 14:02:47 +00002385 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002386
anthony7bcfe7f2012-03-30 14:01:22 +00002387 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002388 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002389 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002390 frame_info.width=geometry.width;
2391 frame_info.height=geometry.height;
2392 if ((flags & HeightValue) == 0)
2393 frame_info.height=geometry.width;
2394 frame_info.outer_bevel=geometry.x;
2395 frame_info.inner_bevel=geometry.y;
2396 frame_info.x=(ssize_t) frame_info.width;
2397 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002398 frame_info.width=_image->columns+2*frame_info.width;
2399 frame_info.height=_image->rows+2*frame_info.height;
2400 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002401 break;
2402 }
anthonyafa3dfc2012-03-03 11:31:30 +00002403 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002404 {
anthony805a2d42011-09-25 08:25:12 +00002405 double
anthonyb1d483a2012-04-14 12:53:56 +00002406 *args;
anthony805a2d42011-09-25 08:25:12 +00002407
anthonyb1d483a2012-04-14 12:53:56 +00002408 ssize_t
2409 count;
anthony805a2d42011-09-25 08:25:12 +00002410
anthony2a0ec8c2012-03-24 04:35:56 +00002411 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2412 if ( parse < 0 )
2413 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2414 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002415 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002416 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002417 if (args == (double *)NULL )
2418 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2419
2420 (void) FunctionImage(_image,(MagickFunction)parse,count,args,
2421 _exception);
2422 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002423 break;
2424 }
anthonyebb73a22012-03-22 14:25:52 +00002425 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002426 }
2427 case 'g':
2428 {
anthonyafa3dfc2012-03-03 11:31:30 +00002429 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002430 {
anthony7bcfe7f2012-03-30 14:01:22 +00002431 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002432 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafa3dfc2012-03-03 11:31:30 +00002433 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002434 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2435 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002436 else
anthony92c93bd2012-03-19 14:02:47 +00002437 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002438 break;
2439 }
anthony975a8d72012-04-12 13:54:36 +00002440 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002441 {
anthonyfd706f92012-01-19 04:22:02 +00002442 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002443 if ((flags & (RhoValue|SigmaValue)) == 0)
2444 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002445 if ((flags & SigmaValue) == 0)
2446 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002447 new_image=GaussianBlurImage(_image,geometry_info.rho,
2448 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002449 break;
2450 }
anthony975a8d72012-04-12 13:54:36 +00002451 if (LocaleCompare("gaussian",option+1) == 0)
2452 {
anthony464f1c42012-04-22 08:51:01 +00002453 CLIWandWarnReplaced("-gaussian-blur");
anthony975a8d72012-04-12 13:54:36 +00002454 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
2455 }
anthonyafa3dfc2012-03-03 11:31:30 +00002456 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002457 {
anthonyfd706f92012-01-19 04:22:02 +00002458 /*
anthony31f1bf72012-01-30 12:37:22 +00002459 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002460 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002461 FUTURE: Why if no 'offset' does this resize ALL images?
2462 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002463 */
anthonyafa3dfc2012-03-03 11:31:30 +00002464 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002465 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002466 if (_image->geometry != (char *) NULL)
2467 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002468 break;
2469 }
anthony7bcfe7f2012-03-30 14:01:22 +00002470 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002471 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002472 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002473 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002474 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002475 else
anthony92c93bd2012-03-19 14:02:47 +00002476 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002477 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002478 break;
2479 }
anthonyebb73a22012-03-22 14:25:52 +00002480 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002481 }
anthony805a2d42011-09-25 08:25:12 +00002482 case 'i':
2483 {
anthonyafa3dfc2012-03-03 11:31:30 +00002484 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002485 {
anthony31f1bf72012-01-30 12:37:22 +00002486 const char
2487 *format,
anthony805a2d42011-09-25 08:25:12 +00002488 *text;
2489
anthony92c93bd2012-03-19 14:02:47 +00002490 format=GetImageOption(_image_info,"format");
anthony964d28e2012-05-17 23:39:46 +00002491 if (format == (char *) NULL) {
2492 (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception);
2493 break;
2494 }
anthony92c93bd2012-03-19 14:02:47 +00002495 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002496 if (text == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00002497 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
2498 option);
anthony805a2d42011-09-25 08:25:12 +00002499 (void) fputs(text,stdout);
2500 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002501 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002502 break;
2503 }
anthonyafa3dfc2012-03-03 11:31:30 +00002504 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002505 {
anthonyb1e21ed2012-04-20 12:43:12 +00002506 flags=ParseGeometry(arg1,&geometry_info);
2507 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002508 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002509 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2510 _exception);
anthony805a2d42011-09-25 08:25:12 +00002511 break;
2512 }
anthonyafa3dfc2012-03-03 11:31:30 +00002513 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002514 {
anthonyfe1aa782012-03-24 13:43:04 +00002515 /* FUTURE: New to IMv7
2516 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002517 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002518 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002519 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2520 new_image=InterpolativeResizeImage(_image,geometry.width,
2521 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002522 break;
2523 }
anthonyebb73a22012-03-22 14:25:52 +00002524 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002525 }
2526 case 'l':
2527 {
anthonyafa3dfc2012-03-03 11:31:30 +00002528 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002529 {
anthonyfd706f92012-01-19 04:22:02 +00002530 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002531 if ((flags & (RhoValue|SigmaValue)) == 0)
2532 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002533 if ((flags & PercentValue) != 0)
2534 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002535 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002536 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002537 _exception);
anthony805a2d42011-09-25 08:25:12 +00002538 break;
2539 }
anthonyafa3dfc2012-03-03 11:31:30 +00002540 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002541 {
2542 MagickRealType
2543 black_point,
2544 gamma,
2545 white_point;
2546
2547 MagickStatusType
2548 flags;
2549
anthonyfd706f92012-01-19 04:22:02 +00002550 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002551 if ((flags & RhoValue) == 0)
2552 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002553 black_point=geometry_info.rho;
2554 white_point=(MagickRealType) QuantumRange;
2555 if ((flags & SigmaValue) != 0)
2556 white_point=geometry_info.sigma;
2557 gamma=1.0;
2558 if ((flags & XiValue) != 0)
2559 gamma=geometry_info.xi;
2560 if ((flags & PercentValue) != 0)
2561 {
2562 black_point*=(MagickRealType) (QuantumRange/100.0);
2563 white_point*=(MagickRealType) (QuantumRange/100.0);
2564 }
2565 if ((flags & SigmaValue) == 0)
2566 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002567 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002568 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002569 else
anthony92c93bd2012-03-19 14:02:47 +00002570 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002571 break;
2572 }
anthonyafa3dfc2012-03-03 11:31:30 +00002573 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002574 {
2575 char
2576 token[MaxTextExtent];
2577
2578 const char
2579 *p;
2580
2581 PixelInfo
2582 black_point,
2583 white_point;
2584
anthonyfd706f92012-01-19 04:22:02 +00002585 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002586 GetMagickToken(p,&p,token); /* get black point color */
2587 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002588 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002589 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002590 else
cristy269c9412011-10-13 23:41:15 +00002591 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002592 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002593 if (isalpha((int) token[0]) || (token[0] == '#'))
2594 GetMagickToken(p,&p,token);
2595 if (*token == '\0')
2596 white_point=black_point; /* set everything to that color */
2597 else
2598 {
2599 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2600 GetMagickToken(p,&p,token); /* Get white point color. */
2601 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002602 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002603 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002604 else
cristy269c9412011-10-13 23:41:15 +00002605 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002606 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002607 }
anthony92c93bd2012-03-19 14:02:47 +00002608 (void) LevelImageColors(_image,&black_point,&white_point,
2609 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002610 break;
2611 }
anthonyafa3dfc2012-03-03 11:31:30 +00002612 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002613 {
2614 double
2615 black_point,
2616 white_point;
2617
2618 MagickStatusType
2619 flags;
2620
anthonyfd706f92012-01-19 04:22:02 +00002621 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002622 if ((flags & RhoValue) == 0)
2623 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002624 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002625 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002626 if ((flags & SigmaValue) != 0)
2627 white_point=geometry_info.sigma;
2628 if ((flags & PercentValue) != 0)
2629 {
anthony92c93bd2012-03-19 14:02:47 +00002630 black_point*=(double) _image->columns*_image->rows/100.0;
2631 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002632 }
2633 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002634 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002635 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002636 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002637 break;
2638 }
anthonyafa3dfc2012-03-03 11:31:30 +00002639 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002640 {
anthonyfe1aa782012-03-24 13:43:04 +00002641 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002642 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002643 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002644 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002645 if ((flags & XValue) == 0)
2646 geometry.x=1;
2647 if ((flags & YValue) == 0)
2648 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002649 new_image=LiquidRescaleImage(_image,geometry.width,
2650 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002651 break;
2652 }
anthonyebb73a22012-03-22 14:25:52 +00002653 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002654 }
2655 case 'm':
2656 {
anthonyafa3dfc2012-03-03 11:31:30 +00002657 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002658 {
anthony464f1c42012-04-22 08:51:01 +00002659 CLIWandWarnReplaced("-remap");
anthony975a8d72012-04-12 13:54:36 +00002660 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
anthony805a2d42011-09-25 08:25:12 +00002661 break;
2662 }
anthonyafa3dfc2012-03-03 11:31:30 +00002663 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002664 {
anthony4837ac22012-05-18 23:39:48 +00002665 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002666 Image
2667 *mask;
2668
anthonyafa3dfc2012-03-03 11:31:30 +00002669 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002670 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002671 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002672 break;
2673 }
anthony5330ae02012-03-20 14:17:01 +00002674 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002675 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002676 if (mask == (Image *) NULL)
2677 break;
anthony92c93bd2012-03-19 14:02:47 +00002678 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002679 mask=DestroyImage(mask);
2680 break;
2681 }
anthonyafa3dfc2012-03-03 11:31:30 +00002682 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002683 {
anthony464f1c42012-04-22 08:51:01 +00002684 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
anthony92c93bd2012-03-19 14:02:47 +00002685 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2686 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002687 break;
2688 }
anthonya3ef4ed2012-03-17 06:52:53 +00002689 if (LocaleCompare("median",option+1) == 0)
2690 {
anthony464f1c42012-04-22 08:51:01 +00002691 CLIWandWarnReplaced("-statistic Median");
anthonya3ef4ed2012-03-17 06:52:53 +00002692 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2693 break;
2694 }
anthonyafa3dfc2012-03-03 11:31:30 +00002695 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002696 {
anthony975a8d72012-04-12 13:54:36 +00002697 /* FUTURE: note this is also a special "montage" option */
anthony464f1c42012-04-22 08:51:01 +00002698 CLIWandWarnReplaced("-statistic Mode");
anthony975a8d72012-04-12 13:54:36 +00002699 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
anthony805a2d42011-09-25 08:25:12 +00002700 break;
2701 }
anthonyafa3dfc2012-03-03 11:31:30 +00002702 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002703 {
anthony7bcfe7f2012-03-30 14:01:22 +00002704 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002705 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002706 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002707 break;
2708 }
anthonyafa3dfc2012-03-03 11:31:30 +00002709 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002710 {
anthony92c93bd2012-03-19 14:02:47 +00002711 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002712 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002713 break;
2714 }
anthonyafa3dfc2012-03-03 11:31:30 +00002715 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002716 {
anthony92c93bd2012-03-19 14:02:47 +00002717 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002718 break;
2719 }
anthonyafa3dfc2012-03-03 11:31:30 +00002720 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002721 {
2722 char
2723 token[MaxTextExtent];
2724
2725 const char
2726 *p;
2727
2728 KernelInfo
2729 *kernel;
2730
anthony805a2d42011-09-25 08:25:12 +00002731 ssize_t
2732 iterations;
2733
anthonyfd706f92012-01-19 04:22:02 +00002734 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002735 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002736 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2737 if ( parse < 0 )
2738 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2739 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002740 iterations=1L;
2741 GetMagickToken(p,&p,token);
2742 if ((*p == ':') || (*p == ','))
2743 GetMagickToken(p,&p,token);
2744 if ((*p != '\0'))
2745 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002746 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002747 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002748 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2749 option,arg2);
2750 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2751 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002752 kernel=DestroyKernelInfo(kernel);
2753 break;
2754 }
anthonyafa3dfc2012-03-03 11:31:30 +00002755 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002756 {
anthonyfd706f92012-01-19 04:22:02 +00002757 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002758 if ((flags & (RhoValue|SigmaValue)) == 0)
2759 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002760 if ((flags & SigmaValue) == 0)
2761 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002762 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002763 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002764 break;
2765 }
anthonyebb73a22012-03-22 14:25:52 +00002766 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002767 }
2768 case 'n':
2769 {
anthonyafa3dfc2012-03-03 11:31:30 +00002770 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002771 {
anthony92c93bd2012-03-19 14:02:47 +00002772 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002773 break;
2774 }
anthonyafa3dfc2012-03-03 11:31:30 +00002775 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002776 {
anthony975a8d72012-04-12 13:54:36 +00002777 double
2778 attenuate;
2779
2780 const char*
2781 value;
2782
anthonyafa3dfc2012-03-03 11:31:30 +00002783 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002784 {
anthony464f1c42012-04-22 08:51:01 +00002785 CLIWandWarnReplaced("-statistic NonPeak");
anthony975a8d72012-04-12 13:54:36 +00002786 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
2787 break;
anthony805a2d42011-09-25 08:25:12 +00002788 }
anthony975a8d72012-04-12 13:54:36 +00002789 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2790 if ( parse < 0 )
2791 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2792 option,arg1);
2793 attenuate=1.0;
2794 value=GetImageOption(_image_info,"attenuate");
2795 if (value != (const char *) NULL)
2796 attenuate=StringToDouble(value,(char **) NULL);
2797 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2798 _exception);
anthony805a2d42011-09-25 08:25:12 +00002799 break;
2800 }
anthonyafa3dfc2012-03-03 11:31:30 +00002801 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002802 {
anthony92c93bd2012-03-19 14:02:47 +00002803 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002804 break;
2805 }
anthonyebb73a22012-03-22 14:25:52 +00002806 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002807 }
2808 case 'o':
2809 {
anthonyafa3dfc2012-03-03 11:31:30 +00002810 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002811 {
2812 PixelInfo
2813 target;
2814
anthony92c93bd2012-03-19 14:02:47 +00002815 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2816 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2817 _exception);
anthony805a2d42011-09-25 08:25:12 +00002818 break;
2819 }
anthonyafa3dfc2012-03-03 11:31:30 +00002820 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002821 {
anthony92c93bd2012-03-19 14:02:47 +00002822 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002823 break;
2824 }
anthonyebb73a22012-03-22 14:25:52 +00002825 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002826 }
2827 case 'p':
2828 {
anthonyafa3dfc2012-03-03 11:31:30 +00002829 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002830 {
anthony22de2722012-04-19 14:43:00 +00002831 flags=ParseGeometry(arg1,&geometry_info);
2832 if ((flags & (RhoValue|SigmaValue)) == 0)
2833 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002834 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2835 _exception);
anthony805a2d42011-09-25 08:25:12 +00002836 break;
2837 }
anthonyafa3dfc2012-03-03 11:31:30 +00002838 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002839 {
cristye9e3d382011-12-14 01:50:13 +00002840 const char
2841 *caption;
2842
anthony805a2d42011-09-25 08:25:12 +00002843 double
2844 angle;
2845
anthony7bc87992012-03-25 02:32:51 +00002846 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002847 RandomInfo
2848 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002849
anthonyf42014d2012-03-25 09:53:06 +00002850 random_info=AcquireRandomInfo();
2851 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2852 random_info=DestroyRandomInfo(random_info);
2853 }
anthony7bc87992012-03-25 02:32:51 +00002854 else {
anthonyf42014d2012-03-25 09:53:06 +00002855 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002856 if ((flags & RhoValue) == 0)
2857 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002858 angle=geometry_info.rho;
2859 }
anthony92c93bd2012-03-19 14:02:47 +00002860 caption=GetImageProperty(_image,"caption",_exception);
2861 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2862 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002863 break;
2864 }
anthonyafa3dfc2012-03-03 11:31:30 +00002865 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002866 {
anthony22de2722012-04-19 14:43:00 +00002867 flags=ParseGeometry(arg1,&geometry_info);
2868 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002869 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002870 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
cristycbda6112012-05-27 20:57:16 +00002871 _quantize_info->dither_method,_exception);
anthony805a2d42011-09-25 08:25:12 +00002872 break;
2873 }
anthonyafa3dfc2012-03-03 11:31:30 +00002874 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002875 {
anthony31f1bf72012-01-30 12:37:22 +00002876 /* FUTURE: should be a 'Genesis' option?
2877 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00002878 Why???
cristy947cb4c2011-10-20 18:41:46 +00002879 */
anthony7bc87992012-03-25 02:32:51 +00002880 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2881 if ( parse < 0 )
2882 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2883 option,arg1);
2884 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00002885 break;
2886 }
anthonyafa3dfc2012-03-03 11:31:30 +00002887 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002888 {
anthony4837ac22012-05-18 23:39:48 +00002889 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002890 const char
2891 *name;
2892
2893 const StringInfo
2894 *profile;
2895
2896 Image
2897 *profile_image;
2898
2899 ImageInfo
2900 *profile_info;
2901
anthonyafa3dfc2012-03-03 11:31:30 +00002902 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002903 { /* Remove a profile from the _image. */
2904 (void) ProfileImage(_image,arg1,(const unsigned char *)
2905 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002906 break;
2907 }
anthony92c93bd2012-03-19 14:02:47 +00002908 /* Associate a profile with the _image. */
2909 profile_info=CloneImageInfo(_image_info);
2910 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002911 if (profile != (StringInfo *) NULL)
2912 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002913 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002914 profile_info=DestroyImageInfo(profile_info);
2915 if (profile_image == (Image *) NULL)
2916 {
2917 StringInfo
2918 *profile;
2919
anthony92c93bd2012-03-19 14:02:47 +00002920 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002921 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002922 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002923 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002924 if (profile != (StringInfo *) NULL)
2925 {
anthony92c93bd2012-03-19 14:02:47 +00002926 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002927 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002928 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002929 profile=DestroyStringInfo(profile);
2930 }
2931 profile_info=DestroyImageInfo(profile_info);
2932 break;
2933 }
2934 ResetImageProfileIterator(profile_image);
2935 name=GetNextImageProfile(profile_image);
2936 while (name != (const char *) NULL)
2937 {
2938 profile=GetImageProfile(profile_image,name);
2939 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002940 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2941 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002942 name=GetNextImageProfile(profile_image);
2943 }
2944 profile_image=DestroyImage(profile_image);
2945 break;
2946 }
anthonyebb73a22012-03-22 14:25:52 +00002947 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002948 }
anthony805a2d42011-09-25 08:25:12 +00002949 case 'r':
2950 {
anthonyafa3dfc2012-03-03 11:31:30 +00002951 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002952 {
anthonyfd706f92012-01-19 04:22:02 +00002953 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002954 if ((flags & RhoValue) == 0)
2955 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyaa2c16c2012-03-25 22:21:35 +00002956 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002957 break;
2958 }
anthonyafa3dfc2012-03-03 11:31:30 +00002959 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002960 {
anthony7bcfe7f2012-03-30 14:01:22 +00002961 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002962 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002963 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002964 if ((flags & SigmaValue) == 0)
2965 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00002966 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002967 break;
2968 }
anthonyafa3dfc2012-03-03 11:31:30 +00002969 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002970 {
anthony7bcfe7f2012-03-30 14:01:22 +00002971 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002972 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002973 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002974 break;
2975 }
anthony975a8d72012-04-12 13:54:36 +00002976 if (LocaleCompare("recolor",option+1) == 0)
2977 {
anthony464f1c42012-04-22 08:51:01 +00002978 CLIWandWarnReplaced("-color-matrix");
anthony975a8d72012-04-12 13:54:36 +00002979 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
2980 }
anthonyafa3dfc2012-03-03 11:31:30 +00002981 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002982 {
anthony4837ac22012-05-18 23:39:48 +00002983 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002984 Image
2985 *remap_image;
2986
anthony92c93bd2012-03-19 14:02:47 +00002987 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002988 if (remap_image == (Image *) NULL)
2989 break;
anthony92c93bd2012-03-19 14:02:47 +00002990 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002991 remap_image=DestroyImage(remap_image);
2992 break;
2993 }
anthonyafa3dfc2012-03-03 11:31:30 +00002994 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002995 {
anthonyafa3dfc2012-03-03 11:31:30 +00002996 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00002997 {
anthony7bcfe7f2012-03-30 14:01:22 +00002998 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00002999 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3000 arg1);
3001 (void) ResetImagePage(_image,arg1);
3002 }
anthony31f1bf72012-01-30 12:37:22 +00003003 else
anthony92c93bd2012-03-19 14:02:47 +00003004 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003005 break;
3006 }
anthonyafa3dfc2012-03-03 11:31:30 +00003007 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003008 {
anthonyf46d4262012-03-26 03:30:34 +00003009 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00003010 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003011 if ((flags & (RhoValue|SigmaValue)) == 0)
3012 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003013 if ((flags & SigmaValue) == 0)
3014 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003015 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003016 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003017 break;
3018 }
anthonyafa3dfc2012-03-03 11:31:30 +00003019 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003020 {
anthony7bcfe7f2012-03-30 14:01:22 +00003021 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003022 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003023 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3024 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003025 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003026 break;
3027 }
anthonyafa3dfc2012-03-03 11:31:30 +00003028 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003029 {
anthony7bcfe7f2012-03-30 14:01:22 +00003030 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003031 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003032 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3033 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003034 break;
3035 }
anthonyafa3dfc2012-03-03 11:31:30 +00003036 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003037 {
anthony22de2722012-04-19 14:43:00 +00003038 flags=ParseGeometry(arg1,&geometry_info);
3039 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003040 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00003041 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00003042 break;
3043 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3044 break;
anthony92c93bd2012-03-19 14:02:47 +00003045 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003046 break;
3047 }
anthonyebb73a22012-03-22 14:25:52 +00003048 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003049 }
3050 case 's':
3051 {
anthonyafa3dfc2012-03-03 11:31:30 +00003052 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003053 {
anthonyfe1aa782012-03-24 13:43:04 +00003054 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003055 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003056 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003057 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3058 new_image=SampleImage(_image,geometry.width,geometry.height,
3059 _exception);
anthony805a2d42011-09-25 08:25:12 +00003060 break;
3061 }
anthonyafa3dfc2012-03-03 11:31:30 +00003062 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003063 {
anthonyfe1aa782012-03-24 13:43:04 +00003064 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003065 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003066 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003067 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3068 new_image=ScaleImage(_image,geometry.width,geometry.height,
3069 _exception);
anthony805a2d42011-09-25 08:25:12 +00003070 break;
3071 }
anthonyf42014d2012-03-25 09:53:06 +00003072 if (LocaleCompare("segment",option+1) == 0)
3073 {
anthonyf42014d2012-03-25 09:53:06 +00003074 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003075 if ((flags & (RhoValue|SigmaValue)) == 0)
3076 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003077 if ((flags & SigmaValue) == 0)
3078 geometry_info.sigma=1.0;
3079 (void) SegmentImage(_image,_image->colorspace,
3080 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3081 _exception);
3082 break;
3083 }
anthonyafa3dfc2012-03-03 11:31:30 +00003084 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003085 {
anthonyfd706f92012-01-19 04:22:02 +00003086 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003087 if ((flags & (RhoValue|SigmaValue)) == 0)
3088 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3089 if ((flags & SigmaValue) == 0)
3090 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003091 if ((flags & PercentValue) != 0)
3092 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003093 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003094 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003095 break;
3096 }
anthonyafa3dfc2012-03-03 11:31:30 +00003097 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003098 {
anthony31f1bf72012-01-30 12:37:22 +00003099 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003100 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003101 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003102 break;
3103 }
anthonyafa3dfc2012-03-03 11:31:30 +00003104 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003105 {
anthony7bcfe7f2012-03-30 14:01:22 +00003106 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003107 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3108 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3109 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003110 break;
3111 }
anthonyafa3dfc2012-03-03 11:31:30 +00003112 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003113 {
anthony4837ac22012-05-18 23:39:48 +00003114 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00003115 char
3116 *value;
3117
anthonyf42014d2012-03-25 09:53:06 +00003118 if (IfPlusOp) {
anthonyfd706f92012-01-19 04:22:02 +00003119 if (LocaleNCompare(arg1,"registry:",9) == 0)
3120 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003121 else
anthony31f1bf72012-01-30 12:37:22 +00003122 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003123 {
anthony92c93bd2012-03-19 14:02:47 +00003124 (void) DeleteImageOption(_image_info,arg1+7);
3125 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003126 }
3127 else
anthony92c93bd2012-03-19 14:02:47 +00003128 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003129 break;
3130 }
anthonyf42014d2012-03-25 09:53:06 +00003131 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003132 if (value == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00003133 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
3134 option);
anthonyfd706f92012-01-19 04:22:02 +00003135 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003136 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003137 else
anthonyfd706f92012-01-19 04:22:02 +00003138 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003139 {
anthony92c93bd2012-03-19 14:02:47 +00003140 (void) SetImageOption(_image_info,arg1+7,value);
3141 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003142 }
3143 else
anthony92c93bd2012-03-19 14:02:47 +00003144 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003145 value=DestroyString(value);
3146 break;
3147 }
anthonyafa3dfc2012-03-03 11:31:30 +00003148 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003149 {
anthonyfd706f92012-01-19 04:22:02 +00003150 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003151 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3152 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003153 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3154 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003155 break;
3156 }
anthonyafa3dfc2012-03-03 11:31:30 +00003157 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003158 {
anthonyfd706f92012-01-19 04:22:02 +00003159 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003160 if ((flags & (RhoValue|SigmaValue)) == 0)
3161 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003162 if ((flags & SigmaValue) == 0)
3163 geometry_info.sigma=1.0;
3164 if ((flags & XiValue) == 0)
3165 geometry_info.xi=4.0;
3166 if ((flags & PsiValue) == 0)
3167 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003168 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3169 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3170 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003171 break;
3172 }
anthonyafa3dfc2012-03-03 11:31:30 +00003173 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003174 {
anthonyfd706f92012-01-19 04:22:02 +00003175 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003176 if ((flags & (RhoValue|SigmaValue)) == 0)
3177 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003178 if ((flags & SigmaValue) == 0)
3179 geometry_info.sigma=1.0;
3180 if ((flags & XiValue) == 0)
3181 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003182 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3183 _exception);
anthony805a2d42011-09-25 08:25:12 +00003184 break;
3185 }
anthonyafa3dfc2012-03-03 11:31:30 +00003186 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003187 {
anthony7bcfe7f2012-03-30 14:01:22 +00003188 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003189 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003190 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3191 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003192 break;
3193 }
anthonyafa3dfc2012-03-03 11:31:30 +00003194 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003195 {
anthonyfd706f92012-01-19 04:22:02 +00003196 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003197 if ((flags & RhoValue) == 0)
3198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003199 if ((flags & SigmaValue) == 0)
3200 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003201 new_image=ShearImage(_image,geometry_info.rho,
3202 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003203 break;
3204 }
anthonyafa3dfc2012-03-03 11:31:30 +00003205 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003206 {
anthonyfd706f92012-01-19 04:22:02 +00003207 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003208 if ((flags & RhoValue) == 0)
3209 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003210 if ((flags & SigmaValue) == 0)
3211 geometry_info.sigma=(double) QuantumRange/2.0;
3212 if ((flags & PercentValue) != 0)
3213 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3214 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003215 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003216 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003217 break;
3218 }
anthonyafa3dfc2012-03-03 11:31:30 +00003219 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003220 {
anthonyfd706f92012-01-19 04:22:02 +00003221 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003222 if ((flags & (RhoValue|SigmaValue)) == 0)
3223 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003224 if ((flags & SigmaValue) == 0)
3225 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003226 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003227 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003228 break;
3229 }
anthonyafa3dfc2012-03-03 11:31:30 +00003230 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003231 {
anthony7bcfe7f2012-03-30 14:01:22 +00003232 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003233 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003234 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3235 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003236 break;
3237 }
anthonyafa3dfc2012-03-03 11:31:30 +00003238 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003239 {
anthonyf42014d2012-03-25 09:53:06 +00003240 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3241 if ( parse < 0 )
3242 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3243 option,arg1);
anthony964d28e2012-05-17 23:39:46 +00003244 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3245 _exception);
anthony805a2d42011-09-25 08:25:12 +00003246 break;
3247 }
anthonyafa3dfc2012-03-03 11:31:30 +00003248 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003249 {
anthony7bcfe7f2012-03-30 14:01:22 +00003250 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003251 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003252 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003253 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003254 break;
3255 }
anthonyafa3dfc2012-03-03 11:31:30 +00003256 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003257 {
anthonyb1e21ed2012-04-20 12:43:12 +00003258 flags=ParseGeometry(arg1,&geometry_info);
3259 if ((flags & RhoValue) == 0)
3260 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003261 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3262 _exception);
anthony805a2d42011-09-25 08:25:12 +00003263 break;
3264 }
anthonyafa3dfc2012-03-03 11:31:30 +00003265 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003266 {
anthony7bc87992012-03-25 02:32:51 +00003267 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3268 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003269 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003270 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003271 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003272 if ((flags & RhoValue) == 0)
3273 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003274 if ((flags & SigmaValue) == 0)
3275 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003276 new_image=StatisticImage(_image,(StatisticType)parse,
3277 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3278 _exception);
anthony805a2d42011-09-25 08:25:12 +00003279 break;
3280 }
anthonyafa3dfc2012-03-03 11:31:30 +00003281 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003282 {
anthony92c93bd2012-03-19 14:02:47 +00003283 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003284 break;
3285 }
anthonyafa3dfc2012-03-03 11:31:30 +00003286 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003287 {
anthonyb1e21ed2012-04-20 12:43:12 +00003288 flags=ParseGeometry(arg2,&geometry_info);
3289 if ((flags & RhoValue) == 0)
3290 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003291 new_image=SwirlImage(_image,geometry_info.rho,
3292 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003293 break;
3294 }
anthonyebb73a22012-03-22 14:25:52 +00003295 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003296 }
3297 case 't':
3298 {
anthonyafa3dfc2012-03-03 11:31:30 +00003299 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003300 {
3301 double
3302 threshold;
3303
anthony52bef752012-03-27 13:54:47 +00003304 threshold=(double) QuantumRange/2;
3305 if (normal_op) {
anthony7bcfe7f2012-03-30 14:01:22 +00003306 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003307 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003308 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003309 }
anthony92c93bd2012-03-19 14:02:47 +00003310 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003311 break;
3312 }
anthonyafa3dfc2012-03-03 11:31:30 +00003313 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003314 {
anthony7bcfe7f2012-03-30 14:01:22 +00003315 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003316 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003317 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3318 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3319 _exception);
anthony805a2d42011-09-25 08:25:12 +00003320 break;
3321 }
anthonyafa3dfc2012-03-03 11:31:30 +00003322 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003323 {
anthony7bcfe7f2012-03-30 14:01:22 +00003324 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003325 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003326 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003327 break;
3328 }
anthonyafa3dfc2012-03-03 11:31:30 +00003329 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003330 {
anthony464f1c42012-04-22 08:51:01 +00003331 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003332 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003333 break;
3334 }
anthonyafa3dfc2012-03-03 11:31:30 +00003335 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003336 {
3337 PixelInfo
3338 target;
3339
anthony92c93bd2012-03-19 14:02:47 +00003340 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3341 (void) TransparentPaintImage(_image,&target,(Quantum)
3342 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003343 break;
3344 }
anthonyafa3dfc2012-03-03 11:31:30 +00003345 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003346 {
anthony92c93bd2012-03-19 14:02:47 +00003347 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003348 break;
3349 }
anthonyafa3dfc2012-03-03 11:31:30 +00003350 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003351 {
anthony92c93bd2012-03-19 14:02:47 +00003352 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003353 break;
3354 }
anthonyafa3dfc2012-03-03 11:31:30 +00003355 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003356 {
anthony92c93bd2012-03-19 14:02:47 +00003357 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003358 break;
3359 }
anthonyafa3dfc2012-03-03 11:31:30 +00003360 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003361 {
anthonyab3a50c2011-10-27 11:48:57 +00003362 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003363 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003364 break;
3365 }
anthonyebb73a22012-03-22 14:25:52 +00003366 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003367 }
3368 case 'u':
3369 {
anthonyafa3dfc2012-03-03 11:31:30 +00003370 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003371 {
anthony52bef752012-03-27 13:54:47 +00003372 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3373 Option is not documented, bt appears to be for "identify".
3374 We may need a identify specific verbose!
3375 */
3376 if (plus_alt_op) {
anthony92c93bd2012-03-19 14:02:47 +00003377 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003378 break;
3379 }
anthony92c93bd2012-03-19 14:02:47 +00003380 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3381 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003382 break;
3383 }
anthonyafa3dfc2012-03-03 11:31:30 +00003384 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003385 {
anthony92c93bd2012-03-19 14:02:47 +00003386 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003387 break;
3388 }
anthonyafa3dfc2012-03-03 11:31:30 +00003389 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003390 {
anthonyfd706f92012-01-19 04:22:02 +00003391 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003392 if ((flags & (RhoValue|SigmaValue)) == 0)
3393 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003394 if ((flags & SigmaValue) == 0)
3395 geometry_info.sigma=1.0;
3396 if ((flags & XiValue) == 0)
3397 geometry_info.xi=1.0;
3398 if ((flags & PsiValue) == 0)
3399 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003400 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3401 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003402 break;
3403 }
anthonyebb73a22012-03-22 14:25:52 +00003404 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003405 }
3406 case 'v':
3407 {
anthonyafa3dfc2012-03-03 11:31:30 +00003408 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003409 {
anthonyafa3dfc2012-03-03 11:31:30 +00003410 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003411 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003412 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003413 */
anthony92c93bd2012-03-19 14:02:47 +00003414 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003415 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003416 break;
3417 }
anthonyafa3dfc2012-03-03 11:31:30 +00003418 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003419 {
anthonyfd706f92012-01-19 04:22:02 +00003420 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003421 if ((flags & (RhoValue|SigmaValue)) == 0)
3422 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003423 if ((flags & SigmaValue) == 0)
3424 geometry_info.sigma=1.0;
3425 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003426 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003427 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003428 geometry_info.psi=0.1*_image->rows;
3429 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003430 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3431 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003432 break;
3433 }
anthonyebb73a22012-03-22 14:25:52 +00003434 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003435 }
3436 case 'w':
3437 {
anthonyafa3dfc2012-03-03 11:31:30 +00003438 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003439 {
anthonyfd706f92012-01-19 04:22:02 +00003440 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003441 if ((flags & (RhoValue|SigmaValue)) == 0)
3442 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003443 if ((flags & SigmaValue) == 0)
3444 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003445 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3446 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003447 break;
3448 }
anthonyafa3dfc2012-03-03 11:31:30 +00003449 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003450 {
anthony7bcfe7f2012-03-30 14:01:22 +00003451 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003452 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003453 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003454 break;
3455 }
anthonyebb73a22012-03-22 14:25:52 +00003456 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003457 }
3458 default:
anthonyebb73a22012-03-22 14:25:52 +00003459 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003460 }
anthony964d28e2012-05-17 23:39:46 +00003461 /* clean up percent escape interpreted strings */
3462 if (arg1 != arg1n )
3463 arg1=DestroyString((char *)arg1);
3464 if (arg2 != arg2n )
3465 arg2=DestroyString((char *)arg2);
3466
3467 /* Replace current image with any image that was generated
3468 and set image point to last image (so image->next is correct) */
anthony805a2d42011-09-25 08:25:12 +00003469 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003470 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003471
anthony31f1bf72012-01-30 12:37:22 +00003472 return;
anthony92c93bd2012-03-19 14:02:47 +00003473#undef _image_info
3474#undef _draw_info
3475#undef _quantize_info
3476#undef _image
3477#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003478#undef IfNormalOp
3479#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003480#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003481#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003482}
anthonyfd706f92012-01-19 04:22:02 +00003483
anthony43f425d2012-02-26 12:58:58 +00003484WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003485 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003486{
3487 size_t
anthony43f425d2012-02-26 12:58:58 +00003488 n,
anthony31f1bf72012-01-30 12:37:22 +00003489 i;
3490
anthony43f425d2012-02-26 12:58:58 +00003491 assert(cli_wand != (MagickCLI *) NULL);
3492 assert(cli_wand->signature == WandSignature);
3493 assert(cli_wand->wand.signature == WandSignature);
3494 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003495 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003496 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003497
anthonyafa3dfc2012-03-03 11:31:30 +00003498#if !USE_WAND_METHODS
3499 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003500 i=0;
anthony43f425d2012-02-26 12:58:58 +00003501 n=GetImageListLength(cli_wand->wand.images);
3502 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003503 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003504 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003505 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003506 if ( cli_wand->wand.images->next == (Image *) NULL )
3507 break;
3508 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003509 }
anthony43f425d2012-02-26 12:58:58 +00003510 assert( i == n );
3511 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003512#else
3513 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003514 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
anthonyafa3dfc2012-03-03 11:31:30 +00003515 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3516 MagickResetIterator(&cli_wand->wand);
3517#endif
anthony31f1bf72012-01-30 12:37:22 +00003518 return;
anthony805a2d42011-09-25 08:25:12 +00003519}
3520
3521/*
3522%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3523% %
3524% %
3525% %
anthony43f425d2012-02-26 12:58:58 +00003526+ 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 +00003527% %
3528% %
3529% %
3530%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3531%
anthony43f425d2012-02-26 12:58:58 +00003532% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003533% entire image list as a whole. The result is often a complete replacment
3534% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003535%
3536% The format of the MogrifyImage method is:
3537%
anthony43f425d2012-02-26 12:58:58 +00003538% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003539% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003540%
3541% A description of each parameter follows:
3542%
anthony43f425d2012-02-26 12:58:58 +00003543% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003544%
anthony36a8c2c2012-02-10 00:08:44 +00003545% o option: The option string for the operation
3546%
anthony31f1bf72012-01-30 12:37:22 +00003547% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003548% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003549%
anthony805a2d42011-09-25 08:25:12 +00003550*/
anthony43f425d2012-02-26 12:58:58 +00003551WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthony964d28e2012-05-17 23:39:46 +00003552 const char *option,const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00003553{
anthony2a0ec8c2012-03-24 04:35:56 +00003554 ssize_t
3555 parse;
3556
anthony31f1bf72012-01-30 12:37:22 +00003557 Image
3558 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003559
anthony964d28e2012-05-17 23:39:46 +00003560 const char /* For percent escape interpretImageProperties() */
3561 *arg1,
3562 *arg2;
3563
anthony2e4501b2012-03-30 04:41:54 +00003564#define _image_info (cli_wand->wand.image_info)
3565#define _images (cli_wand->wand.images)
3566#define _exception (cli_wand->wand.exception)
3567#define _draw_info (cli_wand->draw_info)
3568#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00003569#define _process_flags (cli_wand->process_flags)
3570#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00003571#define IfNormalOp (*option=='-')
3572#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00003573#define normal_op IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003574
anthony43f425d2012-02-26 12:58:58 +00003575 assert(cli_wand != (MagickCLI *) NULL);
3576 assert(cli_wand->signature == WandSignature);
3577 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003578 assert(_images != (Image *) NULL); /* _images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003579 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003580 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003581
anthony964d28e2012-05-17 23:39:46 +00003582 /* Interpret Percent Escapes in Arguments - using first image */
3583 arg1 = arg1n;
3584 arg2 = arg2n;
3585 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3586 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3587 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3588 /* Interpret Percent escapes in argument 1 */
3589 if (arg1n != (char *) NULL) {
3590 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3591 if (arg1 == (char *) NULL) {
3592 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3593 arg1=arg1n; /* use the given argument as is */
3594 }
3595 }
3596 if (arg2n != (char *) NULL) {
3597 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3598 if (arg2 == (char *) NULL) {
3599 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3600 arg2=arg2n; /* use the given argument as is */
3601 }
3602 }
3603 }
anthony4837ac22012-05-18 23:39:48 +00003604#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00003605#undef _option_type
3606
3607#if 0
3608 (void) FormatLocaleFile(stderr,
3609 "CLIListOperatorImages: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
3610#endif
3611
3612
anthony31f1bf72012-01-30 12:37:22 +00003613 new_images=NewImageList();
3614
anthonyafa3dfc2012-03-03 11:31:30 +00003615 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003616 {
3617 case 'a':
3618 {
anthonyafa3dfc2012-03-03 11:31:30 +00003619 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003620 {
anthony92c93bd2012-03-19 14:02:47 +00003621 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003622 break;
3623 }
anthonyafa3dfc2012-03-03 11:31:30 +00003624 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003625 {
anthony464f1c42012-04-22 08:51:01 +00003626 CLIWandWarnReplaced("-evaluate-sequence Mean");
anthonyafa3dfc2012-03-03 11:31:30 +00003627 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003628 break;
3629 }
anthonyebb73a22012-03-22 14:25:52 +00003630 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003631 }
3632 case 'c':
3633 {
cristy5f257b22012-03-07 00:27:29 +00003634 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003635 {
anthony92c93bd2012-03-19 14:02:47 +00003636 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003637 break;
3638 }
anthonyafa3dfc2012-03-03 11:31:30 +00003639 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003640 {
anthony805a2d42011-09-25 08:25:12 +00003641 Image
anthony31f1bf72012-01-30 12:37:22 +00003642 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003643
anthonyafa3dfc2012-03-03 11:31:30 +00003644 /* FUTURE - make this a compose option, and thus can be used
3645 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003646 _images.
cristy87c02f42012-02-24 00:19:10 +00003647 */
anthony92c93bd2012-03-19 14:02:47 +00003648 new_images=RemoveFirstImageFromList(&_images);
3649 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003650 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003651 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003652 break;
cristye52fb5e2012-04-06 23:30:20 +00003653 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003654 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003655 break;
3656 }
anthonyafa3dfc2012-03-03 11:31:30 +00003657 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003658 {
anthony92c93bd2012-03-19 14:02:47 +00003659 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003660 break;
3661 }
anthonyafa3dfc2012-03-03 11:31:30 +00003662 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003663 {
anthony43f425d2012-02-26 12:58:58 +00003664 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003665 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003666 break;
3667 }
anthonyafa3dfc2012-03-03 11:31:30 +00003668 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003669 {
cristyfeb3e962012-03-29 17:25:55 +00003670 CompositeOperator
3671 compose;
3672
3673 const char*
3674 value;
3675
3676 MagickBooleanType
3677 clip_to_self;
3678
anthony805a2d42011-09-25 08:25:12 +00003679 Image
3680 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003681 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003682
3683 RectangleInfo
3684 geometry;
3685
anthony7bcfe7f2012-03-30 14:01:22 +00003686 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003687 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003688 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003689 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003690 else
3691 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3692 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003693
anthony7bcfe7f2012-03-30 14:01:22 +00003694 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003695 value=GetImageOption(_image_info,"compose:clip-to-self");
3696 if (value == (const char *) NULL)
3697 clip_to_self=MagickTrue;
3698 else
3699 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3700 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003701 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003702 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003703 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003704 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003705 }
3706
anthony92c93bd2012-03-19 14:02:47 +00003707 new_images=RemoveFirstImageFromList(&_images);
3708 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003709 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003710 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003711
anthony31f1bf72012-01-30 12:37:22 +00003712 /* FUTURE - this should not be here! - should be part of -geometry */
3713 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003714 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003715
anthony31f1bf72012-01-30 12:37:22 +00003716 SetGeometry(source_image,&geometry);
3717 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3718 GravityAdjustGeometry(new_images->columns,new_images->rows,
3719 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003720
anthony92c93bd2012-03-19 14:02:47 +00003721 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003722 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003723 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003724 if ((compose == DisplaceCompositeOp) ||
anthony7bcfe7f2012-03-30 14:01:22 +00003725 (compose == DistortCompositeOp)) {
3726 /* Merge Y displacement into X displace/distort map. */
3727 (void) CompositeImage(source_image,mask_image,
3728 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3729 mask_image=DestroyImage(mask_image);
3730 }
3731 else {
3732 /* Set a blending mask for the composition. */
3733 (void) NegateImage(mask_image,MagickFalse,_exception);
cristy665e18f2012-05-17 12:39:54 +00003734 (void) SetImageMask(source_image,mask_image,_exception);
anthony7bcfe7f2012-03-30 14:01:22 +00003735 mask_image=DestroyImage(mask_image);
3736 }
anthony805a2d42011-09-25 08:25:12 +00003737 }
cristyfeb3e962012-03-29 17:25:55 +00003738 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3739 geometry.x,geometry.y,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003740 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003741 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003742 break;
3743 }
anthonyebb73a22012-03-22 14:25:52 +00003744 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003745 }
3746 case 'd':
3747 {
anthonyafa3dfc2012-03-03 11:31:30 +00003748 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003749 {
anthony464f1c42012-04-22 08:51:01 +00003750 CLIWandWarnReplaced("-layer CompareAny");
anthonyafa3dfc2012-03-03 11:31:30 +00003751 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003752 break;
3753 }
anthonyafa3dfc2012-03-03 11:31:30 +00003754 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003755 {
anthonyafa3dfc2012-03-03 11:31:30 +00003756 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003757 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003758 else
anthony92c93bd2012-03-19 14:02:47 +00003759 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003760 break;
3761 }
anthonyafa3dfc2012-03-03 11:31:30 +00003762 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003763 {
anthonyafa3dfc2012-03-03 11:31:30 +00003764 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003765 {
3766 const char
3767 *p;
3768
3769 size_t
3770 number_duplicates;
3771
anthony7bcfe7f2012-03-30 14:01:22 +00003772 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003773 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3774 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003775 number_duplicates=(size_t) StringToLong(arg1);
3776 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003777 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003778 new_images=DuplicateImages(_images,number_duplicates,"-1",
3779 _exception);
anthony805a2d42011-09-25 08:25:12 +00003780 else
anthony92c93bd2012-03-19 14:02:47 +00003781 new_images=DuplicateImages(_images,number_duplicates,p,
3782 _exception);
anthony805a2d42011-09-25 08:25:12 +00003783 }
anthonyafa3dfc2012-03-03 11:31:30 +00003784 else
anthony92c93bd2012-03-19 14:02:47 +00003785 new_images=DuplicateImages(_images,1,"-1",_exception);
3786 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003787 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003788 break;
3789 }
anthonyebb73a22012-03-22 14:25:52 +00003790 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003791 }
3792 case 'e':
3793 {
anthonyafa3dfc2012-03-03 11:31:30 +00003794 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003795 {
anthony2a0ec8c2012-03-24 04:35:56 +00003796 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3797 if ( parse < 0 )
3798 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3799 option,arg1);
3800 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3801 _exception);
anthony805a2d42011-09-25 08:25:12 +00003802 break;
3803 }
anthonyebb73a22012-03-22 14:25:52 +00003804 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003805 }
3806 case 'f':
3807 {
anthonyafa3dfc2012-03-03 11:31:30 +00003808 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003809 {
anthony92c93bd2012-03-19 14:02:47 +00003810 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003811 break;
3812 }
anthonyafa3dfc2012-03-03 11:31:30 +00003813 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003814 {
anthony319dac62012-03-06 04:12:44 +00003815 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003816 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003817 break;
3818 }
anthonyafa3dfc2012-03-03 11:31:30 +00003819 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003820 {
anthony92c93bd2012-03-19 14:02:47 +00003821 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003822 break;
3823 }
anthonyebb73a22012-03-22 14:25:52 +00003824 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003825 }
3826 case 'h':
3827 {
anthonyafa3dfc2012-03-03 11:31:30 +00003828 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003829 {
anthony31f1bf72012-01-30 12:37:22 +00003830 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003831 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003832 */
anthony805a2d42011-09-25 08:25:12 +00003833 Image
anthony31f1bf72012-01-30 12:37:22 +00003834 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003835
anthony92c93bd2012-03-19 14:02:47 +00003836 new_images=RemoveFirstImageFromList(&_images);
3837 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003838 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003839 break;
anthony92c93bd2012-03-19 14:02:47 +00003840 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003841 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003842 break;
3843 }
anthonyebb73a22012-03-22 14:25:52 +00003844 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003845 }
3846 case 'i':
3847 {
anthonyafa3dfc2012-03-03 11:31:30 +00003848 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003849 {
3850 Image
anthony805a2d42011-09-25 08:25:12 +00003851 *magnitude_image,
3852 *phase_image;
3853
anthony92c93bd2012-03-19 14:02:47 +00003854 magnitude_image=RemoveFirstImageFromList(&_images);
3855 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003856 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003857 if (phase_image == (Image *) NULL)
3858 break;
3859 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003860 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003861 magnitude_image=DestroyImage(magnitude_image);
3862 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003863 break;
3864 }
anthonyafa3dfc2012-03-03 11:31:30 +00003865 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003866 {
3867 Image
anthony31f1bf72012-01-30 12:37:22 +00003868 *insert_image,
3869 *index_image;
3870
3871 ssize_t
3872 index;
anthony805a2d42011-09-25 08:25:12 +00003873
anthony7bcfe7f2012-03-30 14:01:22 +00003874 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00003875 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003876 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003877 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003878 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003879 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003880 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003881 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003882 PrependImageToList(&_images,insert_image);
3883 else if (index == (ssize_t) GetImageListLength(_images))
3884 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003885 else
anthony43f425d2012-02-26 12:58:58 +00003886 {
anthony92c93bd2012-03-19 14:02:47 +00003887 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003888 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00003889 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00003890 InsertImageInList(&index_image,insert_image);
3891 }
anthony92c93bd2012-03-19 14:02:47 +00003892 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003893 break;
3894 }
anthonyebb73a22012-03-22 14:25:52 +00003895 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003896 }
3897 case 'l':
3898 {
anthonyafa3dfc2012-03-03 11:31:30 +00003899 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003900 {
anthonyfe1aa782012-03-24 13:43:04 +00003901 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3902 if ( parse < 0 )
3903 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3904 option,arg1);
3905 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00003906 {
3907 case CoalesceLayer:
3908 {
anthony92c93bd2012-03-19 14:02:47 +00003909 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003910 break;
3911 }
3912 case CompareAnyLayer:
3913 case CompareClearLayer:
3914 case CompareOverlayLayer:
3915 default:
3916 {
anthonyfe1aa782012-03-24 13:43:04 +00003917 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
3918 _exception);
anthony805a2d42011-09-25 08:25:12 +00003919 break;
3920 }
3921 case MergeLayer:
3922 case FlattenLayer:
3923 case MosaicLayer:
3924 case TrimBoundsLayer:
3925 {
anthonyfe1aa782012-03-24 13:43:04 +00003926 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
3927 _exception);
anthony805a2d42011-09-25 08:25:12 +00003928 break;
3929 }
3930 case DisposeLayer:
3931 {
anthony92c93bd2012-03-19 14:02:47 +00003932 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003933 break;
3934 }
3935 case OptimizeImageLayer:
3936 {
anthony92c93bd2012-03-19 14:02:47 +00003937 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003938 break;
3939 }
3940 case OptimizePlusLayer:
3941 {
anthony92c93bd2012-03-19 14:02:47 +00003942 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003943 break;
3944 }
3945 case OptimizeTransLayer:
3946 {
anthony92c93bd2012-03-19 14:02:47 +00003947 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003948 break;
3949 }
3950 case RemoveDupsLayer:
3951 {
anthony92c93bd2012-03-19 14:02:47 +00003952 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003953 break;
3954 }
3955 case RemoveZeroLayer:
3956 {
anthony92c93bd2012-03-19 14:02:47 +00003957 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003958 break;
3959 }
3960 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003961 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003962 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003963 if (new_images == (Image *) NULL)
3964 break;
anthony92c93bd2012-03-19 14:02:47 +00003965 _images=DestroyImageList(_images);
3966 _images=OptimizeImageLayers(new_images,_exception);
3967 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003968 break;
3969 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00003970 OptimizeImageTransparency(_images,_exception);
3971 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3972 _exception);
anthony805a2d42011-09-25 08:25:12 +00003973 break;
3974 }
3975 case CompositeLayer:
3976 {
anthony805a2d42011-09-25 08:25:12 +00003977 Image
3978 *source;
3979
3980 RectangleInfo
3981 geometry;
3982
anthony31f1bf72012-01-30 12:37:22 +00003983 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003984 compose;
3985
3986 const char*
3987 value;
3988
anthony92c93bd2012-03-19 14:02:47 +00003989 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003990 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003991 if (value != (const char *) NULL)
3992 compose=(CompositeOperator) ParseCommandOption(
3993 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003994
anthony31f1bf72012-01-30 12:37:22 +00003995 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00003996 source=_images;
anthony805a2d42011-09-25 08:25:12 +00003997 while (source != (Image *) NULL)
3998 {
3999 source=GetNextImageInList(source);
4000 if ((source != (Image *) NULL) &&
4001 (LocaleCompare(source->magick,"NULL") == 0))
4002 break;
4003 }
4004 if (source != (Image *) NULL)
4005 {
4006 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4007 (GetNextImageInList(source) == (Image *) NULL))
4008 source=(Image *) NULL;
4009 else
anthony31f1bf72012-01-30 12:37:22 +00004010 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004011 source=SplitImageList(source->previous);
4012 DeleteImageFromList(&source);
4013 }
4014 }
4015 if (source == (Image *) NULL)
4016 {
anthony92c93bd2012-03-19 14:02:47 +00004017 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004018 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004019 break;
4020 }
anthony31f1bf72012-01-30 12:37:22 +00004021 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004022 SetGeometry(_images,&geometry);
4023 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004024 geometry.width=source->page.width != 0 ?
4025 source->page.width : source->columns;
4026 geometry.height=source->page.height != 0 ?
4027 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004028 GravityAdjustGeometry(_images->page.width != 0 ?
4029 _images->page.width : _images->columns,
4030 _images->page.height != 0 ? _images->page.height :
4031 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004032
anthony31f1bf72012-01-30 12:37:22 +00004033 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004034 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4035 _exception);
anthony805a2d42011-09-25 08:25:12 +00004036 source=DestroyImageList(source);
4037 break;
4038 }
4039 }
anthony805a2d42011-09-25 08:25:12 +00004040 break;
4041 }
anthonyebb73a22012-03-22 14:25:52 +00004042 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004043 }
4044 case 'm':
4045 {
anthonyafa3dfc2012-03-03 11:31:30 +00004046 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004047 {
anthony464f1c42012-04-22 08:51:01 +00004048 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00004049 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004050 break;
4051 }
anthonyafa3dfc2012-03-03 11:31:30 +00004052 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004053 {
4054 Image
4055 *morph_image;
4056
anthony7bcfe7f2012-03-30 14:01:22 +00004057 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004058 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004059 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4060 _exception);
anthony805a2d42011-09-25 08:25:12 +00004061 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004062 break;
anthony92c93bd2012-03-19 14:02:47 +00004063 _images=DestroyImageList(_images);
4064 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004065 break;
4066 }
anthonyafa3dfc2012-03-03 11:31:30 +00004067 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004068 {
anthony319dac62012-03-06 04:12:44 +00004069 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00004070 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004071 break;
4072 }
anthonyebb73a22012-03-22 14:25:52 +00004073 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004074 }
4075 case 'p':
4076 {
anthonyafa3dfc2012-03-03 11:31:30 +00004077 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004078 {
anthony964d28e2012-05-17 23:39:46 +00004079 (void) FormatLocaleFile(stdout,"%s",arg1);
anthony24aa8822012-03-11 00:56:06 +00004080 break;
anthony805a2d42011-09-25 08:25:12 +00004081 }
anthonyafa3dfc2012-03-03 11:31:30 +00004082 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004083 {
anthonyb1d483a2012-04-14 12:53:56 +00004084 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00004085 char
4086 **arguments;
4087
4088 int
4089 j,
4090 number_arguments;
4091
anthony31f1bf72012-01-30 12:37:22 +00004092 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004093 if (arguments == (char **) NULL)
4094 break;
anthony31f1bf72012-01-30 12:37:22 +00004095 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004096 {
4097 char
4098 breaker,
4099 quote,
4100 *token;
4101
4102 const char
4103 *arguments;
4104
4105 int
4106 next,
4107 status;
4108
4109 size_t
4110 length;
4111
4112 TokenInfo
4113 *token_info;
4114
4115 /*
anthony24aa8822012-03-11 00:56:06 +00004116 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004117 */
anthony31f1bf72012-01-30 12:37:22 +00004118 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004119 token=(char *) NULL;
4120 if (~length >= (MaxTextExtent-1))
4121 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4122 sizeof(*token));
4123 if (token == (char *) NULL)
4124 break;
4125 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004126 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004127 token_info=AcquireTokenInfo();
4128 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4129 "\"",'\0',&breaker,&next,&quote);
4130 token_info=DestroyTokenInfo(token_info);
4131 if (status == 0)
4132 {
4133 const char
4134 *argv;
4135
4136 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004137 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4138 _exception);
anthony805a2d42011-09-25 08:25:12 +00004139 }
4140 token=DestroyString(token);
4141 break;
4142 }
4143 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004144 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4145 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004146 for (j=0; j < number_arguments; j++)
4147 arguments[j]=DestroyString(arguments[j]);
4148 arguments=(char **) RelinquishMagickMemory(arguments);
4149 break;
4150 }
anthonyebb73a22012-03-22 14:25:52 +00004151 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004152 }
4153 case 'r':
4154 {
anthonyafa3dfc2012-03-03 11:31:30 +00004155 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004156 {
anthony92c93bd2012-03-19 14:02:47 +00004157 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004158 break;
4159 }
anthonyafa3dfc2012-03-03 11:31:30 +00004160 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004161 {
anthony92c93bd2012-03-19 14:02:47 +00004162 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004163 break;
4164 }
anthonyebb73a22012-03-22 14:25:52 +00004165 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004166 }
4167 case 's':
4168 {
anthonyafa3dfc2012-03-03 11:31:30 +00004169 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004170 {
anthonycd358fc2012-04-16 13:59:03 +00004171 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004172 ssize_t
4173 offset;
4174
anthony7bcfe7f2012-03-30 14:01:22 +00004175 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004176 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004177 offset=(ssize_t) StringToLong(arg1);
anthonycd358fc2012-04-16 13:59:03 +00004178 new_images=SmushImages(_images,normal_op,offset,_exception);
4179 break;
4180 }
4181 if (LocaleCompare("subimage",option+1) == 0)
4182 {
4183 Image
4184 *base_image,
4185 *compare_image;
4186
4187 const char *
4188 value;
4189
4190 MetricType
4191 metric;
4192
4193 double
4194 similarity;
4195
4196 RectangleInfo
4197 offset;
4198
4199 base_image=GetImageFromList(_images,0);
4200 compare_image=GetImageFromList(_images,1);
4201
4202 /* Comparision Metric */
4203 metric=UndefinedMetric;
4204 value=GetImageOption(_image_info,"metric");
4205 if (value != (const char *) NULL)
4206 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4207 MagickFalse,value);
4208
4209 new_images=SimilarityImage(base_image,compare_image,metric,
4210 &offset,&similarity,_exception);
4211
4212 if ( new_images != (Image *)NULL ) {
4213 char
4214 result[MaxTextExtent];
4215
4216 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
4217 (void) SetImageProperty(new_images,"subimage:similarity",result,
4218 _exception);
4219 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4220 (long) offset.x);
4221 (void) SetImageProperty(new_images,"subimage:x",result,
4222 _exception);
4223 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4224 (long) offset.y);
4225 (void) SetImageProperty(new_images,"subimage:y",result,
4226 _exception);
4227 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
4228 (unsigned long) offset.width,(unsigned long) offset.height,
4229 (long) offset.x,(long) offset.y);
4230 (void) SetImageProperty(new_images,"subimage:offset",result,
4231 _exception);
4232 }
anthony805a2d42011-09-25 08:25:12 +00004233 break;
4234 }
anthony0ea037a2012-04-03 12:14:39 +00004235 if (LocaleCompare("swap",option+1) == 0) {
4236 Image
4237 *p,
4238 *q,
4239 *swap;
anthony805a2d42011-09-25 08:25:12 +00004240
anthony0ea037a2012-04-03 12:14:39 +00004241 ssize_t
4242 index,
4243 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004244
anthony0ea037a2012-04-03 12:14:39 +00004245 index=-1;
4246 swap_index=-2;
4247 if (IfNormalOp) {
4248 GeometryInfo
4249 geometry_info;
4250
4251 MagickStatusType
4252 flags;
4253
4254 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004255 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00004256 if ((flags & RhoValue) != 0)
4257 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004258 index=(ssize_t) geometry_info.rho;
4259 if ((flags & SigmaValue) != 0)
4260 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004261 }
anthony0ea037a2012-04-03 12:14:39 +00004262 p=GetImageFromList(_images,index);
4263 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004264 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4265 if (IfNormalOp)
4266 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4267 else
4268 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4269 }
anthony0ea037a2012-04-03 12:14:39 +00004270 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004271 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004272 swap=CloneImage(p,0,0,MagickTrue,_exception);
4273 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4274 ReplaceImageInList(&q,swap);
4275 _images=GetFirstImageInList(q);
4276 break;
4277 }
anthonyebb73a22012-03-22 14:25:52 +00004278 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004279 }
anthony805a2d42011-09-25 08:25:12 +00004280 default:
anthonyebb73a22012-03-22 14:25:52 +00004281 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004282 }
anthony964d28e2012-05-17 23:39:46 +00004283
4284 /* clean up percent escape interpreted strings */
4285 if (arg1 != arg1n )
4286 arg1=DestroyString((char *)arg1);
4287 if (arg2 != arg2n )
4288 arg2=DestroyString((char *)arg2);
4289
4290 /* if new image list generated, replace existing image list */
anthony31f1bf72012-01-30 12:37:22 +00004291 if (new_images == (Image *) NULL)
4292 return;
anthony964d28e2012-05-17 23:39:46 +00004293 _images=DestroyImageList(_images);
anthony92c93bd2012-03-19 14:02:47 +00004294 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004295 return;
4296
anthony92c93bd2012-03-19 14:02:47 +00004297#undef _image_info
4298#undef _images
4299#undef _exception
4300#undef _draw_info
4301#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004302#undef IfNormalOp
4303#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004304#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004305}
anthony43f425d2012-02-26 12:58:58 +00004306
4307/*
4308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4309% %
4310% %
4311% %
anthony964d28e2012-05-17 23:39:46 +00004312+ 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 +00004313% %
4314% %
4315% %
4316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4317%
anthony464f1c42012-04-22 08:51:01 +00004318% CLINoImageOperator() Applies operations that may not actually need images
anthony964d28e2012-05-17 23:39:46 +00004319% in an image list.
anthony43f425d2012-02-26 12:58:58 +00004320%
anthony4837ac22012-05-18 23:39:48 +00004321% The classic operators of this type is "-read", which actually creates
4322% images even when no images are present. Or image stack operators, which
4323% can be applied (push or pop) to an empty image list.
anthonyafa3dfc2012-03-03 11:31:30 +00004324%
anthony4837ac22012-05-18 23:39:48 +00004325% Note that these operators may involve other special 'option' prefix
4326% characters other than '-' or '+', namely parenthesis and braces.
anthony43f425d2012-02-26 12:58:58 +00004327%
anthony464f1c42012-04-22 08:51:01 +00004328% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004329%
anthony464f1c42012-04-22 08:51:01 +00004330% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4331% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004332%
4333% A description of each parameter follows:
4334%
4335% o cli_wand: the main CLI Wand to use.
4336%
4337% o option: The special option (with any switch char) to process
4338%
anthony464f1c42012-04-22 08:51:01 +00004339% o arg1 & arg2: Argument for option, if required
4340% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004341%
4342*/
anthony464f1c42012-04-22 08:51:01 +00004343WandExport void CLINoImageOperator(MagickCLI *cli_wand,
4344 const char *option, const char *arg1, const char *magick_unused(arg2))
anthony43f425d2012-02-26 12:58:58 +00004345{
anthony4837ac22012-05-18 23:39:48 +00004346#if 0
4347 const char /* For percent escape interpretImageProperties() */
4348 *arg1,
4349 *arg2;
4350#endif
4351
anthony8226e722012-04-05 14:25:46 +00004352#define _image_info (cli_wand->wand.image_info)
4353#define _images (cli_wand->wand.images)
4354#define _exception (cli_wand->wand.exception)
4355#define IfNormalOp (*option=='-')
4356#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004357
4358 assert(cli_wand != (MagickCLI *) NULL);
4359 assert(cli_wand->signature == WandSignature);
4360 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +00004361 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00004362 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4363
anthonyde897b72012-04-27 00:16:17 +00004364#if 0
anthony4837ac22012-05-18 23:39:48 +00004365 Not able to be used as their may not be any images!
4366 Also the only option that may have arguments that can be percent escaped is
4367 "-clone".
anthony52bef752012-03-27 13:54:47 +00004368
anthony4837ac22012-05-18 23:39:48 +00004369#define _process_flags (cli_wand->process_flags)
4370#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
4371 /* Interpret Percent Escapes in Arguments - using first image */
4372 arg1 = arg1n;
4373 arg2 = arg2n;
4374 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4375 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4376 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4377 /* Interpret Percent escapes in argument 1 */
4378 if (arg1n != (char *) NULL) {
4379 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4380 if (arg1 == (char *) NULL) {
4381 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4382 arg1=arg1n; /* use the given argument as is */
4383 }
4384 }
4385 if (arg2n != (char *) NULL) {
4386 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4387 if (arg2 == (char *) NULL) {
4388 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4389 arg2=arg2n; /* use the given argument as is */
4390 }
4391 }
4392 }
4393#undef _process_flags
4394#undef _option_type
anthonyde897b72012-04-27 00:16:17 +00004395#endif
anthony4837ac22012-05-18 23:39:48 +00004396
4397 do { /* break to exit code */
4398 /*
4399 No-op options (ignore these)
4400 */
4401 if (LocaleCompare("noop",option+1) == 0) /* no argument */
4402 break;
4403 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4404 break;
4405 if (LocaleCompare("sans0",option+1) == 0) /* no argument */
4406 break;
4407 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4408 break;
4409 /*
4410 Image Reading
4411 */
4412 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4413 ( LocaleCompare("--",option) == 0 ) ) {
4414 /* Do Glob filename Expansion for 'arg1' then read all images.
4415 *
4416 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4417 * (but attaching to the filenames in the generated argument list) any
4418 * [...] read modifiers that may be present.
4419 *
4420 * For example: It will expand '*.gif[20x20]' into a list such as
4421 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4422 *
4423 * NOTE: In IMv6 this was done globally across all images. This
4424 * meant you could include IM options in '@filename' lists, but you
4425 * could not include comments. Doing it only for image read makes
4426 * it far more secure.
4427 *
4428 * Note: arguments do not have percent escapes expanded for security
4429 * reasons.
4430 */
4431 int argc;
4432 char **argv;
4433 ssize_t i;
4434
4435 argc = 1;
4436 argv = (char **) &arg1;
4437
4438 /* Expand 'glob' expressions in the given filename.
4439 Expansion handles any 'coder:' prefix, or read modifiers attached
4440 to the filename, including them in the resulting expanded list.
4441 */
4442 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4443 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4444 option,GetExceptionMessage(errno));
4445
4446 /* loop over expanded filename list, and read then all in */
4447 for (i=0; i<argc; i++) {
4448 Image *
4449 new_images;
4450 if (IfMagickTrue(_image_info->ping))
4451 new_images=PingImages(_image_info,argv[i],_exception);
4452 else
4453 new_images=ReadImages(_image_info,argv[i],_exception);
4454 AppendImageToList(&_images, new_images);
4455 }
4456 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4457 break;
4458 }
4459 /*
4460 Image Writing
4461 Note: Writing a empty image list is valid in specific cases
4462 */
4463 if (LocaleCompare("write",option+1) == 0) {
4464 /* Note: arguments do not have percent escapes expanded */
4465 char
4466 key[MaxTextExtent];
4467
4468 Image
4469 *write_images;
4470
4471 ImageInfo
4472 *write_info;
4473
4474 /* Need images, unless a "null:" output coder is used */
4475 if ( cli_wand->wand.images == (Image *) NULL ) {
4476 if ( LocaleCompare(arg1,"null:") == 0 )
4477 break;
4478 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4479 }
4480
4481 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4482 (void) DeleteImageRegistry(key);
4483 write_images=_images;
4484 if (IfPlusOp)
4485 write_images=CloneImageList(_images,_exception);
4486 write_info=CloneImageInfo(_image_info);
4487 (void) WriteImages(write_info,write_images,arg1,_exception);
4488 write_info=DestroyImageInfo(write_info);
4489 if (IfPlusOp)
4490 write_images=DestroyImageList(write_images);
4491 break;
4492 }
4493 /*
4494 Parenthesis and Brace operations
4495 */
4496 if (LocaleCompare("(",option) == 0) {
4497 /* stack 'push' images */
4498 Stack
4499 *node;
4500
4501 size_t
4502 size;
4503
4504 size=0;
4505 node=cli_wand->image_list_stack;
4506 for ( ; node != (Stack *)NULL; node=node->next)
4507 size++;
4508 if ( size >= MAX_STACK_DEPTH )
4509 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4510 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4511 if (node == (Stack *) NULL)
4512 CLIWandExceptionBreak(ResourceLimitFatalError,
4513 "MemoryAllocationFailed",option);
4514 node->data = (void *)cli_wand->wand.images;
4515 cli_wand->wand.images = NewImageList();
4516 node->next = cli_wand->image_list_stack;
4517 cli_wand->image_list_stack = node;
4518
4519 /* handle respect-parenthesis */
4520 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4521 "respect-parenthesis"))))
4522 option="{"; /* fall-thru so as to push image settings too */
anthony52bef752012-03-27 13:54:47 +00004523 else
anthony4837ac22012-05-18 23:39:48 +00004524 break;
4525 /* fall thru to next if */
anthony52bef752012-03-27 13:54:47 +00004526 }
anthony4837ac22012-05-18 23:39:48 +00004527 if (LocaleCompare("{",option) == 0) {
4528 /* stack 'push' of image_info settings */
4529 Stack
4530 *node;
anthony8226e722012-04-05 14:25:46 +00004531
anthony4837ac22012-05-18 23:39:48 +00004532 size_t
4533 size;
anthony8226e722012-04-05 14:25:46 +00004534
anthony4837ac22012-05-18 23:39:48 +00004535 size=0;
4536 node=cli_wand->image_info_stack;
4537 for ( ; node != (Stack *)NULL; node=node->next)
4538 size++;
4539 if ( size >= MAX_STACK_DEPTH )
4540 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4541 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4542 if (node == (Stack *) NULL)
4543 CLIWandExceptionBreak(ResourceLimitFatalError,
4544 "MemoryAllocationFailed",option);
anthony8226e722012-04-05 14:25:46 +00004545
anthony4837ac22012-05-18 23:39:48 +00004546 node->data = (void *)cli_wand->wand.image_info;
4547 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4548 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4549 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4550 option);
4551 cli_wand->wand.image_info = (ImageInfo *)node->data;
4552 node = (Stack *)RelinquishMagickMemory(node);
4553 break;
4554 }
4555
4556 node->next = cli_wand->image_info_stack;
4557 cli_wand->image_info_stack = node;
4558
4559 break;
anthony8226e722012-04-05 14:25:46 +00004560 }
anthony4837ac22012-05-18 23:39:48 +00004561 if (LocaleCompare(")",option) == 0) {
4562 /* pop images from stack */
4563 Stack
4564 *node;
anthony8226e722012-04-05 14:25:46 +00004565
anthony4837ac22012-05-18 23:39:48 +00004566 node = (Stack *)cli_wand->image_list_stack;
4567 if ( node == (Stack *)NULL)
4568 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4569 cli_wand->image_list_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004570
anthony4837ac22012-05-18 23:39:48 +00004571 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4572 cli_wand->wand.images= (Image *)node->data;
4573 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004574
anthony4837ac22012-05-18 23:39:48 +00004575 /* handle respect-parenthesis - of the previous 'pushed' settings */
4576 node = cli_wand->image_info_stack;
4577 if ( node != (Stack *)NULL)
4578 {
4579 if (IfMagickTrue(IsStringTrue(GetImageOption(
4580 cli_wand->wand.image_info,"respect-parenthesis"))))
4581 option="}"; /* fall-thru so as to pop image settings too */
4582 else
4583 break;
4584 }
4585 else
4586 break;
4587 /* fall thru to next if */
4588 }
4589 if (LocaleCompare("}",option) == 0) {
4590 /* pop image_info settings from stack */
4591 Stack
4592 *node;
anthony43f425d2012-02-26 12:58:58 +00004593
anthony4837ac22012-05-18 23:39:48 +00004594 node = (Stack *)cli_wand->image_info_stack;
4595 if ( node == (Stack *)NULL)
4596 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4597 cli_wand->image_info_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004598
anthony4837ac22012-05-18 23:39:48 +00004599 (void) DestroyImageInfo(cli_wand->wand.image_info);
anthony43f425d2012-02-26 12:58:58 +00004600 cli_wand->wand.image_info = (ImageInfo *)node->data;
4601 node = (Stack *)RelinquishMagickMemory(node);
anthony4837ac22012-05-18 23:39:48 +00004602
4603 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4604 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4605 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4606
4607 break;
4608 }
4609 if (LocaleCompare("clone",option+1) == 0) {
4610 Image
4611 *new_images;
4612
4613 if (*option == '+')
4614 arg1="-1";
4615 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4616 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
4617 if ( cli_wand->image_list_stack == (Stack *)NULL)
4618 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4619 new_images = (Image *)cli_wand->image_list_stack->data;
4620 if (new_images == (Image *) NULL)
4621 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4622 new_images=CloneImages(new_images,arg1,_exception);
4623 if (new_images == (Image *) NULL)
4624 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4625 AppendImageToList(&_images,new_images);
4626 break;
4627 }
4628 /*
4629 Informational Operations
4630
4631 Note that these do not require either cli-wand or images!
4632 */
4633 if (LocaleCompare("version",option+1) == 0) {
4634 (void) FormatLocaleFile(stdout,"Version: %s\n",
4635 GetMagickVersion((size_t *) NULL));
4636 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4637 GetMagickCopyright());
4638 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4639 GetMagickFeatures());
4640 break;
4641 }
4642 if (LocaleCompare("list",option+1) == 0) {
4643 /*
4644 FUTURE: This 'switch' should really be built into the MagickCore
4645 */
4646 ssize_t
4647 list;
4648
4649 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4650 if ( list < 0 ) {
4651 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4652 break;
4653 }
4654 switch (list)
4655 {
4656 case MagickCoderOptions:
4657 {
4658 (void) ListCoderInfo((FILE *) NULL,_exception);
4659 break;
4660 }
4661 case MagickColorOptions:
4662 {
4663 (void) ListColorInfo((FILE *) NULL,_exception);
4664 break;
4665 }
4666 case MagickConfigureOptions:
4667 {
4668 (void) ListConfigureInfo((FILE *) NULL,_exception);
4669 break;
4670 }
4671 case MagickDelegateOptions:
4672 {
4673 (void) ListDelegateInfo((FILE *) NULL,_exception);
4674 break;
4675 }
4676 case MagickFontOptions:
4677 {
4678 (void) ListTypeInfo((FILE *) NULL,_exception);
4679 break;
4680 }
4681 case MagickFormatOptions:
4682 (void) ListMagickInfo((FILE *) NULL,_exception);
4683 break;
4684 case MagickLocaleOptions:
4685 (void) ListLocaleInfo((FILE *) NULL,_exception);
4686 break;
4687 case MagickLogOptions:
4688 (void) ListLogInfo((FILE *) NULL,_exception);
4689 break;
4690 case MagickMagicOptions:
4691 (void) ListMagicInfo((FILE *) NULL,_exception);
4692 break;
4693 case MagickMimeOptions:
4694 (void) ListMimeInfo((FILE *) NULL,_exception);
4695 break;
4696 case MagickModuleOptions:
4697 (void) ListModuleInfo((FILE *) NULL,_exception);
4698 break;
4699 case MagickPolicyOptions:
4700 (void) ListPolicyInfo((FILE *) NULL,_exception);
4701 break;
4702 case MagickResourceOptions:
4703 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4704 break;
4705 case MagickThresholdOptions:
4706 (void) ListThresholdMaps((FILE *) NULL,_exception);
4707 break;
4708 default:
4709 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4710 _exception);
4711 break;
4712 }
4713 break;
anthony43f425d2012-02-26 12:58:58 +00004714 }
anthony8226e722012-04-05 14:25:46 +00004715
anthony4837ac22012-05-18 23:39:48 +00004716 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony8226e722012-04-05 14:25:46 +00004717
anthony4837ac22012-05-18 23:39:48 +00004718 } while (0); /* break to exit code. */
anthony43f425d2012-02-26 12:58:58 +00004719
4720#if 0
anthony4837ac22012-05-18 23:39:48 +00004721 /* clean up percent escape interpreted strings */
4722 if (arg1 != arg1n )
4723 arg1=DestroyString((char *)arg1);
4724 if (arg2 != arg2n )
4725 arg2=DestroyString((char *)arg2);
anthony43f425d2012-02-26 12:58:58 +00004726#endif
4727
anthony8226e722012-04-05 14:25:46 +00004728#undef _image_info
4729#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004730#undef _exception
anthony8226e722012-04-05 14:25:46 +00004731#undef IfNormalOp
4732#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004733}
anthony464f1c42012-04-22 08:51:01 +00004734
4735/*
4736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4737% %
4738% %
4739% %
anthony964d28e2012-05-17 23:39:46 +00004740+ C L I O p t i o n %
anthony464f1c42012-04-22 08:51:01 +00004741% %
4742% %
4743% %
4744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4745%
4746% CLIOption() Processes the given option using the given CLI Magick Wand.
anthony964d28e2012-05-17 23:39:46 +00004747% The option arguments can be variable in number, though at this time no more
4748% that two is actually used by any option (this may change). Excess options
4749% are simply ignored.
anthony464f1c42012-04-22 08:51:01 +00004750%
4751% If the cli_wand->command pointer is non-null, then it is assumed that the
4752% option has already been search for up from the CommandOptions[] table in
anthony964d28e2012-05-17 23:39:46 +00004753% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
4754% routine will do the lookup instead. The pointer is reset afterward.
4755%
4756% This action allows the caller to lookup and pre-handle any 'special'
4757% options, (such as implicit reads) before calling this general option
4758% handler to deal with 'standard' command line options.
anthony464f1c42012-04-22 08:51:01 +00004759%
4760% The format of the CLIOption method is:
4761%
4762% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
4763%
4764% A description of each parameter follows:
4765%
4766% o cli_wand: the main CLI Wand to use.
4767%
4768% o option: The special option (with any switch char) to process
4769%
anthony964d28e2012-05-17 23:39:46 +00004770% o args: any required arguments for an option (variable number)
anthony464f1c42012-04-22 08:51:01 +00004771%
4772% Example Usage...
4773%
4774% CLIoption(cli_wand,"-read","rose:");
4775% CLIoption(cli_wand,"-virtual-pixel","transparent");
4776% CLIoption(cli_wand,"-distort","SRT:","30");
4777% CLIoption(cli_wand,"-write","rotated_rose.png");
4778%
4779*/
4780WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
4781{
4782 const char
4783 *arg1,
4784 *arg2;
4785
4786 CommandOptionFlags
4787 option_type;
4788
4789 assert(cli_wand != (MagickCLI *) NULL);
4790 assert(cli_wand->signature == WandSignature);
4791 assert(cli_wand->wand.signature == WandSignature);
4792 if (IfMagickTrue(cli_wand->wand.debug))
4793 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4794
anthony964d28e2012-05-17 23:39:46 +00004795 do { /* Break Code Block for error handling */
4796
4797 /* get information about option */
4798 if ( cli_wand->command == (const OptionInfo *) NULL )
4799 cli_wand->command = GetCommandOptionInfo(option);
anthony464f1c42012-04-22 08:51:01 +00004800#if 0
anthony964d28e2012-05-17 23:39:46 +00004801 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
4802 option, cli_wand->command->mnemonic );
anthony464f1c42012-04-22 08:51:01 +00004803#endif
anthony964d28e2012-05-17 23:39:46 +00004804 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthony464f1c42012-04-22 08:51:01 +00004805
anthony964d28e2012-05-17 23:39:46 +00004806 if ( option_type == UndefinedOptionFlag )
4807 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
anthony464f1c42012-04-22 08:51:01 +00004808
anthony964d28e2012-05-17 23:39:46 +00004809 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
anthony464f1c42012-04-22 08:51:01 +00004810
anthony964d28e2012-05-17 23:39:46 +00004811 /* depreciated options */
4812 if ( (option_type & DeprecateOptionFlag) != 0 )
4813 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
anthony464f1c42012-04-22 08:51:01 +00004814
anthony964d28e2012-05-17 23:39:46 +00004815 /* options that this module does not handle */
4816 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
4817 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
anthony464f1c42012-04-22 08:51:01 +00004818
anthony964d28e2012-05-17 23:39:46 +00004819 /* Get argument strings from VarArgs
4820 How can you determine arguments is enough was supplied? */
4821 { size_t
4822 count = cli_wand->command->type;
anthony464f1c42012-04-22 08:51:01 +00004823
anthony964d28e2012-05-17 23:39:46 +00004824 va_list
4825 operands;
anthony464f1c42012-04-22 08:51:01 +00004826
anthony964d28e2012-05-17 23:39:46 +00004827 va_start(operands,option);
anthony464f1c42012-04-22 08:51:01 +00004828
anthony964d28e2012-05-17 23:39:46 +00004829 arg1=arg2=NULL;
4830 if ( count >= 1 )
4831 arg1=(const char *) va_arg(operands, const char *);
4832 if ( count >= 2 )
4833 arg2=(const char *) va_arg(operands, const char *);
anthony464f1c42012-04-22 08:51:01 +00004834
anthony964d28e2012-05-17 23:39:46 +00004835 va_end(operands);
anthony464f1c42012-04-22 08:51:01 +00004836
anthony52cb3df2012-04-24 03:29:32 +00004837#if 0
anthony964d28e2012-05-17 23:39:46 +00004838 (void) FormatLocaleFile(stderr,
4839 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
4840 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00004841#endif
anthony964d28e2012-05-17 23:39:46 +00004842 }
4843
4844 /*
4845 Call the appropriate option handler
4846 */
4847
4848 /* FUTURE: this is temporary - get 'settings' to handle distribution of
4849 settings to images attributes,proprieties,artifacts */
4850 if ( cli_wand->wand.images != (Image *)NULL )
4851 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4852 cli_wand->wand.exception);
4853
4854 if ( (option_type & SettingOptionFlags) != 0 ) {
4855 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
4856 // FUTURE: Sync Specific Settings into Image Properities (not global)
4857 }
4858
4859 /* Operators that do not need images - read, write, stack, clone */
4860 if ( (option_type & NoImageOperatorFlag) != 0)
4861 CLINoImageOperator(cli_wand, option, arg1, arg2);
4862
4863 /* FUTURE: The not a setting part below is a temporary hack due to
4864 * some options being both a Setting and a Simple operator.
4865 * Specifically -monitor, -depth, and -colorspace */
4866 if ( cli_wand->wand.images == (Image *)NULL )
4867 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
4868 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
4869 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
4870
4871 /* Operators work on single images, and needs a loop over the images */
4872 if ( (option_type & SimpleOperatorFlag) != 0)
4873 CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
4874
4875 /* Operators that work on the image list as a whole */
4876 if ( (option_type & ListOperatorFlag) != 0 )
4877 CLIListOperatorImages(cli_wand, option, arg1, arg2);
4878
4879 } while (0); /* end Break code block */
anthony464f1c42012-04-22 08:51:01 +00004880
4881 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
anthony464f1c42012-04-22 08:51:01 +00004882}