blob: 9999b951fdae10c823223520270507d77949823a [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"
anthony7a4d6102012-07-01 09:48:25 +000060#include "MagickCore/pixel-private.h"
anthony805a2d42011-09-25 08:25:12 +000061
62/*
63 Define declarations.
64*/
anthonyafa3dfc2012-03-03 11:31:30 +000065#define USE_WAND_METHODS 0
66#define MAX_STACK_DEPTH 32
67#define UNDEFINED_COMPRESSION_QUALITY 0UL
68
anthonyb1d483a2012-04-14 12:53:56 +000069/* FUTURE: why is this default so specific? */
70#define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
71
anthony805a2d42011-09-25 08:25:12 +000072/*
73 Constant declaration. (temporary exports)
74*/
75static const char
76 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000077 BorderColor[] = "#dfdfdf", /* sRGB gray */
78 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony22de2722012-04-19 14:43:00 +000079
80/* For Debugging Geometry Input */
81#define ReportGeometry(flags,info) \
82 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
83 flags, info.rho, info.sigma, info.xi, info.psi )
anthony805a2d42011-09-25 08:25:12 +000084
85/*
86** Function to report on the progress of image operations
87*/
88static MagickBooleanType MonitorProgress(const char *text,
89 const MagickOffsetType offset,const MagickSizeType extent,
anthony43f425d2012-02-26 12:58:58 +000090 void *wand_unused(cli_wandent_data))
anthony805a2d42011-09-25 08:25:12 +000091{
92 char
93 message[MaxTextExtent],
94 tag[MaxTextExtent];
95
96 const char
97 *locale_message;
98
99 register char
100 *p;
101
102 if (extent < 2)
103 return(MagickTrue);
104 (void) CopyMagickMemory(tag,text,MaxTextExtent);
105 p=strrchr(tag,'/');
106 if (p != (char *) NULL)
107 *p='\0';
108 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
109 locale_message=GetLocaleMessage(message);
110 if (locale_message == message)
111 locale_message=tag;
112 if (p == (char *) NULL)
113 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
114 locale_message,(long) offset,(unsigned long) extent,(long)
115 (100L*offset/(extent-1)));
116 else
117 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
118 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
119 (100L*offset/(extent-1)));
120 if (offset == (MagickOffsetType) (extent-1))
121 (void) FormatLocaleFile(stderr,"\n");
122 (void) fflush(stderr);
123 return(MagickTrue);
124}
125
126/*
127** GetImageCache() will read an image into a image cache if not already
128** present then return the image that is in the cache under that filename.
129*/
130static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
131 ExceptionInfo *exception)
132{
133 char
134 key[MaxTextExtent];
135
136 ExceptionInfo
137 *sans_exception;
138
139 Image
140 *image;
141
142 ImageInfo
143 *read_info;
144
145 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
146 sans_exception=AcquireExceptionInfo();
147 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
148 sans_exception=DestroyExceptionInfo(sans_exception);
149 if (image != (Image *) NULL)
150 return(image);
151 read_info=CloneImageInfo(image_info);
152 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
153 image=ReadImage(read_info,exception);
154 read_info=DestroyImageInfo(read_info);
155 if (image != (Image *) NULL)
156 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
157 return(image);
158}
159
anthony756cd0d2012-04-08 12:41:44 +0000160/*
anthonya89dd172011-10-04 13:29:35 +0000161 SparseColorOption() parse the complex -sparse-color argument into an
162 an array of floating point values than call SparseColorImage().
163 Argument is a complex mix of floating-point pixel coodinates, and color
164 specifications (or direct floating point numbers). The number of floats
165 needed to represent a color varies depending on teh current channel
166 setting.
anthony43f425d2012-02-26 12:58:58 +0000167
168 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000169*/
170static Image *SparseColorOption(const Image *image,
171 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000172 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000173{
174 char
175 token[MaxTextExtent];
176
177 const char
178 *p;
179
180 double
181 *sparse_arguments;
182
183 Image
184 *sparse_image;
185
186 PixelInfo
187 color;
188
189 MagickBooleanType
190 error;
191
192 register size_t
193 x;
194
195 size_t
196 number_arguments,
197 number_colors;
198
199 assert(image != (Image *) NULL);
200 assert(image->signature == MagickSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000201 if (IfMagickTrue(image->debug))
anthony805a2d42011-09-25 08:25:12 +0000202 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
203 assert(exception != (ExceptionInfo *) NULL);
204 assert(exception->signature == MagickSignature);
205 /*
anthonyb1d483a2012-04-14 12:53:56 +0000206 Limit channels according to image
207 add up number of values needed per color.
anthony805a2d42011-09-25 08:25:12 +0000208 */
209 number_colors=0;
210 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
211 number_colors++;
212 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
213 number_colors++;
214 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
215 number_colors++;
216 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
217 (image->colorspace == CMYKColorspace))
218 number_colors++;
219 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000220 IfMagickTrue(image->matte))
anthony805a2d42011-09-25 08:25:12 +0000221 number_colors++;
222
223 /*
224 Read string, to determine number of arguments needed,
225 */
226 p=arguments;
227 x=0;
228 while( *p != '\0' )
229 {
230 GetMagickToken(p,&p,token);
231 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000232 if ( isalpha((int) token[0]) || token[0] == '#' )
233 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000234 else
anthony805a2d42011-09-25 08:25:12 +0000235 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000236 }
anthony31f1bf72012-01-30 12:37:22 +0000237 /* control points and color values */
anthony7bcfe7f2012-03-30 14:01:22 +0000238 error = IsMagickTrue( x % (2+number_colors) );
anthony31f1bf72012-01-30 12:37:22 +0000239 number_arguments=x;
anthony7bcfe7f2012-03-30 14:01:22 +0000240 if ( IfMagickTrue(error) ) {
anthony805a2d42011-09-25 08:25:12 +0000241 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000242 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000243 "Invalid number of Arguments");
244 return( (Image *)NULL);
245 }
246
247 /* Allocate and fill in the floating point arguments */
248 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
249 sizeof(*sparse_arguments));
250 if (sparse_arguments == (double *) NULL) {
251 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
252 "MemoryAllocationFailed","%s","SparseColorOption");
253 return( (Image *)NULL);
254 }
255 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
256 sizeof(*sparse_arguments));
257 p=arguments;
258 x=0;
259 while( *p != '\0' && x < number_arguments ) {
260 /* X coordinate */
261 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
262 if ( token[0] == '\0' ) break;
263 if ( isalpha((int) token[0]) || token[0] == '#' ) {
264 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000265 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000266 "Color found, instead of X-coord");
267 error = MagickTrue;
268 break;
269 }
cristydbdd0e32011-11-04 23:29:40 +0000270 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000271 /* Y coordinate */
272 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
273 if ( token[0] == '\0' ) break;
274 if ( isalpha((int) token[0]) || token[0] == '#' ) {
275 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000276 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000277 "Color found, instead of Y-coord");
278 error = MagickTrue;
279 break;
280 }
cristydbdd0e32011-11-04 23:29:40 +0000281 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000282 /* color name or function given in string argument */
283 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
284 if ( token[0] == '\0' ) break;
285 if ( isalpha((int) token[0]) || token[0] == '#' ) {
286 /* Color string given */
287 (void) QueryColorCompliance(token,AllCompliance,&color,
288 exception);
289 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
290 sparse_arguments[x++] = QuantumScale*color.red;
291 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
292 sparse_arguments[x++] = QuantumScale*color.green;
293 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
294 sparse_arguments[x++] = QuantumScale*color.blue;
295 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
296 (image->colorspace == CMYKColorspace))
297 sparse_arguments[x++] = QuantumScale*color.black;
298 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000299 IfMagickTrue(image->matte))
anthony31f1bf72012-01-30 12:37:22 +0000300 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000301 }
anthony31f1bf72012-01-30 12:37:22 +0000302 else {
303 /* Colors given as a set of floating point values - experimental */
304 /* NB: token contains the first floating point value to use! */
305 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
306 {
307 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
308 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
309 break;
310 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
311 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000312 }
anthony31f1bf72012-01-30 12:37:22 +0000313 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
314 {
315 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
316 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
317 break;
318 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
319 token[0] = ','; /* used this token - get another */
320 }
321 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
322 {
323 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
324 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
325 break;
326 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
327 token[0] = ','; /* used this token - get another */
328 }
329 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
330 (image->colorspace == CMYKColorspace))
331 {
332 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
333 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
334 break;
335 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
336 token[0] = ','; /* used this token - get another */
337 }
338 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000339 IfMagickTrue(image->matte))
anthony31f1bf72012-01-30 12:37:22 +0000340 {
341 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
342 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
343 break;
344 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
345 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000346 }
347 }
348 }
349 if ( number_arguments != x && !error ) {
350 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000351 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000352 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
353 return( (Image *)NULL);
354 }
355 if ( error )
356 return( (Image *)NULL);
357
anthony31f1bf72012-01-30 12:37:22 +0000358 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000359 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
360 exception);
361 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
362 return( sparse_image );
363}
364
365/*
366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367% %
368% %
369% %
anthony464f1c42012-04-22 08:51:01 +0000370% C L I S e t t i n g O p t i o n I n f o %
anthony43f425d2012-02-26 12:58:58 +0000371% %
372% %
373% %
374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375%
376% CLISettingOptionInfo() applies a single settings option into a CLI wand
377% holding the image_info, draw_info, quantize_info structures that will be
378% used when processing the images.
379%
380% These options do no require images to be present in the CLI wand for them
381% to be able to be set, in which case they will generally be applied to image
382% that are read in later
anthony80c37752012-01-16 01:03:11 +0000383%
384% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000385% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000386%
anthony2052d272012-02-28 12:48:29 +0000387% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000388%
anthonyafa3dfc2012-03-03 11:31:30 +0000389% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000390% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000391%
392% A description of each parameter follows:
393%
anthony43f425d2012-02-26 12:58:58 +0000394% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000395%
anthonydcf510d2011-10-30 13:51:40 +0000396% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000397%
anthonye5fcd362012-04-09 04:02:09 +0000398% o arg1, arg2: optional argument strings to the operation
399% arg2 is currently only used by "-limit"
anthonydcf510d2011-10-30 13:51:40 +0000400%
anthony805a2d42011-09-25 08:25:12 +0000401*/
anthonyafa3dfc2012-03-03 11:31:30 +0000402WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
anthonye5fcd362012-04-09 04:02:09 +0000403 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +0000404{
anthony30b912a2012-03-22 01:20:28 +0000405 ssize_t
406 parse; /* option argument parsing (string to value table lookup) */
407
anthony43f425d2012-02-26 12:58:58 +0000408 assert(cli_wand != (MagickCLI *) NULL);
409 assert(cli_wand->signature == WandSignature);
410 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000411 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +0000412 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000413
anthony2e4501b2012-03-30 04:41:54 +0000414#define _image_info (cli_wand->wand.image_info)
415#define _exception (cli_wand->wand.exception)
416#define _draw_info (cli_wand->draw_info)
417#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000418#define IfSetOption (*option=='-')
anthony7bcfe7f2012-03-30 14:01:22 +0000419#define ArgBoolean IsMagickTrue(IfSetOption)
420#define ArgBooleanNot IsMagickFalse(IfSetOption)
anthony24aa8822012-03-11 00:56:06 +0000421#define ArgBooleanString (IfSetOption?"true":"false")
422#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000423
anthony4837ac22012-05-18 23:39:48 +0000424#if 0
425Setting are not directly involved with images, so can not
426interpret Percent Escapes in Arguments, At least not yet */
427
428#define _process_flags (cli_wand->process_flags)
429#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
430 /* Interpret Percent Escapes in Arguments - using first image */
431 arg1 = arg1n,
432 arg2 = arg2n;
433 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
434 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
435 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
436 /* Interpret Percent escapes in argument 1 */
437 if (arg1n != (char *) NULL) {
438 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
439 if (arg1 == (char *) NULL) {
440 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
441 arg1=arg1n; /* use the given argument as is */
442 }
443 }
444 if (arg2n != (char *) NULL) {
445 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
446 if (arg2 == (char *) NULL) {
447 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
448 arg2=arg2n; /* use the given argument as is */
449 }
450 }
451 }
452#undef _process_flags
453#undef _option_type
454#endif
455
anthonyafa3dfc2012-03-03 11:31:30 +0000456 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000457 {
458 case 'a':
459 {
anthonyafa3dfc2012-03-03 11:31:30 +0000460 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000461 {
anthony92c93bd2012-03-19 14:02:47 +0000462 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000463 break;
464 }
anthonyafa3dfc2012-03-03 11:31:30 +0000465 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000466 {
anthony464f1c42012-04-22 08:51:01 +0000467 CLIWandWarnReplaced("-draw 'affine ...'");
anthony74b1cfc2011-10-06 12:44:16 +0000468 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000469 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000470 else
anthony92c93bd2012-03-19 14:02:47 +0000471 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000472 break;
473 }
anthonyafa3dfc2012-03-03 11:31:30 +0000474 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000475 {
anthony92c93bd2012-03-19 14:02:47 +0000476 _image_info->antialias =
477 _draw_info->stroke_antialias =
478 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000479 break;
480 }
anthony31f1bf72012-01-30 12:37:22 +0000481 if (LocaleCompare("attenuate",option+1) == 0)
482 {
anthony7bcfe7f2012-03-30 14:01:22 +0000483 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +0000484 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
485 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000486 break;
487 }
anthonyafa3dfc2012-03-03 11:31:30 +0000488 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000489 {
anthony92c93bd2012-03-19 14:02:47 +0000490 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000491 break;
492 }
anthonyebb73a22012-03-22 14:25:52 +0000493 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000494 }
495 case 'b':
496 {
anthonyafa3dfc2012-03-03 11:31:30 +0000497 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000498 {
anthony92c93bd2012-03-19 14:02:47 +0000499 /* FUTURE: both _image_info attribute & ImageOption in use!
500 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000501 SyncImageSettings() used to set per-image attribute.
502
anthony92c93bd2012-03-19 14:02:47 +0000503 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000504 we should fall back to per-image background_color
505
506 At this time -background will 'wipe out' the per-image
507 background color!
508
509 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000510 */
anthony92c93bd2012-03-19 14:02:47 +0000511 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000512 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000513 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000514 break;
515 }
anthonyafa3dfc2012-03-03 11:31:30 +0000516 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000517 {
anthony52bef752012-03-27 13:54:47 +0000518 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000519 as it is actually rarely used except in direct convolve operations
520 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000521
522 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000523 */
anthony7bcfe7f2012-03-30 14:01:22 +0000524 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000525 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000526 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000527 break;
528 }
anthonyafa3dfc2012-03-03 11:31:30 +0000529 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000530 {
anthony72feaa62012-01-17 06:46:23 +0000531 /* Used as a image chromaticity setting
532 SyncImageSettings() used to set per-image attribute.
533 */
anthony92c93bd2012-03-19 14:02:47 +0000534 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000535 break;
536 }
anthonyafa3dfc2012-03-03 11:31:30 +0000537 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000538 {
anthonyafbaed72011-10-26 12:05:04 +0000539 /* Image chromaticity X,Y NB: Y=X if Y not defined
540 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000541 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000542 */
anthonyf42014d2012-03-25 09:53:06 +0000543 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000544 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000545 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000546 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000547 break;
548 }
anthonyafa3dfc2012-03-03 11:31:30 +0000549 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000550 {
anthony92c93bd2012-03-19 14:02:47 +0000551 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000552 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000553 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000554 */
anthony74b1cfc2011-10-06 12:44:16 +0000555 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000556 {
anthony92c93bd2012-03-19 14:02:47 +0000557 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000558 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000559 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000560 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000561 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000562 break;
563 }
anthony92c93bd2012-03-19 14:02:47 +0000564 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000565 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000566 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000567 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000568 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000569 break;
570 }
anthonyafa3dfc2012-03-03 11:31:30 +0000571 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000572 {
anthony464f1c42012-04-22 08:51:01 +0000573 CLIWandWarnReplaced("-undercolor");
anthony975a8d72012-04-12 13:54:36 +0000574 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
anthonyfd706f92012-01-19 04:22:02 +0000575 break;
anthony805a2d42011-09-25 08:25:12 +0000576 }
anthonyebb73a22012-03-22 14:25:52 +0000577 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000578 }
579 case 'c':
580 {
anthonyafa3dfc2012-03-03 11:31:30 +0000581 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000582 {
583 MagickSizeType
584 limit;
585
anthony7bcfe7f2012-03-30 14:01:22 +0000586 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000588 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000589 if (LocaleCompare("unlimited",arg1) != 0)
590 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000591 (void) SetMagickResourceLimit(MemoryResource,limit);
592 (void) SetMagickResourceLimit(MapResource,2*limit);
593 break;
594 }
anthonyafa3dfc2012-03-03 11:31:30 +0000595 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000596 {
anthony92c93bd2012-03-19 14:02:47 +0000597 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000598 break;
599 }
anthonyafa3dfc2012-03-03 11:31:30 +0000600 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000601 {
anthony30b912a2012-03-22 01:20:28 +0000602 arg1=ArgOption("default");
603 parse=ParseChannelOption(arg1);
604 if (parse < 0)
605 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
606 option,arg1);
607 _image_info->channel=(ChannelType) parse;
608 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000609 break;
610 }
anthonyafa3dfc2012-03-03 11:31:30 +0000611 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000612 {
anthonyafbaed72011-10-26 12:05:04 +0000613 /* Setting used for new images via AquireImage()
614 But also used as a SimpleImageOperator
615 Undefined colorspace means don't modify images on
616 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000617 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
618 ArgOption("undefined"));
619 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000620 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
621 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000622 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000623 break;
624 }
anthonyafa3dfc2012-03-03 11:31:30 +0000625 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000626 {
anthony92c93bd2012-03-19 14:02:47 +0000627 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000628 break;
629 }
anthonyafa3dfc2012-03-03 11:31:30 +0000630 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000631 {
anthony92c93bd2012-03-19 14:02:47 +0000632 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000633 SyncImageSettings() used to set per-image attribute. - REMOVE
634
anthonyafbaed72011-10-26 12:05:04 +0000635 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000636 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000637 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000638 */
anthonyebb73a22012-03-22 14:25:52 +0000639 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
640 ArgOption("undefined"));
641 if (parse < 0)
642 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
643 option,arg1);
644 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000645 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000646 break;
647 }
anthonyafa3dfc2012-03-03 11:31:30 +0000648 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000649 {
anthony92c93bd2012-03-19 14:02:47 +0000650 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000651 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000652 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000653
anthony92c93bd2012-03-19 14:02:47 +0000654 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000655 however the image attribute (for save) is set from the
656 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000657
658 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000659 */
anthonyebb73a22012-03-22 14:25:52 +0000660 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
661 ArgOption("undefined"));
662 if (parse < 0)
663 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
664 option,arg1);
665 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000666 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000667 break;
668 }
anthonyebb73a22012-03-22 14:25:52 +0000669 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000670 }
671 case 'd':
672 {
anthonyafa3dfc2012-03-03 11:31:30 +0000673 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000674 {
anthony72feaa62012-01-17 06:46:23 +0000675 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000676 arg1=ArgOption("none");
677 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
678 if (parse < 0)
679 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
680 option,arg1);
681 (void) SetLogEventMask(arg1);
682 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000683 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000684 break;
685 }
anthonyafa3dfc2012-03-03 11:31:30 +0000686 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000687 {
anthony24aa8822012-03-11 00:56:06 +0000688 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000689 {
anthony5f867ae2011-10-09 10:28:34 +0000690 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000691 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000692 else
anthony24aa8822012-03-11 00:56:06 +0000693 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000694 break;
695 }
anthony24aa8822012-03-11 00:56:06 +0000696 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000697 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000698 (void) DefineImageOption(_image_info,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +0000699 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000700 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000701 break;
702 }
anthonyafa3dfc2012-03-03 11:31:30 +0000703 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000704 {
anthonyafbaed72011-10-26 12:05:04 +0000705 /* Only used for new images via AcquireImage()
706 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000707 */
anthonyebb73a22012-03-22 14:25:52 +0000708 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000709 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000710 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
711 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000712 break;
713 }
anthonyafa3dfc2012-03-03 11:31:30 +0000714 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000715 {
anthony92c93bd2012-03-19 14:02:47 +0000716 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000717 Basically as density can be in a XxY form!
718
719 SyncImageSettings() used to set per-image attribute.
720 */
anthony7bcfe7f2012-03-30 14:01:22 +0000721 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000722 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000723 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
724 (void) CloneString(&_image_info->density,ArgOption(NULL));
725 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000726 break;
727 }
anthonyafa3dfc2012-03-03 11:31:30 +0000728 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000729 {
anthony72feaa62012-01-17 06:46:23 +0000730 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
731 SyncImageSettings() used to set per-image attribute.
732 */
anthony7bcfe7f2012-03-30 14:01:22 +0000733 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000734 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000735 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000736 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000737 break;
738 }
anthonyafa3dfc2012-03-03 11:31:30 +0000739 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000740 {
anthony92c93bd2012-03-19 14:02:47 +0000741 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000742 arg1=ArgOption("undefined");
743 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
744 if (parse < 0)
745 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
746 option,arg1);
747 _draw_info->direction=(DirectionType) parse;
748 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000749 break;
750 }
anthonyafa3dfc2012-03-03 11:31:30 +0000751 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000752 {
anthony92c93bd2012-03-19 14:02:47 +0000753 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
754 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000755 break;
756 }
anthonyafa3dfc2012-03-03 11:31:30 +0000757 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000758 {
anthony72feaa62012-01-17 06:46:23 +0000759 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000760 arg1=ArgOption("undefined");
761 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
762 if (parse < 0)
763 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
764 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000765 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000766 break;
767 }
anthonyb1d483a2012-04-14 12:53:56 +0000768 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
769 {
770 /* FUTURE: this is only used by CompareImages() which is used
771 only by the "compare" CLI program at this time. */
772 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
773 if (IfMagickFalse(IsGeometry(arg1)))
774 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
775 (void) SetImageOption(_image_info,option+1,arg1);
776 break;
777 }
anthonyafa3dfc2012-03-03 11:31:30 +0000778 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000779 {
anthony92c93bd2012-03-19 14:02:47 +0000780 /* _image_info attr (on/off), _quantize_info attr (on/off)
781 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000782 FUTURE: merge the duality of the dithering options
783 */
cristycbda6112012-05-27 20:57:16 +0000784 _image_info->dither = ArgBoolean;
anthony92c93bd2012-03-19 14:02:47 +0000785 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
786 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
cristycbda6112012-05-27 20:57:16 +0000787 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000788 if (_quantize_info->dither_method == NoDitherMethod)
cristycbda6112012-05-27 20:57:16 +0000789 _image_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000790 break;
791 }
anthonyebb73a22012-03-22 14:25:52 +0000792 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000793 }
794 case 'e':
795 {
anthonyafa3dfc2012-03-03 11:31:30 +0000796 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000797 {
anthony92c93bd2012-03-19 14:02:47 +0000798 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
799 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000800 break;
801 }
anthonyafa3dfc2012-03-03 11:31:30 +0000802 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000803 {
anthony92c93bd2012-03-19 14:02:47 +0000804 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000805 arg1 = ArgOption("undefined");
806 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
807 if (parse < 0)
808 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
809 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000810 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000811 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000812 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000813 break;
814 }
anthonyafa3dfc2012-03-03 11:31:30 +0000815 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000816 {
anthony92c93bd2012-03-19 14:02:47 +0000817 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000818 break;
819 }
anthonyebb73a22012-03-22 14:25:52 +0000820 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000821 }
822 case 'f':
823 {
anthonyafa3dfc2012-03-03 11:31:30 +0000824 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000825 {
anthony92c93bd2012-03-19 14:02:47 +0000826 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000827 break;
828 }
anthonyafa3dfc2012-03-03 11:31:30 +0000829 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000830 {
anthony92c93bd2012-03-19 14:02:47 +0000831 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000832 The original fill color is preserved if a fill-pattern is given.
833 That way it does not effect other operations that directly using
834 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000835 */
anthony72feaa62012-01-17 06:46:23 +0000836 MagickBooleanType
837 status;
anthony6dc09cd2011-10-12 08:56:49 +0000838
839 ExceptionInfo
840 *sans;
841
anthonyfd706f92012-01-19 04:22:02 +0000842 PixelInfo
843 color;
844
anthony2a0ec8c2012-03-24 04:35:56 +0000845 arg1 = ArgOption("none"); /* +fill turns it off! */
846 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000847 if (_draw_info->fill_pattern != (Image *) NULL)
848 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000849
850 /* is it a color or a image? -- ignore exceptions */
851 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +0000852 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000853 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000854
anthony7bcfe7f2012-03-30 14:01:22 +0000855 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +0000856 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000857 else
anthony92c93bd2012-03-19 14:02:47 +0000858 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000859 break;
860 }
anthonyafa3dfc2012-03-03 11:31:30 +0000861 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000862 {
anthony72feaa62012-01-17 06:46:23 +0000863 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +0000864 arg1 = ArgOption("undefined");
865 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
866 if (parse < 0)
867 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
868 option,arg1);
869 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000870 break;
871 }
anthonyafa3dfc2012-03-03 11:31:30 +0000872 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000873 {
anthony92c93bd2012-03-19 14:02:47 +0000874 (void) CloneString(&_draw_info->font,ArgOption(NULL));
875 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000876 break;
877 }
anthonyafa3dfc2012-03-03 11:31:30 +0000878 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000879 {
anthonydcf510d2011-10-30 13:51:40 +0000880 /* FUTURE: why the ping test, you could set ping after this! */
881 /*
anthony805a2d42011-09-25 08:25:12 +0000882 register const char
883 *q;
884
anthony24aa8822012-03-11 00:56:06 +0000885 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000886 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +0000887 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000888 */
anthony92c93bd2012-03-19 14:02:47 +0000889 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000890 break;
891 }
anthonyafa3dfc2012-03-03 11:31:30 +0000892 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000893 {
anthony72feaa62012-01-17 06:46:23 +0000894 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000895 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000896 SyncImageSettings() used to set per-image attribute.
897
anthony2a0ec8c2012-03-24 04:35:56 +0000898 FUTURE: Can't find anything else using _image_info->fuzz directly!
899 remove direct sttribute from image_info
anthony6613bf32011-10-15 07:24:44 +0000900 */
anthony2a0ec8c2012-03-24 04:35:56 +0000901 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000902 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +0000903 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
904 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +0000905 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +0000906 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000907 break;
908 }
anthonyebb73a22012-03-22 14:25:52 +0000909 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000910 }
911 case 'g':
912 {
anthonyafa3dfc2012-03-03 11:31:30 +0000913 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000914 {
anthony72feaa62012-01-17 06:46:23 +0000915 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000916 arg1 = ArgOption("none");
917 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
918 if (parse < 0)
919 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
920 option,arg1);
anthonyfe1aa782012-03-24 13:43:04 +0000921 _draw_info->gravity=(GravityType) parse;
anthonye8490972012-04-03 13:16:01 +0000922 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000923 break;
924 }
anthonyafa3dfc2012-03-03 11:31:30 +0000925 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000926 {
anthonydcf510d2011-10-30 13:51:40 +0000927 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000928 SyncImageSettings() used to set per-image attribute.
929 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000930 */
anthonyf42014d2012-03-25 09:53:06 +0000931 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000932 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000933 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000934 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000935 break;
936 }
anthonyebb73a22012-03-22 14:25:52 +0000937 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000938 }
anthonyb1d483a2012-04-14 12:53:56 +0000939 case 'h':
940 {
941 if (LocaleCompare("highlight-color",option+1) == 0)
942 {
943 /* FUTURE: this is only used by CompareImages() which is used
944 only by the "compare" CLI program at this time. */
945 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
946 break;
947 }
948 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
949 }
anthony805a2d42011-09-25 08:25:12 +0000950 case 'i':
951 {
anthonyafa3dfc2012-03-03 11:31:30 +0000952 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000953 {
anthony72feaa62012-01-17 06:46:23 +0000954 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000955 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000956 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000957 */
anthonyfe1aa782012-03-24 13:43:04 +0000958 arg1 = ArgOption("indefined");
959 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
960 if (parse < 0)
961 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
962 option,arg1);
963 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000964 break;
965 }
anthonyafa3dfc2012-03-03 11:31:30 +0000966 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000967 {
anthony92c93bd2012-03-19 14:02:47 +0000968 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +0000969 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000970 */
anthonyfe1aa782012-03-24 13:43:04 +0000971 arg1 = ArgOption("undefined");
972 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
973 if (parse < 0)
974 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
975 option,arg1);
976 _image_info->interlace=(InterlaceType) parse;
977 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000978 break;
979 }
anthonyafa3dfc2012-03-03 11:31:30 +0000980 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000981 {
anthony7bcfe7f2012-03-30 14:01:22 +0000982 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +0000983 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000984 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
985 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +0000986 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000987 break;
988 }
anthonyafa3dfc2012-03-03 11:31:30 +0000989 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000990 {
anthonyfd706f92012-01-19 04:22:02 +0000991 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +0000992 arg1 = ArgOption("undefined");
993 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
994 if (parse < 0)
995 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
996 option,arg1);
997 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000998 break;
999 }
anthonyafa3dfc2012-03-03 11:31:30 +00001000 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001001 {
anthony7bcfe7f2012-03-30 14:01:22 +00001002 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001003 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001004 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1005 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001006 break;
1007 }
anthonyebb73a22012-03-22 14:25:52 +00001008 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001009 }
1010 case 'k':
1011 {
anthonyafa3dfc2012-03-03 11:31:30 +00001012 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001013 {
anthony7bcfe7f2012-03-30 14:01:22 +00001014 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001015 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001016 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1017 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001018 break;
1019 }
anthonyebb73a22012-03-22 14:25:52 +00001020 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001021 }
1022 case 'l':
1023 {
anthonyafa3dfc2012-03-03 11:31:30 +00001024 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001025 {
anthony72feaa62012-01-17 06:46:23 +00001026 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001027 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001028 break;
1029 }
anthony756cd0d2012-04-08 12:41:44 +00001030 if (LocaleCompare("limit",option+1) == 0)
1031 {
1032 MagickSizeType
1033 limit;
1034
1035 limit=MagickResourceInfinity;
1036 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1037 if ( parse < 0 )
1038 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1039 option,arg1);
1040 if (LocaleCompare("unlimited",arg2) != 0)
1041 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1042 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1043 break;
1044 }
anthonyafa3dfc2012-03-03 11:31:30 +00001045 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001046 {
anthonyfe1aa782012-03-24 13:43:04 +00001047 if (IfSetOption) {
1048 if ((strchr(arg1,'%') == (char *) NULL))
1049 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001050 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001051 }
anthony805a2d42011-09-25 08:25:12 +00001052 break;
1053 }
anthony975a8d72012-04-12 13:54:36 +00001054 if (LocaleCompare("lowlight-color",option+1) == 0)
1055 {
anthonyb1d483a2012-04-14 12:53:56 +00001056 /* FUTURE: this is only used by CompareImages() which is used
1057 only by the "compare" CLI program at this time. */
anthony975a8d72012-04-12 13:54:36 +00001058 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1059 break;
1060 }
anthonyafa3dfc2012-03-03 11:31:30 +00001061 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001062 {
anthony72feaa62012-01-17 06:46:23 +00001063 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001064 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001065 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001066 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1067 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001068 break;
1069 }
anthonyebb73a22012-03-22 14:25:52 +00001070 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001071 }
1072 case 'm':
1073 {
anthonyafa3dfc2012-03-03 11:31:30 +00001074 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001075 {
anthony72feaa62012-01-17 06:46:23 +00001076 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001077 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001078 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001079 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001080 break;
anthonycd358fc2012-04-16 13:59:03 +00001081 }
anthonyb1d483a2012-04-14 12:53:56 +00001082 if (LocaleCompare("metric",option+1) == 0)
1083 {
1084 /* FUTURE: this is only used by CompareImages() which is used
1085 only by the "compare" CLI program at this time. */
1086 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1087 if ( parse < 0 )
1088 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1089 option,arg1);
1090 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthonycd358fc2012-04-16 13:59:03 +00001091 break;
anthony805a2d42011-09-25 08:25:12 +00001092 }
anthonyafa3dfc2012-03-03 11:31:30 +00001093 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001094 {
anthony92c93bd2012-03-19 14:02:47 +00001095 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001096 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001097 break;
1098 }
anthonyafa3dfc2012-03-03 11:31:30 +00001099 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001100 {
anthony24aa8822012-03-11 00:56:06 +00001101 /* Setting (used by some input coders!) -- why?
1102 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001103 */
anthony92c93bd2012-03-19 14:02:47 +00001104 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001105 break;
1106 }
anthonyebb73a22012-03-22 14:25:52 +00001107 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001108 }
1109 case 'o':
1110 {
anthonyafa3dfc2012-03-03 11:31:30 +00001111 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001112 {
anthony72feaa62012-01-17 06:46:23 +00001113 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001114 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001115 FUTURE: make set meta-data operator instead.
1116 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001117 */
anthony7bc87992012-03-25 02:32:51 +00001118 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1119 ArgOption("undefined"));
1120 if (parse < 0)
1121 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1122 option,arg1);
1123 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001124 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001125 break;
1126 }
anthonyebb73a22012-03-22 14:25:52 +00001127 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001128 }
1129 case 'p':
1130 {
anthonyafa3dfc2012-03-03 11:31:30 +00001131 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001132 {
anthony7bc87992012-03-25 02:32:51 +00001133 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001134 SyncImageSettings() used to set per-image attribute. ?????
1135 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001136 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001137 */
anthony805a2d42011-09-25 08:25:12 +00001138 char
1139 *canonical_page,
1140 page[MaxTextExtent];
1141
1142 const char
1143 *image_option;
1144
1145 MagickStatusType
1146 flags;
1147
1148 RectangleInfo
1149 geometry;
1150
anthonydcf510d2011-10-30 13:51:40 +00001151 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001152 {
anthony92c93bd2012-03-19 14:02:47 +00001153 (void) DeleteImageOption(_image_info,option+1);
1154 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001155 break;
1156 }
1157 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001158 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001159 if (image_option != (const char *) NULL)
1160 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001161 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001162 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1163 canonical_page=DestroyString(canonical_page);
1164 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1165 (unsigned long) geometry.width,(unsigned long) geometry.height);
1166 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1167 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1168 (unsigned long) geometry.width,(unsigned long) geometry.height,
1169 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001170 (void) SetImageOption(_image_info,option+1,page);
1171 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001172 break;
1173 }
anthonyafa3dfc2012-03-03 11:31:30 +00001174 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001175 {
anthony92c93bd2012-03-19 14:02:47 +00001176 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001177 break;
1178 }
anthonyafa3dfc2012-03-03 11:31:30 +00001179 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001180 {
anthonyf42014d2012-03-25 09:53:06 +00001181 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001182 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001183 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1184 _image_info->pointsize =
1185 _draw_info->pointsize =
1186 StringToDouble(arg1,(char **) NULL);
1187 }
1188 else {
1189 _image_info->pointsize=0.0; /* unset pointsize */
1190 _draw_info->pointsize=12.0;
1191 }
anthony805a2d42011-09-25 08:25:12 +00001192 break;
1193 }
anthonyafa3dfc2012-03-03 11:31:30 +00001194 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001195 {
anthonyf42014d2012-03-25 09:53:06 +00001196 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001197 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1199 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001200 break;
1201 }
anthonydcf510d2011-10-30 13:51:40 +00001202 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001203 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001204 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001205 {
anthony92c93bd2012-03-19 14:02:47 +00001206 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001207 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001208 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001209 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001210 break;
1211 }
anthonydcf510d2011-10-30 13:51:40 +00001212 */
anthonyebb73a22012-03-22 14:25:52 +00001213 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001214 }
1215 case 'q':
1216 {
anthonyafa3dfc2012-03-03 11:31:30 +00001217 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001218 {
anthony7bcfe7f2012-03-30 14:01:22 +00001219 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001220 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001221 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1222 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001223 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001224 break;
1225 }
anthonyafa3dfc2012-03-03 11:31:30 +00001226 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001227 {
anthony92c93bd2012-03-19 14:02:47 +00001228 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001229 arg1=ArgOption("undefined");
1230 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1231 if (parse < 0)
1232 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1233 option,arg1);
1234 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001235 break;
1236 }
anthonyafa3dfc2012-03-03 11:31:30 +00001237 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001238 {
anthonyf42014d2012-03-25 09:53:06 +00001239 /* FUTURE: if two -quiet is performed you can not do +quiet!
1240 This needs to be checked over thoughly.
1241 */
anthony805a2d42011-09-25 08:25:12 +00001242 static WarningHandler
1243 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001244
anthonyafbaed72011-10-26 12:05:04 +00001245 WarningHandler
1246 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001247
anthonyafbaed72011-10-26 12:05:04 +00001248 if ( tmp != (WarningHandler) NULL)
1249 warning_handler = tmp; /* remember the old handler */
1250 if (!IfSetOption) /* set the old handler */
1251 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001252 break;
1253 }
anthonyebb73a22012-03-22 14:25:52 +00001254 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001255 }
1256 case 'r':
1257 {
anthonyafa3dfc2012-03-03 11:31:30 +00001258 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001259 {
anthonydcf510d2011-10-30 13:51:40 +00001260 /* Image chromaticity X,Y NB: Y=X if Y not defined
1261 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001262 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001263 */
anthonyf42014d2012-03-25 09:53:06 +00001264 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001265 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001266 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001267 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001268 break;
1269 }
cristyb0f7a182012-04-06 23:33:11 +00001270 if (LocaleCompare("regard-warnings",option+1) == 0)
anthonye5fcd362012-04-09 04:02:09 +00001271 /* FUTURE: to be replaced by a 'fatal-level' type setting */
cristyb0f7a182012-04-06 23:33:11 +00001272 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001273 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001274 {
anthony92c93bd2012-03-19 14:02:47 +00001275 /* _draw_info only setting */
1276 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001277 break;
1278 }
anthony756cd0d2012-04-08 12:41:44 +00001279 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1280 {
1281 /* link image and setting stacks - option is itself saved on stack! */
1282 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1283 break;
1284 }
anthonyebb73a22012-03-22 14:25:52 +00001285 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001286 }
1287 case 's':
1288 {
anthonyafa3dfc2012-03-03 11:31:30 +00001289 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001290 {
anthonyafbaed72011-10-26 12:05:04 +00001291 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001292 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001293 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001294 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001295 break;
1296 }
anthonyafa3dfc2012-03-03 11:31:30 +00001297 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001298 {
anthonyf42014d2012-03-25 09:53:06 +00001299 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001300 What ??? Why ????
1301 */
anthony7bcfe7f2012-03-30 14:01:22 +00001302 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001303 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001304 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1305 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001306 break;
1307 }
anthonyafa3dfc2012-03-03 11:31:30 +00001308 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001309 {
anthony7bcfe7f2012-03-30 14:01:22 +00001310 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001311 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyd7761bb2012-04-14 01:42:05 +00001312 SetRandomSecretKey(
anthony24aa8822012-03-11 00:56:06 +00001313 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001314 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001315 break;
1316 }
anthonyafa3dfc2012-03-03 11:31:30 +00001317 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001318 {
anthony92c93bd2012-03-19 14:02:47 +00001319 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001320 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001321 */
anthony92c93bd2012-03-19 14:02:47 +00001322 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001323 break;
1324 }
anthonyafa3dfc2012-03-03 11:31:30 +00001325 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001326 {
anthonyf42014d2012-03-25 09:53:06 +00001327 arg1=ArgOption("undefined");
1328 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1329 if (parse < 0)
1330 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1331 option,arg1);
1332 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001333 break;
1334 }
anthonyafa3dfc2012-03-03 11:31:30 +00001335 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001336 {
anthonyafbaed72011-10-26 12:05:04 +00001337 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001338 UPDATE: ensure stroke color is not destroyed is a pattern
1339 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001340 */
anthony72feaa62012-01-17 06:46:23 +00001341 MagickBooleanType
1342 status;
anthonyafbaed72011-10-26 12:05:04 +00001343
1344 ExceptionInfo
1345 *sans;
1346
anthonyfd706f92012-01-19 04:22:02 +00001347 PixelInfo
1348 color;
1349
anthony2a0ec8c2012-03-24 04:35:56 +00001350 arg1 = ArgOption("none"); /* +fill turns it off! */
1351 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001352 if (_draw_info->stroke_pattern != (Image *) NULL)
1353 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001354
1355 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001356 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001357 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001358 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001359
anthony7bcfe7f2012-03-30 14:01:22 +00001360 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001361 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001362 else
anthony92c93bd2012-03-19 14:02:47 +00001363 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001364 break;
1365 }
anthonyafa3dfc2012-03-03 11:31:30 +00001366 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001367 {
anthony7bcfe7f2012-03-30 14:01:22 +00001368 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001369 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001370 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1371 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001372 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001373 break;
1374 }
anthonyafa3dfc2012-03-03 11:31:30 +00001375 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001376 {
anthonyf42014d2012-03-25 09:53:06 +00001377 arg1=ArgOption("undefined");
1378 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1379 if (parse < 0)
1380 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1381 option,arg1);
1382 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001383 break;
1384 }
anthonycd358fc2012-04-16 13:59:03 +00001385#if 0
anthonyb1d483a2012-04-14 12:53:56 +00001386 if (LocaleCompare("subimage-search",option+1) == 0)
1387 {
1388 /* FUTURE: this is only used by CompareImages() which is used
1389 only by the "compare" CLI program at this time. */
1390 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1391 break;
1392 }
anthonycd358fc2012-04-16 13:59:03 +00001393#endif
anthonyafa3dfc2012-03-03 11:31:30 +00001394 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001395 {
anthonyf42014d2012-03-25 09:53:06 +00001396 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001397 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001398 break;
1399 }
anthonyebb73a22012-03-22 14:25:52 +00001400 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001401 }
1402 case 't':
1403 {
anthonyafa3dfc2012-03-03 11:31:30 +00001404 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001405 {
anthony72feaa62012-01-17 06:46:23 +00001406 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001407 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001408 break;
1409 }
anthonyafa3dfc2012-03-03 11:31:30 +00001410 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001411 {
anthony4837ac22012-05-18 23:39:48 +00001412 /* Note: arguments do not have percent escapes expanded */
anthony52bef752012-03-27 13:54:47 +00001413 /* FUTURE: move _image_info string to option splay-tree
1414 Other than "montage" what uses "texture" ????
1415 */
anthony92c93bd2012-03-19 14:02:47 +00001416 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001417 break;
1418 }
anthonyafa3dfc2012-03-03 11:31:30 +00001419 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001420 {
anthony4837ac22012-05-18 23:39:48 +00001421 /* Note: arguments do not have percent escapes expanded */
anthony92c93bd2012-03-19 14:02:47 +00001422 _draw_info->fill_pattern=IfSetOption
1423 ?GetImageCache(_image_info,arg1,_exception)
1424 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001425 break;
1426 }
anthonyafa3dfc2012-03-03 11:31:30 +00001427 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001428 {
anthony72feaa62012-01-17 06:46:23 +00001429 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001430 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001431 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001432 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1433 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001434 break;
1435 }
anthonyafa3dfc2012-03-03 11:31:30 +00001436 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001437 {
anthony92c93bd2012-03-19 14:02:47 +00001438 /* FUTURE: both _image_info attribute & ImageOption in use!
1439 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001440 SyncImageSettings() used to set per-image attribute.
1441
anthonyafbaed72011-10-26 12:05:04 +00001442 Note that +transparent-color, means fall-back to image
1443 attribute so ImageOption is deleted, not set to a default.
1444 */
anthony7bcfe7f2012-03-30 14:01:22 +00001445 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001446 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001447 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001448 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001449 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001450 break;
1451 }
anthonyafa3dfc2012-03-03 11:31:30 +00001452 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001453 {
anthony92c93bd2012-03-19 14:02:47 +00001454 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1455 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001456 break;
1457 }
anthonyafa3dfc2012-03-03 11:31:30 +00001458 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001459 {
anthony72feaa62012-01-17 06:46:23 +00001460 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001461 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1462 ArgOption("undefined"));
1463 if (parse < 0)
1464 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1465 option,arg1);
1466 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001467 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001468 break;
1469 }
anthonyebb73a22012-03-22 14:25:52 +00001470 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001471 }
1472 case 'u':
1473 {
anthonyafa3dfc2012-03-03 11:31:30 +00001474 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001475 {
anthony92c93bd2012-03-19 14:02:47 +00001476 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001477 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001478 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001479 break;
1480 }
anthonyafa3dfc2012-03-03 11:31:30 +00001481 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001482 {
anthony72feaa62012-01-17 06:46:23 +00001483 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001484 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001485 FUTURE: this probably should be part of the density setting
1486 */
anthony52bef752012-03-27 13:54:47 +00001487 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1488 ArgOption("undefined"));
1489 if (parse < 0)
1490 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1491 option,arg1);
1492 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001493 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001494 break;
1495 }
anthonyebb73a22012-03-22 14:25:52 +00001496 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001497 }
1498 case 'v':
1499 {
anthonyafa3dfc2012-03-03 11:31:30 +00001500 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001501 {
anthony24aa8822012-03-11 00:56:06 +00001502 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001503 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001504 */
anthony92c93bd2012-03-19 14:02:47 +00001505 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1506 _image_info->verbose= ArgBoolean;
1507 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001508 break;
1509 }
anthonyafa3dfc2012-03-03 11:31:30 +00001510 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001511 {
anthony92c93bd2012-03-19 14:02:47 +00001512 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001513 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001514 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001515 */
anthony92c93bd2012-03-19 14:02:47 +00001516 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001517 break;
1518 }
anthonyafa3dfc2012-03-03 11:31:30 +00001519 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001520 {
anthonyfd706f92012-01-19 04:22:02 +00001521 /* SyncImageSettings() used to set per-image attribute.
1522 This is VERY deep in the image caching structure.
1523 */
anthony52bef752012-03-27 13:54:47 +00001524 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1525 ArgOption("undefined"));
1526 if (parse < 0)
1527 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1528 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001529 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001530 break;
1531 }
anthonyebb73a22012-03-22 14:25:52 +00001532 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001533 }
1534 case 'w':
1535 {
anthonyafa3dfc2012-03-03 11:31:30 +00001536 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001537 {
anthony72feaa62012-01-17 06:46:23 +00001538 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001539 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001540 */
anthony52bef752012-03-27 13:54:47 +00001541 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001542 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001543 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001544 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001545 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001546 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001547 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001548 if (_draw_info->weight <= 800)
1549 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001550 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001551 if (_draw_info->weight >= 100)
1552 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001553 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001554 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001555 break;
1556 }
anthonyafa3dfc2012-03-03 11:31:30 +00001557 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001558 {
anthony72feaa62012-01-17 06:46:23 +00001559 /* Used as a image chromaticity setting
1560 SyncImageSettings() used to set per-image attribute.
1561 */
anthony52bef752012-03-27 13:54:47 +00001562 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001563 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001564 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1565 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001566 break;
1567 }
anthonyebb73a22012-03-22 14:25:52 +00001568 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001569 }
1570 default:
anthonyebb73a22012-03-22 14:25:52 +00001571 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001572 }
anthony24aa8822012-03-11 00:56:06 +00001573
anthony4837ac22012-05-18 23:39:48 +00001574#if 0
1575 /* clean up percent escape interpreted strings */
1576 if (arg1 != arg1n )
1577 arg1=DestroyString((char *)arg1);
1578 if (arg2 != arg2n )
1579 arg2=DestroyString((char *)arg2);
1580#endif
1581
anthony92c93bd2012-03-19 14:02:47 +00001582#undef _image_info
1583#undef _exception
1584#undef _draw_info
1585#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001586#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001587#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001588#undef ArgBooleanNot
1589#undef ArgBooleanString
1590#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001591
anthony31f1bf72012-01-30 12:37:22 +00001592 return;
anthony805a2d42011-09-25 08:25:12 +00001593}
1594
1595/*
1596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597% %
1598% %
1599% %
anthony43f425d2012-02-26 12:58:58 +00001600+ C L I S i m p l e O p e r a t o r I m a g e s %
anthony805a2d42011-09-25 08:25:12 +00001601% %
1602% %
1603% %
1604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605%
anthony7a4d6102012-07-01 09:48:25 +00001606% WandSimpleOperatorImages() andSimpleOperatorImagespplys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001607% the images in the CLI wand, with the settings that was previously saved in
1608% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001609%
1610% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001611% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001612%
anthony7a4d6102012-07-01 09:48:25 +00001613% The format of the WandSimpleOperatorImages method is:
anthony805a2d42011-09-25 08:25:12 +00001614%
anthony43f425d2012-02-26 12:58:58 +00001615% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001616% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001617%
1618% A description of each parameter follows:
1619%
anthony43f425d2012-02-26 12:58:58 +00001620% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001621%
anthonyfd706f92012-01-19 04:22:02 +00001622% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001623%
anthonyfd706f92012-01-19 04:22:02 +00001624% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001625%
anthony805a2d42011-09-25 08:25:12 +00001626*/
anthony31f1bf72012-01-30 12:37:22 +00001627
1628/*
1629 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001630 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001631
1632 The image in the list may be modified in three different ways...
1633 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1634 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1635 * one image replace by a list of images (-separate and -crop only!)
1636
anthonyafa3dfc2012-03-03 11:31:30 +00001637 In each case the result replaces the single original image in the list, as
1638 well as the pointer to the modified image (last image added if replaced by a
1639 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001640
1641 As the image pointed to may be replaced, the first image in the list may
1642 also change. GetFirstImageInList() should be used by caller if they wish
1643 return the Image pointer to the first image in list.
1644*/
anthony43f425d2012-02-26 12:58:58 +00001645static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthony964d28e2012-05-17 23:39:46 +00001646 const char *option, const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00001647{
1648 Image *
1649 new_image;
1650
anthony805a2d42011-09-25 08:25:12 +00001651 GeometryInfo
1652 geometry_info;
1653
1654 RectangleInfo
1655 geometry;
1656
1657 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001658 flags;
1659
anthony92c93bd2012-03-19 14:02:47 +00001660 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001661 parse;
anthony92c93bd2012-03-19 14:02:47 +00001662
anthony964d28e2012-05-17 23:39:46 +00001663 const char /* For percent escape interpretImageProperties() */
1664 *arg1,
1665 *arg2;
1666
anthony2e4501b2012-03-30 04:41:54 +00001667#define _image_info (cli_wand->wand.image_info)
1668#define _image (cli_wand->wand.images)
1669#define _exception (cli_wand->wand.exception)
1670#define _draw_info (cli_wand->draw_info)
1671#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00001672#define _process_flags (cli_wand->process_flags)
1673#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00001674#define IfNormalOp (*option=='-')
1675#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00001676#define normal_op IsMagickTrue(IfNormalOp)
1677#define plus_alt_op IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001678
anthony43f425d2012-02-26 12:58:58 +00001679 assert(cli_wand != (MagickCLI *) NULL);
1680 assert(cli_wand->signature == WandSignature);
1681 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001682 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001683 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001684 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001685
anthony964d28e2012-05-17 23:39:46 +00001686 /* Interpret Percent Escapes in Arguments - using first image */
1687 arg1 = arg1n,
1688 arg2 = arg2n;
1689 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1690 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1691 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1692 /* Interpret Percent escapes in argument 1 */
1693 if (arg1n != (char *) NULL) {
1694 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1695 if (arg1 == (char *) NULL) {
1696 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1697 arg1=arg1n; /* use the given argument as is */
1698 }
1699 }
1700 if (arg2n != (char *) NULL) {
1701 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1702 if (arg2 == (char *) NULL) {
1703 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1704 arg2=arg2n; /* use the given argument as is */
1705 }
1706 }
1707 }
anthony4837ac22012-05-18 23:39:48 +00001708#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00001709#undef _option_type
1710
1711#if 0
1712 (void) FormatLocaleFile(stderr,
1713 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1714#endif
anthony805a2d42011-09-25 08:25:12 +00001715
anthony5330ae02012-03-20 14:17:01 +00001716 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony964d28e2012-05-17 23:39:46 +00001717 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001718
anthonyafa3dfc2012-03-03 11:31:30 +00001719 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001720 {
1721 case 'a':
1722 {
anthonyafa3dfc2012-03-03 11:31:30 +00001723 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001724 {
anthonyfd706f92012-01-19 04:22:02 +00001725 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001726 if ((flags & (RhoValue|SigmaValue)) == 0)
1727 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001728 if ((flags & SigmaValue) == 0)
1729 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001730 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001731 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001732 break;
1733 }
anthonyafa3dfc2012-03-03 11:31:30 +00001734 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001735 {
anthonyfe1aa782012-03-24 13:43:04 +00001736 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001737 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001738 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1739 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1740 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001741 _exception);
anthony805a2d42011-09-25 08:25:12 +00001742 break;
1743 }
anthonyafa3dfc2012-03-03 11:31:30 +00001744 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001745 {
anthonyfd706f92012-01-19 04:22:02 +00001746 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001747 if ((flags & (RhoValue|SigmaValue)) == 0)
1748 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001749 if ((flags & SigmaValue) == 0)
1750 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001751 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001752 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001753 break;
1754 }
anthonyafa3dfc2012-03-03 11:31:30 +00001755 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001756 {
anthony2a0ec8c2012-03-24 04:35:56 +00001757 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1758 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001759 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1760 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001761 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1762 _exception);
anthony805a2d42011-09-25 08:25:12 +00001763 break;
1764 }
anthonyafa3dfc2012-03-03 11:31:30 +00001765 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001766 {
1767 char
anthony805a2d42011-09-25 08:25:12 +00001768 geometry[MaxTextExtent];
1769
anthony805a2d42011-09-25 08:25:12 +00001770 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001771 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001772 if ((flags & RhoValue) == 0)
1773 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001774 if ((flags & SigmaValue) == 0)
1775 geometry_info.sigma=geometry_info.rho;
anthony964d28e2012-05-17 23:39:46 +00001776 (void) CloneString(&_draw_info->text,arg2);
anthony805a2d42011-09-25 08:25:12 +00001777 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1778 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001779 (void) CloneString(&_draw_info->geometry,geometry);
1780 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001781 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001782 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001783 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001784 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001785 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001786 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001787 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001788 (void) AnnotateImage(_image,_draw_info,_exception);
1789 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001790 break;
1791 }
anthonyafa3dfc2012-03-03 11:31:30 +00001792 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001793 {
anthony92c93bd2012-03-19 14:02:47 +00001794 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001795 break;
1796 }
anthonyafa3dfc2012-03-03 11:31:30 +00001797 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001798 {
anthony92c93bd2012-03-19 14:02:47 +00001799 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001800 break;
1801 }
anthonyafa3dfc2012-03-03 11:31:30 +00001802 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001803 {
anthony5330ae02012-03-20 14:17:01 +00001804 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001805 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001806 {
1807 case TopRightOrientation:
1808 {
anthony92c93bd2012-03-19 14:02:47 +00001809 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001810 break;
1811 }
1812 case BottomRightOrientation:
1813 {
anthony92c93bd2012-03-19 14:02:47 +00001814 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001815 break;
1816 }
1817 case BottomLeftOrientation:
1818 {
anthony92c93bd2012-03-19 14:02:47 +00001819 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001820 break;
1821 }
1822 case LeftTopOrientation:
1823 {
anthony92c93bd2012-03-19 14:02:47 +00001824 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001825 break;
1826 }
1827 case RightTopOrientation:
1828 {
anthony92c93bd2012-03-19 14:02:47 +00001829 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001830 break;
1831 }
1832 case RightBottomOrientation:
1833 {
anthony92c93bd2012-03-19 14:02:47 +00001834 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001835 break;
1836 }
1837 case LeftBottomOrientation:
1838 {
anthony92c93bd2012-03-19 14:02:47 +00001839 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001840 break;
1841 }
1842 default:
1843 break;
1844 }
1845 if (new_image != (Image *) NULL)
1846 new_image->orientation=TopLeftOrientation;
1847 break;
1848 }
anthonyebb73a22012-03-22 14:25:52 +00001849 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001850 }
1851 case 'b':
1852 {
anthonyafa3dfc2012-03-03 11:31:30 +00001853 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001854 {
anthony7bcfe7f2012-03-30 14:01:22 +00001855 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001856 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001857 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001858 break;
1859 }
anthonyafa3dfc2012-03-03 11:31:30 +00001860 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001861 {
anthony805a2d42011-09-25 08:25:12 +00001862 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001863 if (IfNormalOp) {
anthonyfd706f92012-01-19 04:22:02 +00001864 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001865 if ((flags & RhoValue) == 0)
1866 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony5330ae02012-03-20 14:17:01 +00001867 }
anthony92c93bd2012-03-19 14:02:47 +00001868 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001869 break;
1870 }
anthonyafa3dfc2012-03-03 11:31:30 +00001871 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001872 {
anthonyfd706f92012-01-19 04:22:02 +00001873 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001874 if ((flags & (RhoValue|SigmaValue)) == 0)
1875 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001876 if ((flags & SigmaValue) == 0)
1877 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001878 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1879 _exception);
anthony805a2d42011-09-25 08:25:12 +00001880 break;
1881 }
anthonyafa3dfc2012-03-03 11:31:30 +00001882 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001883 {
anthony31f1bf72012-01-30 12:37:22 +00001884 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001885 compose;
1886
1887 const char*
anthony5f867ae2011-10-09 10:28:34 +00001888 value;
1889
anthony22de2722012-04-19 14:43:00 +00001890 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
1891 if ((flags & RhoValue) == 0)
anthony5330ae02012-03-20 14:17:01 +00001892 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony22de2722012-04-19 14:43:00 +00001893 if ((flags & SigmaValue) == 0)
1894 geometry.height=geometry.width;
anthony5330ae02012-03-20 14:17:01 +00001895
anthony92c93bd2012-03-19 14:02:47 +00001896 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001897 if (value != (const char *) NULL)
1898 compose=(CompositeOperator) ParseCommandOption(
1899 MagickComposeOptions,MagickFalse,value);
1900 else
anthony92c93bd2012-03-19 14:02:47 +00001901 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001902
anthony92c93bd2012-03-19 14:02:47 +00001903 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001904 break;
1905 }
anthonyafa3dfc2012-03-03 11:31:30 +00001906 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001907 {
1908 double
1909 brightness,
1910 contrast;
1911
1912 GeometryInfo
1913 geometry_info;
1914
1915 MagickStatusType
1916 flags;
1917
anthonyfd706f92012-01-19 04:22:02 +00001918 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001919 if ((flags & RhoValue) == 0)
1920 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001921 brightness=geometry_info.rho;
1922 contrast=0.0;
1923 if ((flags & SigmaValue) != 0)
1924 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001925 (void) BrightnessContrastImage(_image,brightness,contrast,
1926 _exception);
anthony805a2d42011-09-25 08:25:12 +00001927 break;
1928 }
anthonyebb73a22012-03-22 14:25:52 +00001929 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001930 }
1931 case 'c':
1932 {
anthonyafa3dfc2012-03-03 11:31:30 +00001933 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001934 {
anthony4837ac22012-05-18 23:39:48 +00001935 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001936 char
1937 *color_correction_collection;
1938
1939 /*
1940 Color correct with a color decision list.
1941 */
anthony92c93bd2012-03-19 14:02:47 +00001942 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001943 if (color_correction_collection == (char *) NULL)
1944 break;
anthony92c93bd2012-03-19 14:02:47 +00001945 (void) ColorDecisionListImage(_image,color_correction_collection,
1946 _exception);
anthony805a2d42011-09-25 08:25:12 +00001947 break;
1948 }
anthonyafa3dfc2012-03-03 11:31:30 +00001949 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001950 {
anthonyfd706f92012-01-19 04:22:02 +00001951 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00001952 if ((flags & (RhoValue|SigmaValue)) == 0)
1953 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001954 if ((flags & SigmaValue) == 0)
1955 geometry_info.sigma=1.0;
1956 if ((flags & XiValue) == 0)
1957 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001958 new_image=CharcoalImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001959 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001960 break;
1961 }
anthonyafa3dfc2012-03-03 11:31:30 +00001962 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001963 {
anthony7bcfe7f2012-03-30 14:01:22 +00001964 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001965 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001966 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1967 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001968 break;
1969 }
anthonyafa3dfc2012-03-03 11:31:30 +00001970 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001971 {
anthony92c93bd2012-03-19 14:02:47 +00001972 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001973 break;
1974 }
anthonyafa3dfc2012-03-03 11:31:30 +00001975 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001976 {
anthonyafa3dfc2012-03-03 11:31:30 +00001977 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001978 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001979 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001980 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001981 break;
1982 }
anthonyafa3dfc2012-03-03 11:31:30 +00001983 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001984 {
anthony4837ac22012-05-18 23:39:48 +00001985 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00001986 CacheView
1987 *mask_view;
1988
1989 Image
1990 *mask_image;
1991
1992 register Quantum
1993 *restrict q;
1994
1995 register ssize_t
1996 x;
1997
1998 ssize_t
1999 y;
2000
anthonyafa3dfc2012-03-03 11:31:30 +00002001 if (IfPlusOp) {
anthony4837ac22012-05-18 23:39:48 +00002002 /* use "+clip-mask" Remove the write mask for -clip-path */
anthony92c93bd2012-03-19 14:02:47 +00002003 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002004 break;
2005 }
anthony92c93bd2012-03-19 14:02:47 +00002006 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002007 if (mask_image == (Image *) NULL)
2008 break;
anthony7bcfe7f2012-03-30 14:01:22 +00002009 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00002010 break;
anthony5330ae02012-03-20 14:17:01 +00002011 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002012 /* FUTURE: use Alpha operations instead and create a Grey Image */
cristydb070952012-04-20 14:33:00 +00002013 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002014 for (y=0; y < (ssize_t) mask_image->rows; y++)
2015 {
2016 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002017 _exception);
anthony805a2d42011-09-25 08:25:12 +00002018 if (q == (Quantum *) NULL)
2019 break;
2020 for (x=0; x < (ssize_t) mask_image->columns; x++)
2021 {
anthony7bcfe7f2012-03-30 14:01:22 +00002022 if (IfMagickFalse(mask_image->matte))
anthony805a2d42011-09-25 08:25:12 +00002023 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2024 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2025 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2026 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2027 q+=GetPixelChannels(mask_image);
2028 }
anthony7bcfe7f2012-03-30 14:01:22 +00002029 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00002030 break;
2031 }
anthonyfd706f92012-01-19 04:22:02 +00002032 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002033 mask_view=DestroyCacheView(mask_view);
2034 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002035 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002036 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002037 break;
2038 }
anthonyafa3dfc2012-03-03 11:31:30 +00002039 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002040 {
anthony92c93bd2012-03-19 14:02:47 +00002041 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony4837ac22012-05-18 23:39:48 +00002042 /* Note: Use "+clip-mask" remove the write mask added */
anthony805a2d42011-09-25 08:25:12 +00002043 break;
2044 }
anthonyafa3dfc2012-03-03 11:31:30 +00002045 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002046 {
anthony7bcfe7f2012-03-30 14:01:22 +00002047 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002048 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002049 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002050 break;
2051 }
anthonyafa3dfc2012-03-03 11:31:30 +00002052 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002053 {
2054 KernelInfo
2055 *kernel;
2056
anthonyfd706f92012-01-19 04:22:02 +00002057 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002058 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002059 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002060 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002061 kernel=DestroyKernelInfo(kernel);
2062 break;
2063 }
anthonyafa3dfc2012-03-03 11:31:30 +00002064 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002065 {
anthony5330ae02012-03-20 14:17:01 +00002066 /* Reduce the number of colors in the image.
2067 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002068 */
anthony92c93bd2012-03-19 14:02:47 +00002069 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2070 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002071 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002072 if ((_image->storage_class == DirectClass) ||
2073 _image->colors > _quantize_info->number_colors)
2074 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002075 else
anthony92c93bd2012-03-19 14:02:47 +00002076 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002077 break;
2078 }
anthonyafa3dfc2012-03-03 11:31:30 +00002079 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002080 {
anthony5330ae02012-03-20 14:17:01 +00002081 /* WARNING: this is both a image_info setting (already done)
2082 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002083
2084 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002085 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002086
anthonyd2cdc862011-10-07 14:07:17 +00002087 Note that +colorspace sets "undefined" or no effect on
2088 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002089 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002090 */
anthony92c93bd2012-03-19 14:02:47 +00002091 (void) TransformImageColorspace(_image,
2092 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2093 _exception);
anthony805a2d42011-09-25 08:25:12 +00002094 break;
2095 }
anthonyafa3dfc2012-03-03 11:31:30 +00002096 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002097 {
anthony464f1c42012-04-22 08:51:01 +00002098 CLIWandWarnReplaced(normal_op?"-level":"+level");
anthony92c93bd2012-03-19 14:02:47 +00002099 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002100 break;
2101 }
anthonyafa3dfc2012-03-03 11:31:30 +00002102 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002103 {
2104 double
2105 black_point,
2106 white_point;
2107
2108 MagickStatusType
2109 flags;
2110
anthonyfd706f92012-01-19 04:22:02 +00002111 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002112 if ((flags & RhoValue) == 0)
2113 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002114 black_point=geometry_info.rho;
2115 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2116 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002117 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002118 black_point*=(double) _image->columns*_image->rows/100.0;
2119 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002120 }
anthony92c93bd2012-03-19 14:02:47 +00002121 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002122 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002123 (void) ContrastStretchImage(_image,black_point,white_point,
2124 _exception);
anthony805a2d42011-09-25 08:25:12 +00002125 break;
2126 }
anthonyafa3dfc2012-03-03 11:31:30 +00002127 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002128 {
2129 KernelInfo
2130 *kernel_info;
2131
anthonyfd706f92012-01-19 04:22:02 +00002132 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002133 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002134 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristya12d8ba2012-04-29 16:33:41 +00002135 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2136 _exception);
anthony805a2d42011-09-25 08:25:12 +00002137 kernel_info=DestroyKernelInfo(kernel_info);
2138 break;
2139 }
anthonyafa3dfc2012-03-03 11:31:30 +00002140 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002141 {
anthony31f1bf72012-01-30 12:37:22 +00002142 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002143 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002144 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002145 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002146 break;
2147 }
anthonyafa3dfc2012-03-03 11:31:30 +00002148 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002149 {
anthony7bcfe7f2012-03-30 14:01:22 +00002150 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002151 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002152 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2153 _exception);
anthony805a2d42011-09-25 08:25:12 +00002154 break;
2155 }
anthonyebb73a22012-03-22 14:25:52 +00002156 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002157 }
2158 case 'd':
2159 {
anthonyafa3dfc2012-03-03 11:31:30 +00002160 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002161 {
anthony4837ac22012-05-18 23:39:48 +00002162 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002163 StringInfo
2164 *passkey;
2165
anthony92c93bd2012-03-19 14:02:47 +00002166 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002167 if (passkey == (StringInfo *) NULL)
2168 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2169
2170 (void) PasskeyDecipherImage(_image,passkey,_exception);
2171 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002172 break;
2173 }
anthonyafa3dfc2012-03-03 11:31:30 +00002174 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002175 {
anthony92c93bd2012-03-19 14:02:47 +00002176 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002177 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002178
anthonydcf510d2011-10-30 13:51:40 +00002179 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2180 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002181
anthonyfd706f92012-01-19 04:22:02 +00002182 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002183 */
anthony92c93bd2012-03-19 14:02:47 +00002184 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002185 break;
2186 }
anthonyafa3dfc2012-03-03 11:31:30 +00002187 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002188 {
2189 double
2190 threshold;
2191
anthonyebb73a22012-03-22 14:25:52 +00002192 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002193 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002194 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002195 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002196 }
anthonyafa3dfc2012-03-03 11:31:30 +00002197 else
2198 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002199 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002200 break;
2201 }
anthonyafa3dfc2012-03-03 11:31:30 +00002202 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002203 {
anthony92c93bd2012-03-19 14:02:47 +00002204 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002205 break;
2206 }
anthonyafa3dfc2012-03-03 11:31:30 +00002207 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002208 {
anthony805a2d42011-09-25 08:25:12 +00002209 double
anthonyb1d483a2012-04-14 12:53:56 +00002210 *args;
anthony805a2d42011-09-25 08:25:12 +00002211
anthonyb1d483a2012-04-14 12:53:56 +00002212 ssize_t
2213 count;
anthony805a2d42011-09-25 08:25:12 +00002214
anthony2a0ec8c2012-03-24 04:35:56 +00002215 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2216 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002217 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2218 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002219 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002220 {
anthony80c37752012-01-16 01:03:11 +00002221 double
2222 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002223 /* Special Case - Argument is actually a resize geometry!
2224 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002225 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002226 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002227 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002228 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2229 option,arg2);
2230 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002231 resize_args[0]=(double) geometry.width;
2232 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002233 new_image=DistortImage(_image,(DistortImageMethod) parse,
2234 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002235 break;
2236 }
anthonyb1d483a2012-04-14 12:53:56 +00002237 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002238 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002239 if (args == (double *)NULL )
2240 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2241
2242 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
2243 plus_alt_op,_exception);
2244 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002245 break;
2246 }
anthonyafa3dfc2012-03-03 11:31:30 +00002247 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002248 {
anthony92c93bd2012-03-19 14:02:47 +00002249 (void) CloneString(&_draw_info->primitive,arg1);
2250 (void) DrawImage(_image,_draw_info,_exception);
2251 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002252 break;
2253 }
anthonyebb73a22012-03-22 14:25:52 +00002254 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002255 }
2256 case 'e':
2257 {
anthonyafa3dfc2012-03-03 11:31:30 +00002258 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002259 {
anthonyfd706f92012-01-19 04:22:02 +00002260 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002261 if ((flags & (RhoValue|SigmaValue)) == 0)
2262 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002263 if ((flags & SigmaValue) == 0)
2264 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002265 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2266 _exception);
anthony805a2d42011-09-25 08:25:12 +00002267 break;
2268 }
anthonyafa3dfc2012-03-03 11:31:30 +00002269 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002270 {
anthonyfd706f92012-01-19 04:22:02 +00002271 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002272 if ((flags & (RhoValue|SigmaValue)) == 0)
2273 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002274 if ((flags & SigmaValue) == 0)
2275 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002276 new_image=EmbossImage(_image,geometry_info.rho,
2277 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002278 break;
2279 }
anthonyafa3dfc2012-03-03 11:31:30 +00002280 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002281 {
anthony4837ac22012-05-18 23:39:48 +00002282 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002283 StringInfo
2284 *passkey;
2285
anthony92c93bd2012-03-19 14:02:47 +00002286 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002287 if (passkey != (StringInfo *) NULL)
2288 {
anthony92c93bd2012-03-19 14:02:47 +00002289 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002290 passkey=DestroyStringInfo(passkey);
2291 }
2292 break;
2293 }
anthonyafa3dfc2012-03-03 11:31:30 +00002294 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002295 {
anthony92c93bd2012-03-19 14:02:47 +00002296 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002297 break;
2298 }
anthonyafa3dfc2012-03-03 11:31:30 +00002299 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002300 {
anthony92c93bd2012-03-19 14:02:47 +00002301 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002302 break;
2303 }
anthonyafa3dfc2012-03-03 11:31:30 +00002304 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002305 {
2306 double
2307 constant;
2308
anthony2a0ec8c2012-03-24 04:35:56 +00002309 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2310 if ( parse < 0 )
2311 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2312 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002313 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002314 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002315 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002316 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2317 _exception);
anthony805a2d42011-09-25 08:25:12 +00002318 break;
2319 }
anthonyafa3dfc2012-03-03 11:31:30 +00002320 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002321 {
anthony7bcfe7f2012-03-30 14:01:22 +00002322 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002323 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002324 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002325 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002326 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002327 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002328 geometry.height=_image->rows;
2329 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002330 break;
2331 }
anthonyebb73a22012-03-22 14:25:52 +00002332 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002333 }
2334 case 'f':
2335 {
anthonyafa3dfc2012-03-03 11:31:30 +00002336 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002337 {
anthony31f1bf72012-01-30 12:37:22 +00002338 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002339 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002340 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002341 break;
2342 }
anthony92c93bd2012-03-19 14:02:47 +00002343 (void) SetImageArtifact(_image,"identify:features","true");
2344 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002345 break;
2346 }
anthonyafa3dfc2012-03-03 11:31:30 +00002347 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002348 {
anthony92c93bd2012-03-19 14:02:47 +00002349 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002350 break;
2351 }
anthonyafa3dfc2012-03-03 11:31:30 +00002352 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002353 {
anthony92c93bd2012-03-19 14:02:47 +00002354 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002355 break;
2356 }
anthonyafa3dfc2012-03-03 11:31:30 +00002357 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002358 {
2359 PixelInfo
2360 target;
2361
anthony7bcfe7f2012-03-30 14:01:22 +00002362 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002363 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002364 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2365 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2366 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2367 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002368 break;
2369 }
anthonyafa3dfc2012-03-03 11:31:30 +00002370 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002371 {
2372 FrameInfo
2373 frame_info;
2374
anthony31f1bf72012-01-30 12:37:22 +00002375 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002376 compose;
2377
2378 const char*
2379 value;
2380
anthony92c93bd2012-03-19 14:02:47 +00002381 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002382 if (value != (const char *) NULL)
2383 compose=(CompositeOperator) ParseCommandOption(
2384 MagickComposeOptions,MagickFalse,value);
2385 else
anthony92c93bd2012-03-19 14:02:47 +00002386 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002387
anthony7bcfe7f2012-03-30 14:01:22 +00002388 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002389 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002390 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002391 frame_info.width=geometry.width;
2392 frame_info.height=geometry.height;
2393 if ((flags & HeightValue) == 0)
2394 frame_info.height=geometry.width;
2395 frame_info.outer_bevel=geometry.x;
2396 frame_info.inner_bevel=geometry.y;
2397 frame_info.x=(ssize_t) frame_info.width;
2398 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002399 frame_info.width=_image->columns+2*frame_info.width;
2400 frame_info.height=_image->rows+2*frame_info.height;
2401 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002402 break;
2403 }
anthonyafa3dfc2012-03-03 11:31:30 +00002404 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002405 {
anthony805a2d42011-09-25 08:25:12 +00002406 double
anthonyb1d483a2012-04-14 12:53:56 +00002407 *args;
anthony805a2d42011-09-25 08:25:12 +00002408
anthonyb1d483a2012-04-14 12:53:56 +00002409 ssize_t
2410 count;
anthony805a2d42011-09-25 08:25:12 +00002411
anthony2a0ec8c2012-03-24 04:35:56 +00002412 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2413 if ( parse < 0 )
2414 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2415 option,arg1);
anthonyb1d483a2012-04-14 12:53:56 +00002416 /* convert argument string into an array of doubles */
anthony964d28e2012-05-17 23:39:46 +00002417 args = StringToArrayOfDoubles(arg2,&count,_exception);
anthonyb1d483a2012-04-14 12:53:56 +00002418 if (args == (double *)NULL )
2419 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2420
2421 (void) FunctionImage(_image,(MagickFunction)parse,count,args,
2422 _exception);
2423 args=(double *) RelinquishMagickMemory(args);
anthony805a2d42011-09-25 08:25:12 +00002424 break;
2425 }
anthonyebb73a22012-03-22 14:25:52 +00002426 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002427 }
2428 case 'g':
2429 {
anthonyafa3dfc2012-03-03 11:31:30 +00002430 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002431 {
anthony7a4d6102012-07-01 09:48:25 +00002432 double
2433 constant;
2434
anthony7bcfe7f2012-03-30 14:01:22 +00002435 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002436 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony7a4d6102012-07-01 09:48:25 +00002437 constant=StringToDouble(arg1,(char **) NULL);
2438#if 0
2439 /* Using Gamma, via a cache */
2440 if (IfPlusOp)
2441 constant=MagickEpsilonReciprocal(constant);
2442 (void) GammaImage(_image,constant,_exception);
2443#else
2444 /* Using Evaluate POW, direct update of values - more accurite */
anthonyafa3dfc2012-03-03 11:31:30 +00002445 if (IfNormalOp)
anthony7a4d6102012-07-01 09:48:25 +00002446 constant=MagickEpsilonReciprocal(constant);
2447 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
2448#endif
2449 /* Set gamma setting -- Old meaning of "+gamma"
2450 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2451 */
anthony805a2d42011-09-25 08:25:12 +00002452 break;
2453 }
anthony975a8d72012-04-12 13:54:36 +00002454 if (LocaleCompare("gaussian-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002455 {
anthonyfd706f92012-01-19 04:22:02 +00002456 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00002457 if ((flags & (RhoValue|SigmaValue)) == 0)
2458 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002459 if ((flags & SigmaValue) == 0)
2460 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002461 new_image=GaussianBlurImage(_image,geometry_info.rho,
2462 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002463 break;
2464 }
anthony975a8d72012-04-12 13:54:36 +00002465 if (LocaleCompare("gaussian",option+1) == 0)
2466 {
anthony464f1c42012-04-22 08:51:01 +00002467 CLIWandWarnReplaced("-gaussian-blur");
anthony975a8d72012-04-12 13:54:36 +00002468 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
2469 }
anthonyafa3dfc2012-03-03 11:31:30 +00002470 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002471 {
anthonyfd706f92012-01-19 04:22:02 +00002472 /*
anthony31f1bf72012-01-30 12:37:22 +00002473 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002474 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002475 FUTURE: Why if no 'offset' does this resize ALL images?
2476 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002477 */
anthonyafa3dfc2012-03-03 11:31:30 +00002478 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002479 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002480 if (_image->geometry != (char *) NULL)
2481 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002482 break;
2483 }
anthony7bcfe7f2012-03-30 14:01:22 +00002484 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002485 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002486 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002487 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002488 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002489 else
anthony92c93bd2012-03-19 14:02:47 +00002490 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002491 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002492 break;
2493 }
anthonyebb73a22012-03-22 14:25:52 +00002494 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002495 }
anthony805a2d42011-09-25 08:25:12 +00002496 case 'i':
2497 {
anthonyafa3dfc2012-03-03 11:31:30 +00002498 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002499 {
anthony31f1bf72012-01-30 12:37:22 +00002500 const char
2501 *format,
anthony805a2d42011-09-25 08:25:12 +00002502 *text;
2503
anthony92c93bd2012-03-19 14:02:47 +00002504 format=GetImageOption(_image_info,"format");
anthony964d28e2012-05-17 23:39:46 +00002505 if (format == (char *) NULL) {
2506 (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception);
2507 break;
2508 }
anthony92c93bd2012-03-19 14:02:47 +00002509 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002510 if (text == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00002511 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
2512 option);
anthony805a2d42011-09-25 08:25:12 +00002513 (void) fputs(text,stdout);
2514 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002515 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002516 break;
2517 }
anthonyafa3dfc2012-03-03 11:31:30 +00002518 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002519 {
anthonyb1e21ed2012-04-20 12:43:12 +00002520 flags=ParseGeometry(arg1,&geometry_info);
2521 if ((flags & RhoValue) == 0)
anthonyfe1aa782012-03-24 13:43:04 +00002522 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00002523 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2524 _exception);
anthony805a2d42011-09-25 08:25:12 +00002525 break;
2526 }
anthonyafa3dfc2012-03-03 11:31:30 +00002527 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002528 {
anthonyfe1aa782012-03-24 13:43:04 +00002529 /* FUTURE: New to IMv7
2530 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002531 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002532 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002533 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2534 new_image=InterpolativeResizeImage(_image,geometry.width,
2535 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002536 break;
2537 }
anthonyebb73a22012-03-22 14:25:52 +00002538 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002539 }
2540 case 'l':
2541 {
anthonyafa3dfc2012-03-03 11:31:30 +00002542 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002543 {
anthonyfd706f92012-01-19 04:22:02 +00002544 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002545 if ((flags & (RhoValue|SigmaValue)) == 0)
2546 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002547 if ((flags & PercentValue) != 0)
2548 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002549 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002550 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002551 _exception);
anthony805a2d42011-09-25 08:25:12 +00002552 break;
2553 }
anthonyafa3dfc2012-03-03 11:31:30 +00002554 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002555 {
2556 MagickRealType
2557 black_point,
2558 gamma,
2559 white_point;
2560
2561 MagickStatusType
2562 flags;
2563
anthonyfd706f92012-01-19 04:22:02 +00002564 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002565 if ((flags & RhoValue) == 0)
2566 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002567 black_point=geometry_info.rho;
2568 white_point=(MagickRealType) QuantumRange;
2569 if ((flags & SigmaValue) != 0)
2570 white_point=geometry_info.sigma;
2571 gamma=1.0;
2572 if ((flags & XiValue) != 0)
2573 gamma=geometry_info.xi;
2574 if ((flags & PercentValue) != 0)
2575 {
2576 black_point*=(MagickRealType) (QuantumRange/100.0);
2577 white_point*=(MagickRealType) (QuantumRange/100.0);
2578 }
2579 if ((flags & SigmaValue) == 0)
2580 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002581 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002582 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002583 else
anthony92c93bd2012-03-19 14:02:47 +00002584 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002585 break;
2586 }
anthonyafa3dfc2012-03-03 11:31:30 +00002587 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002588 {
2589 char
2590 token[MaxTextExtent];
2591
2592 const char
2593 *p;
2594
2595 PixelInfo
2596 black_point,
2597 white_point;
2598
anthonyfd706f92012-01-19 04:22:02 +00002599 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002600 GetMagickToken(p,&p,token); /* get black 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 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002604 else
cristy269c9412011-10-13 23:41:15 +00002605 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002606 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002607 if (isalpha((int) token[0]) || (token[0] == '#'))
2608 GetMagickToken(p,&p,token);
2609 if (*token == '\0')
2610 white_point=black_point; /* set everything to that color */
2611 else
2612 {
2613 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2614 GetMagickToken(p,&p,token); /* Get white point color. */
2615 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002616 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002617 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002618 else
cristy269c9412011-10-13 23:41:15 +00002619 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002620 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002621 }
anthony92c93bd2012-03-19 14:02:47 +00002622 (void) LevelImageColors(_image,&black_point,&white_point,
2623 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002624 break;
2625 }
anthonyafa3dfc2012-03-03 11:31:30 +00002626 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002627 {
2628 double
2629 black_point,
2630 white_point;
2631
2632 MagickStatusType
2633 flags;
2634
anthonyfd706f92012-01-19 04:22:02 +00002635 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002636 if ((flags & RhoValue) == 0)
2637 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002638 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002639 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002640 if ((flags & SigmaValue) != 0)
2641 white_point=geometry_info.sigma;
2642 if ((flags & PercentValue) != 0)
2643 {
anthony92c93bd2012-03-19 14:02:47 +00002644 black_point*=(double) _image->columns*_image->rows/100.0;
2645 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002646 }
2647 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002648 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002649 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002650 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002651 break;
2652 }
anthonyafa3dfc2012-03-03 11:31:30 +00002653 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002654 {
anthonyfe1aa782012-03-24 13:43:04 +00002655 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002656 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002657 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002658 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002659 if ((flags & XValue) == 0)
2660 geometry.x=1;
2661 if ((flags & YValue) == 0)
2662 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002663 new_image=LiquidRescaleImage(_image,geometry.width,
2664 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002665 break;
2666 }
anthonyebb73a22012-03-22 14:25:52 +00002667 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002668 }
2669 case 'm':
2670 {
anthonyafa3dfc2012-03-03 11:31:30 +00002671 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002672 {
anthony464f1c42012-04-22 08:51:01 +00002673 CLIWandWarnReplaced("-remap");
anthony975a8d72012-04-12 13:54:36 +00002674 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
anthony805a2d42011-09-25 08:25:12 +00002675 break;
2676 }
anthonyafa3dfc2012-03-03 11:31:30 +00002677 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002678 {
anthony4837ac22012-05-18 23:39:48 +00002679 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002680 Image
2681 *mask;
2682
anthonyafa3dfc2012-03-03 11:31:30 +00002683 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002684 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002685 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002686 break;
2687 }
anthony5330ae02012-03-20 14:17:01 +00002688 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002689 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002690 if (mask == (Image *) NULL)
2691 break;
anthony92c93bd2012-03-19 14:02:47 +00002692 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002693 mask=DestroyImage(mask);
2694 break;
2695 }
anthonyafa3dfc2012-03-03 11:31:30 +00002696 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002697 {
anthony464f1c42012-04-22 08:51:01 +00002698 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
anthony92c93bd2012-03-19 14:02:47 +00002699 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2700 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002701 break;
2702 }
anthonya3ef4ed2012-03-17 06:52:53 +00002703 if (LocaleCompare("median",option+1) == 0)
2704 {
anthony464f1c42012-04-22 08:51:01 +00002705 CLIWandWarnReplaced("-statistic Median");
anthonya3ef4ed2012-03-17 06:52:53 +00002706 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2707 break;
2708 }
anthonyafa3dfc2012-03-03 11:31:30 +00002709 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002710 {
anthony975a8d72012-04-12 13:54:36 +00002711 /* FUTURE: note this is also a special "montage" option */
anthony464f1c42012-04-22 08:51:01 +00002712 CLIWandWarnReplaced("-statistic Mode");
anthony975a8d72012-04-12 13:54:36 +00002713 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
anthony805a2d42011-09-25 08:25:12 +00002714 break;
2715 }
anthonyafa3dfc2012-03-03 11:31:30 +00002716 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002717 {
anthony7bcfe7f2012-03-30 14:01:22 +00002718 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002719 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002720 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002721 break;
2722 }
anthonyafa3dfc2012-03-03 11:31:30 +00002723 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002724 {
anthony92c93bd2012-03-19 14:02:47 +00002725 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002726 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002727 break;
2728 }
anthonyafa3dfc2012-03-03 11:31:30 +00002729 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002730 {
anthony92c93bd2012-03-19 14:02:47 +00002731 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002732 break;
2733 }
anthonyafa3dfc2012-03-03 11:31:30 +00002734 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002735 {
2736 char
2737 token[MaxTextExtent];
2738
2739 const char
2740 *p;
2741
2742 KernelInfo
2743 *kernel;
2744
anthony805a2d42011-09-25 08:25:12 +00002745 ssize_t
2746 iterations;
2747
anthonyfd706f92012-01-19 04:22:02 +00002748 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002749 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002750 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2751 if ( parse < 0 )
2752 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2753 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002754 iterations=1L;
2755 GetMagickToken(p,&p,token);
2756 if ((*p == ':') || (*p == ','))
2757 GetMagickToken(p,&p,token);
2758 if ((*p != '\0'))
2759 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002760 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002761 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002762 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2763 option,arg2);
2764 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2765 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002766 kernel=DestroyKernelInfo(kernel);
2767 break;
2768 }
anthonyafa3dfc2012-03-03 11:31:30 +00002769 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002770 {
anthonyfd706f92012-01-19 04:22:02 +00002771 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002772 if ((flags & (RhoValue|SigmaValue)) == 0)
2773 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002774 if ((flags & SigmaValue) == 0)
2775 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002776 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002777 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002778 break;
2779 }
anthonyebb73a22012-03-22 14:25:52 +00002780 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002781 }
2782 case 'n':
2783 {
anthonyafa3dfc2012-03-03 11:31:30 +00002784 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002785 {
anthony92c93bd2012-03-19 14:02:47 +00002786 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002787 break;
2788 }
anthonyafa3dfc2012-03-03 11:31:30 +00002789 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002790 {
anthony975a8d72012-04-12 13:54:36 +00002791 double
2792 attenuate;
2793
2794 const char*
2795 value;
2796
anthonyafa3dfc2012-03-03 11:31:30 +00002797 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002798 {
anthony464f1c42012-04-22 08:51:01 +00002799 CLIWandWarnReplaced("-statistic NonPeak");
anthony975a8d72012-04-12 13:54:36 +00002800 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
2801 break;
anthony805a2d42011-09-25 08:25:12 +00002802 }
anthony975a8d72012-04-12 13:54:36 +00002803 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2804 if ( parse < 0 )
2805 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2806 option,arg1);
2807 attenuate=1.0;
2808 value=GetImageOption(_image_info,"attenuate");
2809 if (value != (const char *) NULL)
2810 attenuate=StringToDouble(value,(char **) NULL);
2811 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2812 _exception);
anthony805a2d42011-09-25 08:25:12 +00002813 break;
2814 }
anthonyafa3dfc2012-03-03 11:31:30 +00002815 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002816 {
anthony92c93bd2012-03-19 14:02:47 +00002817 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002818 break;
2819 }
anthonyebb73a22012-03-22 14:25:52 +00002820 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002821 }
2822 case 'o':
2823 {
anthonyafa3dfc2012-03-03 11:31:30 +00002824 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002825 {
2826 PixelInfo
2827 target;
2828
anthony92c93bd2012-03-19 14:02:47 +00002829 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2830 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2831 _exception);
anthony805a2d42011-09-25 08:25:12 +00002832 break;
2833 }
anthonyafa3dfc2012-03-03 11:31:30 +00002834 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002835 {
anthony92c93bd2012-03-19 14:02:47 +00002836 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002837 break;
2838 }
anthonyebb73a22012-03-22 14:25:52 +00002839 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002840 }
2841 case 'p':
2842 {
anthonyafa3dfc2012-03-03 11:31:30 +00002843 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002844 {
anthony22de2722012-04-19 14:43:00 +00002845 flags=ParseGeometry(arg1,&geometry_info);
2846 if ((flags & (RhoValue|SigmaValue)) == 0)
2847 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002848 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2849 _exception);
anthony805a2d42011-09-25 08:25:12 +00002850 break;
2851 }
anthonyafa3dfc2012-03-03 11:31:30 +00002852 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002853 {
cristye9e3d382011-12-14 01:50:13 +00002854 const char
2855 *caption;
2856
anthony805a2d42011-09-25 08:25:12 +00002857 double
2858 angle;
2859
anthony7bc87992012-03-25 02:32:51 +00002860 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00002861 RandomInfo
2862 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002863
anthonyf42014d2012-03-25 09:53:06 +00002864 random_info=AcquireRandomInfo();
2865 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2866 random_info=DestroyRandomInfo(random_info);
2867 }
anthony7bc87992012-03-25 02:32:51 +00002868 else {
anthonyf42014d2012-03-25 09:53:06 +00002869 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002870 if ((flags & RhoValue) == 0)
2871 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00002872 angle=geometry_info.rho;
2873 }
anthony92c93bd2012-03-19 14:02:47 +00002874 caption=GetImageProperty(_image,"caption",_exception);
2875 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2876 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002877 break;
2878 }
anthonyafa3dfc2012-03-03 11:31:30 +00002879 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002880 {
anthony22de2722012-04-19 14:43:00 +00002881 flags=ParseGeometry(arg1,&geometry_info);
2882 if ((flags & RhoValue) == 0)
anthony7bc87992012-03-25 02:32:51 +00002883 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002884 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
cristycbda6112012-05-27 20:57:16 +00002885 _quantize_info->dither_method,_exception);
anthony805a2d42011-09-25 08:25:12 +00002886 break;
2887 }
anthonyafa3dfc2012-03-03 11:31:30 +00002888 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002889 {
anthony31f1bf72012-01-30 12:37:22 +00002890 /* FUTURE: should be a 'Genesis' option?
2891 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00002892 Why???
cristy947cb4c2011-10-20 18:41:46 +00002893 */
anthony7bc87992012-03-25 02:32:51 +00002894 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2895 if ( parse < 0 )
2896 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2897 option,arg1);
2898 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00002899 break;
2900 }
anthonyafa3dfc2012-03-03 11:31:30 +00002901 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002902 {
anthony4837ac22012-05-18 23:39:48 +00002903 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002904 const char
2905 *name;
2906
2907 const StringInfo
2908 *profile;
2909
2910 Image
2911 *profile_image;
2912
2913 ImageInfo
2914 *profile_info;
2915
anthonyafa3dfc2012-03-03 11:31:30 +00002916 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002917 { /* Remove a profile from the _image. */
2918 (void) ProfileImage(_image,arg1,(const unsigned char *)
2919 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002920 break;
2921 }
anthony92c93bd2012-03-19 14:02:47 +00002922 /* Associate a profile with the _image. */
2923 profile_info=CloneImageInfo(_image_info);
2924 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002925 if (profile != (StringInfo *) NULL)
2926 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002927 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002928 profile_info=DestroyImageInfo(profile_info);
2929 if (profile_image == (Image *) NULL)
2930 {
2931 StringInfo
2932 *profile;
2933
anthony92c93bd2012-03-19 14:02:47 +00002934 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002935 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002936 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002937 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002938 if (profile != (StringInfo *) NULL)
2939 {
anthony92c93bd2012-03-19 14:02:47 +00002940 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002941 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002942 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002943 profile=DestroyStringInfo(profile);
2944 }
2945 profile_info=DestroyImageInfo(profile_info);
2946 break;
2947 }
2948 ResetImageProfileIterator(profile_image);
2949 name=GetNextImageProfile(profile_image);
2950 while (name != (const char *) NULL)
2951 {
2952 profile=GetImageProfile(profile_image,name);
2953 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002954 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2955 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002956 name=GetNextImageProfile(profile_image);
2957 }
2958 profile_image=DestroyImage(profile_image);
2959 break;
2960 }
anthonyebb73a22012-03-22 14:25:52 +00002961 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002962 }
anthony805a2d42011-09-25 08:25:12 +00002963 case 'r':
2964 {
anthonyafa3dfc2012-03-03 11:31:30 +00002965 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002966 {
anthonyfd706f92012-01-19 04:22:02 +00002967 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00002968 if ((flags & RhoValue) == 0)
2969 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
cristyaa2c16c2012-03-25 22:21:35 +00002970 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00002971 break;
2972 }
anthonyafa3dfc2012-03-03 11:31:30 +00002973 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002974 {
anthony7bcfe7f2012-03-30 14:01:22 +00002975 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002976 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002977 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002978 if ((flags & SigmaValue) == 0)
2979 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00002980 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002981 break;
2982 }
anthonyafa3dfc2012-03-03 11:31:30 +00002983 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002984 {
anthony7bcfe7f2012-03-30 14:01:22 +00002985 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00002986 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002987 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002988 break;
2989 }
anthony975a8d72012-04-12 13:54:36 +00002990 if (LocaleCompare("recolor",option+1) == 0)
2991 {
anthony464f1c42012-04-22 08:51:01 +00002992 CLIWandWarnReplaced("-color-matrix");
anthony975a8d72012-04-12 13:54:36 +00002993 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
2994 }
anthonyafa3dfc2012-03-03 11:31:30 +00002995 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002996 {
anthony4837ac22012-05-18 23:39:48 +00002997 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00002998 Image
2999 *remap_image;
3000
anthony92c93bd2012-03-19 14:02:47 +00003001 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003002 if (remap_image == (Image *) NULL)
3003 break;
anthony92c93bd2012-03-19 14:02:47 +00003004 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003005 remap_image=DestroyImage(remap_image);
3006 break;
3007 }
anthonyafa3dfc2012-03-03 11:31:30 +00003008 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003009 {
anthonyafa3dfc2012-03-03 11:31:30 +00003010 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00003011 {
anthony7bcfe7f2012-03-30 14:01:22 +00003012 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00003013 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3014 arg1);
3015 (void) ResetImagePage(_image,arg1);
3016 }
anthony31f1bf72012-01-30 12:37:22 +00003017 else
anthony92c93bd2012-03-19 14:02:47 +00003018 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003019 break;
3020 }
anthonyafa3dfc2012-03-03 11:31:30 +00003021 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003022 {
anthonyf46d4262012-03-26 03:30:34 +00003023 /* FUTURE: Roll into a resize special operation */
anthonyfd706f92012-01-19 04:22:02 +00003024 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003025 if ((flags & (RhoValue|SigmaValue)) == 0)
3026 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003027 if ((flags & SigmaValue) == 0)
3028 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003029 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003030 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003031 break;
3032 }
anthonyafa3dfc2012-03-03 11:31:30 +00003033 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003034 {
anthony7bcfe7f2012-03-30 14:01:22 +00003035 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003036 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003037 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3038 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003039 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003040 break;
3041 }
anthonyafa3dfc2012-03-03 11:31:30 +00003042 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003043 {
anthony7bcfe7f2012-03-30 14:01:22 +00003044 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003045 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003046 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3047 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003048 break;
3049 }
anthonyafa3dfc2012-03-03 11:31:30 +00003050 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003051 {
anthony22de2722012-04-19 14:43:00 +00003052 flags=ParseGeometry(arg1,&geometry_info);
3053 if ((flags & RhoValue) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003054 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyad255a02012-04-19 15:02:01 +00003055 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
anthony22de2722012-04-19 14:43:00 +00003056 break;
3057 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3058 break;
anthony92c93bd2012-03-19 14:02:47 +00003059 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003060 break;
3061 }
anthonyebb73a22012-03-22 14:25:52 +00003062 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003063 }
3064 case 's':
3065 {
anthonyafa3dfc2012-03-03 11:31:30 +00003066 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003067 {
anthonyfe1aa782012-03-24 13:43:04 +00003068 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003069 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003070 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003071 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3072 new_image=SampleImage(_image,geometry.width,geometry.height,
3073 _exception);
anthony805a2d42011-09-25 08:25:12 +00003074 break;
3075 }
anthonyafa3dfc2012-03-03 11:31:30 +00003076 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003077 {
anthonyfe1aa782012-03-24 13:43:04 +00003078 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003079 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003080 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003081 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3082 new_image=ScaleImage(_image,geometry.width,geometry.height,
3083 _exception);
anthony805a2d42011-09-25 08:25:12 +00003084 break;
3085 }
anthonyf42014d2012-03-25 09:53:06 +00003086 if (LocaleCompare("segment",option+1) == 0)
3087 {
anthonyf42014d2012-03-25 09:53:06 +00003088 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003089 if ((flags & (RhoValue|SigmaValue)) == 0)
3090 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00003091 if ((flags & SigmaValue) == 0)
3092 geometry_info.sigma=1.0;
3093 (void) SegmentImage(_image,_image->colorspace,
3094 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3095 _exception);
3096 break;
3097 }
anthonyafa3dfc2012-03-03 11:31:30 +00003098 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003099 {
anthonyfd706f92012-01-19 04:22:02 +00003100 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003101 if ((flags & (RhoValue|SigmaValue)) == 0)
3102 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3103 if ((flags & SigmaValue) == 0)
3104 geometry_info.sigma=1.0;
anthony805a2d42011-09-25 08:25:12 +00003105 if ((flags & PercentValue) != 0)
3106 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003107 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003108 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003109 break;
3110 }
anthonyafa3dfc2012-03-03 11:31:30 +00003111 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003112 {
anthony31f1bf72012-01-30 12:37:22 +00003113 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003114 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003115 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003116 break;
3117 }
anthonyafa3dfc2012-03-03 11:31:30 +00003118 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003119 {
anthony7bcfe7f2012-03-30 14:01:22 +00003120 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003121 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3122 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3123 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003124 break;
3125 }
anthonyafa3dfc2012-03-03 11:31:30 +00003126 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003127 {
anthony4837ac22012-05-18 23:39:48 +00003128 /* Note: arguments do not have percent escapes expanded */
anthony805a2d42011-09-25 08:25:12 +00003129 char
3130 *value;
3131
anthonyf42014d2012-03-25 09:53:06 +00003132 if (IfPlusOp) {
anthonyfd706f92012-01-19 04:22:02 +00003133 if (LocaleNCompare(arg1,"registry:",9) == 0)
3134 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003135 else
anthony31f1bf72012-01-30 12:37:22 +00003136 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003137 {
anthony92c93bd2012-03-19 14:02:47 +00003138 (void) DeleteImageOption(_image_info,arg1+7);
3139 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003140 }
3141 else
anthony92c93bd2012-03-19 14:02:47 +00003142 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003143 break;
3144 }
anthonyf42014d2012-03-25 09:53:06 +00003145 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003146 if (value == (char *) NULL)
anthony964d28e2012-05-17 23:39:46 +00003147 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
3148 option);
anthonyfd706f92012-01-19 04:22:02 +00003149 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003150 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003151 else
anthonyfd706f92012-01-19 04:22:02 +00003152 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003153 {
anthony92c93bd2012-03-19 14:02:47 +00003154 (void) SetImageOption(_image_info,arg1+7,value);
3155 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003156 }
3157 else
anthony92c93bd2012-03-19 14:02:47 +00003158 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003159 value=DestroyString(value);
3160 break;
3161 }
anthonyafa3dfc2012-03-03 11:31:30 +00003162 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003163 {
anthonyfd706f92012-01-19 04:22:02 +00003164 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003165 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3166 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003167 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3168 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003169 break;
3170 }
anthonyafa3dfc2012-03-03 11:31:30 +00003171 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003172 {
anthonyfd706f92012-01-19 04:22:02 +00003173 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003174 if ((flags & (RhoValue|SigmaValue)) == 0)
3175 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003176 if ((flags & SigmaValue) == 0)
3177 geometry_info.sigma=1.0;
3178 if ((flags & XiValue) == 0)
3179 geometry_info.xi=4.0;
3180 if ((flags & PsiValue) == 0)
3181 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003182 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3183 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3184 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003185 break;
3186 }
anthonyafa3dfc2012-03-03 11:31:30 +00003187 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003188 {
anthonyfd706f92012-01-19 04:22:02 +00003189 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003190 if ((flags & (RhoValue|SigmaValue)) == 0)
3191 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003192 if ((flags & SigmaValue) == 0)
3193 geometry_info.sigma=1.0;
3194 if ((flags & XiValue) == 0)
3195 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003196 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3197 _exception);
anthony805a2d42011-09-25 08:25:12 +00003198 break;
3199 }
anthonyafa3dfc2012-03-03 11:31:30 +00003200 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003201 {
anthony7bcfe7f2012-03-30 14:01:22 +00003202 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003203 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003204 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3205 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003206 break;
3207 }
anthonyafa3dfc2012-03-03 11:31:30 +00003208 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003209 {
anthonyfd706f92012-01-19 04:22:02 +00003210 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003211 if ((flags & RhoValue) == 0)
3212 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003213 if ((flags & SigmaValue) == 0)
3214 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003215 new_image=ShearImage(_image,geometry_info.rho,
3216 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003217 break;
3218 }
anthonyafa3dfc2012-03-03 11:31:30 +00003219 if (LocaleCompare("sigmoidal-contrast",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) == 0)
3223 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003224 if ((flags & SigmaValue) == 0)
3225 geometry_info.sigma=(double) QuantumRange/2.0;
3226 if ((flags & PercentValue) != 0)
3227 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3228 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003229 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthonyb1d483a2012-04-14 12:53:56 +00003230 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003231 break;
3232 }
anthonyafa3dfc2012-03-03 11:31:30 +00003233 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003234 {
anthonyfd706f92012-01-19 04:22:02 +00003235 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003236 if ((flags & (RhoValue|SigmaValue)) == 0)
3237 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003238 if ((flags & SigmaValue) == 0)
3239 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003240 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003241 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003242 break;
3243 }
anthonyafa3dfc2012-03-03 11:31:30 +00003244 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003245 {
anthony7bcfe7f2012-03-30 14:01:22 +00003246 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003247 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003248 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3249 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003250 break;
3251 }
anthonyafa3dfc2012-03-03 11:31:30 +00003252 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003253 {
anthonyf42014d2012-03-25 09:53:06 +00003254 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3255 if ( parse < 0 )
3256 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3257 option,arg1);
anthony964d28e2012-05-17 23:39:46 +00003258 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3259 _exception);
anthony805a2d42011-09-25 08:25:12 +00003260 break;
3261 }
anthonyafa3dfc2012-03-03 11:31:30 +00003262 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003263 {
anthony7bcfe7f2012-03-30 14:01:22 +00003264 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003265 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyb1e21ed2012-04-20 12:43:12 +00003266 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003267 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003268 break;
3269 }
anthonyafa3dfc2012-03-03 11:31:30 +00003270 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003271 {
anthonyb1e21ed2012-04-20 12:43:12 +00003272 flags=ParseGeometry(arg1,&geometry_info);
3273 if ((flags & RhoValue) == 0)
3274 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony92c93bd2012-03-19 14:02:47 +00003275 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3276 _exception);
anthony805a2d42011-09-25 08:25:12 +00003277 break;
3278 }
anthonyafa3dfc2012-03-03 11:31:30 +00003279 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003280 {
anthony7bc87992012-03-25 02:32:51 +00003281 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3282 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003283 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003284 option,arg1);
anthony975a8d72012-04-12 13:54:36 +00003285 flags=ParseGeometry(arg2,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003286 if ((flags & RhoValue) == 0)
3287 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony975a8d72012-04-12 13:54:36 +00003288 if ((flags & SigmaValue) == 0)
3289 geometry_info.sigma=geometry_info.rho;
anthony7bc87992012-03-25 02:32:51 +00003290 new_image=StatisticImage(_image,(StatisticType)parse,
3291 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3292 _exception);
anthony805a2d42011-09-25 08:25:12 +00003293 break;
3294 }
anthonyafa3dfc2012-03-03 11:31:30 +00003295 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003296 {
anthony92c93bd2012-03-19 14:02:47 +00003297 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003298 break;
3299 }
anthonyafa3dfc2012-03-03 11:31:30 +00003300 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003301 {
cristy898c6042012-06-24 00:36:34 +00003302 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00003303 if ((flags & RhoValue) == 0)
cristy898c6042012-06-24 00:36:34 +00003304 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003305 new_image=SwirlImage(_image,geometry_info.rho,
3306 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003307 break;
3308 }
anthonyebb73a22012-03-22 14:25:52 +00003309 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003310 }
3311 case 't':
3312 {
anthonyafa3dfc2012-03-03 11:31:30 +00003313 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003314 {
3315 double
3316 threshold;
3317
anthony52bef752012-03-27 13:54:47 +00003318 threshold=(double) QuantumRange/2;
3319 if (normal_op) {
anthony7bcfe7f2012-03-30 14:01:22 +00003320 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003321 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003322 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003323 }
anthony92c93bd2012-03-19 14:02:47 +00003324 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003325 break;
3326 }
anthonyafa3dfc2012-03-03 11:31:30 +00003327 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003328 {
anthony7bcfe7f2012-03-30 14:01:22 +00003329 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003330 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003331 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3332 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3333 _exception);
anthony805a2d42011-09-25 08:25:12 +00003334 break;
3335 }
anthonyafa3dfc2012-03-03 11:31:30 +00003336 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003337 {
anthony7bcfe7f2012-03-30 14:01:22 +00003338 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003339 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003340 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003341 break;
3342 }
anthonyafa3dfc2012-03-03 11:31:30 +00003343 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003344 {
anthony464f1c42012-04-22 08:51:01 +00003345 CLIWandWarnReplaced("+distort AffineProjection");
anthony52bef752012-03-27 13:54:47 +00003346 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003347 break;
3348 }
anthonyafa3dfc2012-03-03 11:31:30 +00003349 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003350 {
3351 PixelInfo
3352 target;
3353
anthony92c93bd2012-03-19 14:02:47 +00003354 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3355 (void) TransparentPaintImage(_image,&target,(Quantum)
3356 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003357 break;
3358 }
anthonyafa3dfc2012-03-03 11:31:30 +00003359 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003360 {
anthony92c93bd2012-03-19 14:02:47 +00003361 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003362 break;
3363 }
anthonyafa3dfc2012-03-03 11:31:30 +00003364 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003365 {
anthony92c93bd2012-03-19 14:02:47 +00003366 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003367 break;
3368 }
anthonyafa3dfc2012-03-03 11:31:30 +00003369 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003370 {
anthony92c93bd2012-03-19 14:02:47 +00003371 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003372 break;
3373 }
anthonyafa3dfc2012-03-03 11:31:30 +00003374 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003375 {
anthonyab3a50c2011-10-27 11:48:57 +00003376 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003377 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003378 break;
3379 }
anthonyebb73a22012-03-22 14:25:52 +00003380 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003381 }
3382 case 'u':
3383 {
anthonyafa3dfc2012-03-03 11:31:30 +00003384 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003385 {
anthony52bef752012-03-27 13:54:47 +00003386 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3387 Option is not documented, bt appears to be for "identify".
3388 We may need a identify specific verbose!
3389 */
3390 if (plus_alt_op) {
anthony92c93bd2012-03-19 14:02:47 +00003391 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003392 break;
3393 }
anthony92c93bd2012-03-19 14:02:47 +00003394 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3395 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003396 break;
3397 }
anthonyafa3dfc2012-03-03 11:31:30 +00003398 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003399 {
anthony92c93bd2012-03-19 14:02:47 +00003400 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003401 break;
3402 }
anthonyafa3dfc2012-03-03 11:31:30 +00003403 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003404 {
anthonyfd706f92012-01-19 04:22:02 +00003405 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003406 if ((flags & (RhoValue|SigmaValue)) == 0)
3407 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003408 if ((flags & SigmaValue) == 0)
3409 geometry_info.sigma=1.0;
3410 if ((flags & XiValue) == 0)
3411 geometry_info.xi=1.0;
3412 if ((flags & PsiValue) == 0)
3413 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003414 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3415 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003416 break;
3417 }
anthonyebb73a22012-03-22 14:25:52 +00003418 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003419 }
3420 case 'v':
3421 {
anthonyafa3dfc2012-03-03 11:31:30 +00003422 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003423 {
anthonyafa3dfc2012-03-03 11:31:30 +00003424 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003425 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003426 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003427 */
anthony92c93bd2012-03-19 14:02:47 +00003428 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003429 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003430 break;
3431 }
anthonyafa3dfc2012-03-03 11:31:30 +00003432 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003433 {
anthonyfd706f92012-01-19 04:22:02 +00003434 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003435 if ((flags & (RhoValue|SigmaValue)) == 0)
3436 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003437 if ((flags & SigmaValue) == 0)
3438 geometry_info.sigma=1.0;
3439 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003440 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003441 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003442 geometry_info.psi=0.1*_image->rows;
3443 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003444 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3445 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003446 break;
3447 }
anthonyebb73a22012-03-22 14:25:52 +00003448 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003449 }
3450 case 'w':
3451 {
anthonyafa3dfc2012-03-03 11:31:30 +00003452 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003453 {
anthonyfd706f92012-01-19 04:22:02 +00003454 flags=ParseGeometry(arg1,&geometry_info);
anthony22de2722012-04-19 14:43:00 +00003455 if ((flags & (RhoValue|SigmaValue)) == 0)
3456 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003457 if ((flags & SigmaValue) == 0)
3458 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003459 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3460 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003461 break;
3462 }
anthonyafa3dfc2012-03-03 11:31:30 +00003463 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003464 {
anthony7bcfe7f2012-03-30 14:01:22 +00003465 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003466 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003467 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003468 break;
3469 }
anthonyebb73a22012-03-22 14:25:52 +00003470 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003471 }
3472 default:
anthonyebb73a22012-03-22 14:25:52 +00003473 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003474 }
anthony964d28e2012-05-17 23:39:46 +00003475 /* clean up percent escape interpreted strings */
3476 if (arg1 != arg1n )
3477 arg1=DestroyString((char *)arg1);
3478 if (arg2 != arg2n )
3479 arg2=DestroyString((char *)arg2);
3480
3481 /* Replace current image with any image that was generated
3482 and set image point to last image (so image->next is correct) */
anthony805a2d42011-09-25 08:25:12 +00003483 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003484 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003485
anthony31f1bf72012-01-30 12:37:22 +00003486 return;
anthony92c93bd2012-03-19 14:02:47 +00003487#undef _image_info
3488#undef _draw_info
3489#undef _quantize_info
3490#undef _image
3491#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003492#undef IfNormalOp
3493#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003494#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003495#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003496}
anthonyfd706f92012-01-19 04:22:02 +00003497
anthony43f425d2012-02-26 12:58:58 +00003498WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003499 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003500{
3501 size_t
anthony43f425d2012-02-26 12:58:58 +00003502 n,
anthony31f1bf72012-01-30 12:37:22 +00003503 i;
3504
anthony43f425d2012-02-26 12:58:58 +00003505 assert(cli_wand != (MagickCLI *) NULL);
3506 assert(cli_wand->signature == WandSignature);
3507 assert(cli_wand->wand.signature == WandSignature);
3508 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003509 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003510 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003511
anthonyafa3dfc2012-03-03 11:31:30 +00003512#if !USE_WAND_METHODS
3513 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003514 i=0;
anthony43f425d2012-02-26 12:58:58 +00003515 n=GetImageListLength(cli_wand->wand.images);
3516 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003517 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003518 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003519 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003520 if ( cli_wand->wand.images->next == (Image *) NULL )
3521 break;
3522 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003523 }
anthony43f425d2012-02-26 12:58:58 +00003524 assert( i == n );
3525 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003526#else
3527 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003528 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
anthonyafa3dfc2012-03-03 11:31:30 +00003529 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3530 MagickResetIterator(&cli_wand->wand);
3531#endif
anthony31f1bf72012-01-30 12:37:22 +00003532 return;
anthony805a2d42011-09-25 08:25:12 +00003533}
3534
3535/*
3536%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3537% %
3538% %
3539% %
anthony43f425d2012-02-26 12:58:58 +00003540+ 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 +00003541% %
3542% %
3543% %
3544%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3545%
anthony43f425d2012-02-26 12:58:58 +00003546% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003547% entire image list as a whole. The result is often a complete replacment
3548% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003549%
3550% The format of the MogrifyImage method is:
3551%
anthony43f425d2012-02-26 12:58:58 +00003552% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003553% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003554%
3555% A description of each parameter follows:
3556%
anthony43f425d2012-02-26 12:58:58 +00003557% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003558%
anthony36a8c2c2012-02-10 00:08:44 +00003559% o option: The option string for the operation
3560%
anthony31f1bf72012-01-30 12:37:22 +00003561% o arg1, arg2: optional argument strings to the operation
anthonye5fcd362012-04-09 04:02:09 +00003562% arg2 is currently not used
anthony8b10b462012-02-08 12:32:44 +00003563%
anthony805a2d42011-09-25 08:25:12 +00003564*/
anthony43f425d2012-02-26 12:58:58 +00003565WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthony964d28e2012-05-17 23:39:46 +00003566 const char *option,const char *arg1n, const char *arg2n)
anthony805a2d42011-09-25 08:25:12 +00003567{
anthony2a0ec8c2012-03-24 04:35:56 +00003568 ssize_t
3569 parse;
3570
anthony31f1bf72012-01-30 12:37:22 +00003571 Image
3572 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003573
anthony964d28e2012-05-17 23:39:46 +00003574 const char /* For percent escape interpretImageProperties() */
3575 *arg1,
3576 *arg2;
3577
anthony2e4501b2012-03-30 04:41:54 +00003578#define _image_info (cli_wand->wand.image_info)
3579#define _images (cli_wand->wand.images)
3580#define _exception (cli_wand->wand.exception)
3581#define _draw_info (cli_wand->draw_info)
3582#define _quantize_info (cli_wand->quantize_info)
anthony964d28e2012-05-17 23:39:46 +00003583#define _process_flags (cli_wand->process_flags)
3584#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
anthonyafa3dfc2012-03-03 11:31:30 +00003585#define IfNormalOp (*option=='-')
3586#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00003587#define normal_op IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003588
anthony43f425d2012-02-26 12:58:58 +00003589 assert(cli_wand != (MagickCLI *) NULL);
3590 assert(cli_wand->signature == WandSignature);
3591 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003592 assert(_images != (Image *) NULL); /* _images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003593 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003594 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003595
anthony964d28e2012-05-17 23:39:46 +00003596 /* Interpret Percent Escapes in Arguments - using first image */
3597 arg1 = arg1n;
3598 arg2 = arg2n;
3599 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3600 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3601 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3602 /* Interpret Percent escapes in argument 1 */
3603 if (arg1n != (char *) NULL) {
3604 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3605 if (arg1 == (char *) NULL) {
3606 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3607 arg1=arg1n; /* use the given argument as is */
3608 }
3609 }
3610 if (arg2n != (char *) NULL) {
3611 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3612 if (arg2 == (char *) NULL) {
3613 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3614 arg2=arg2n; /* use the given argument as is */
3615 }
3616 }
3617 }
anthony4837ac22012-05-18 23:39:48 +00003618#undef _process_flags
anthony964d28e2012-05-17 23:39:46 +00003619#undef _option_type
3620
3621#if 0
3622 (void) FormatLocaleFile(stderr,
3623 "CLIListOperatorImages: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
3624#endif
3625
3626
anthony31f1bf72012-01-30 12:37:22 +00003627 new_images=NewImageList();
3628
anthonyafa3dfc2012-03-03 11:31:30 +00003629 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003630 {
3631 case 'a':
3632 {
anthonyafa3dfc2012-03-03 11:31:30 +00003633 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003634 {
anthony92c93bd2012-03-19 14:02:47 +00003635 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003636 break;
3637 }
anthonyafa3dfc2012-03-03 11:31:30 +00003638 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003639 {
anthony464f1c42012-04-22 08:51:01 +00003640 CLIWandWarnReplaced("-evaluate-sequence Mean");
anthonyafa3dfc2012-03-03 11:31:30 +00003641 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003642 break;
3643 }
anthonyebb73a22012-03-22 14:25:52 +00003644 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003645 }
3646 case 'c':
3647 {
cristy5f257b22012-03-07 00:27:29 +00003648 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003649 {
anthony92c93bd2012-03-19 14:02:47 +00003650 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003651 break;
3652 }
anthonyafa3dfc2012-03-03 11:31:30 +00003653 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003654 {
anthony805a2d42011-09-25 08:25:12 +00003655 Image
anthony31f1bf72012-01-30 12:37:22 +00003656 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003657
anthonyafa3dfc2012-03-03 11:31:30 +00003658 /* FUTURE - make this a compose option, and thus can be used
3659 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003660 _images.
cristy87c02f42012-02-24 00:19:10 +00003661 */
anthony92c93bd2012-03-19 14:02:47 +00003662 new_images=RemoveFirstImageFromList(&_images);
3663 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003664 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003665 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003666 break;
cristye52fb5e2012-04-06 23:30:20 +00003667 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003668 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003669 break;
3670 }
anthonyafa3dfc2012-03-03 11:31:30 +00003671 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003672 {
anthony92c93bd2012-03-19 14:02:47 +00003673 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003674 break;
3675 }
anthonyafa3dfc2012-03-03 11:31:30 +00003676 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003677 {
anthony43f425d2012-02-26 12:58:58 +00003678 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003679 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003680 break;
3681 }
anthonyafa3dfc2012-03-03 11:31:30 +00003682 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003683 {
cristyfeb3e962012-03-29 17:25:55 +00003684 CompositeOperator
3685 compose;
3686
3687 const char*
3688 value;
3689
3690 MagickBooleanType
3691 clip_to_self;
3692
anthony805a2d42011-09-25 08:25:12 +00003693 Image
3694 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003695 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003696
3697 RectangleInfo
3698 geometry;
3699
anthony7bcfe7f2012-03-30 14:01:22 +00003700 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003701 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003702 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003703 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003704 else
3705 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3706 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003707
anthony7bcfe7f2012-03-30 14:01:22 +00003708 /* Get "clip-to-self" expert setting (false is normal) */
cristyca0e82c2012-04-10 11:53:24 +00003709 value=GetImageOption(_image_info,"compose:clip-to-self");
3710 if (value == (const char *) NULL)
3711 clip_to_self=MagickTrue;
3712 else
3713 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3714 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003715 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003716 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003717 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003718 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003719 }
3720
anthony92c93bd2012-03-19 14:02:47 +00003721 new_images=RemoveFirstImageFromList(&_images);
3722 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003723 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003724 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003725
anthony31f1bf72012-01-30 12:37:22 +00003726 /* FUTURE - this should not be here! - should be part of -geometry */
3727 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003728 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003729
anthony31f1bf72012-01-30 12:37:22 +00003730 SetGeometry(source_image,&geometry);
3731 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3732 GravityAdjustGeometry(new_images->columns,new_images->rows,
3733 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003734
anthony92c93bd2012-03-19 14:02:47 +00003735 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003736 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003737 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003738 if ((compose == DisplaceCompositeOp) ||
anthony7bcfe7f2012-03-30 14:01:22 +00003739 (compose == DistortCompositeOp)) {
3740 /* Merge Y displacement into X displace/distort map. */
3741 (void) CompositeImage(source_image,mask_image,
3742 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3743 mask_image=DestroyImage(mask_image);
3744 }
3745 else {
3746 /* Set a blending mask for the composition. */
3747 (void) NegateImage(mask_image,MagickFalse,_exception);
cristy665e18f2012-05-17 12:39:54 +00003748 (void) SetImageMask(source_image,mask_image,_exception);
anthony7bcfe7f2012-03-30 14:01:22 +00003749 mask_image=DestroyImage(mask_image);
3750 }
anthony805a2d42011-09-25 08:25:12 +00003751 }
cristyfeb3e962012-03-29 17:25:55 +00003752 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3753 geometry.x,geometry.y,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003754 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003755 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003756 break;
3757 }
anthonyebb73a22012-03-22 14:25:52 +00003758 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003759 }
3760 case 'd':
3761 {
anthonyafa3dfc2012-03-03 11:31:30 +00003762 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003763 {
anthony464f1c42012-04-22 08:51:01 +00003764 CLIWandWarnReplaced("-layer CompareAny");
anthonyafa3dfc2012-03-03 11:31:30 +00003765 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003766 break;
3767 }
anthonyafa3dfc2012-03-03 11:31:30 +00003768 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003769 {
anthonyafa3dfc2012-03-03 11:31:30 +00003770 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003771 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003772 else
anthony92c93bd2012-03-19 14:02:47 +00003773 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003774 break;
3775 }
anthonyafa3dfc2012-03-03 11:31:30 +00003776 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003777 {
anthonyafa3dfc2012-03-03 11:31:30 +00003778 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003779 {
3780 const char
3781 *p;
3782
3783 size_t
3784 number_duplicates;
3785
anthony7bcfe7f2012-03-30 14:01:22 +00003786 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003787 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3788 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003789 number_duplicates=(size_t) StringToLong(arg1);
3790 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003791 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003792 new_images=DuplicateImages(_images,number_duplicates,"-1",
3793 _exception);
anthony805a2d42011-09-25 08:25:12 +00003794 else
anthony92c93bd2012-03-19 14:02:47 +00003795 new_images=DuplicateImages(_images,number_duplicates,p,
3796 _exception);
anthony805a2d42011-09-25 08:25:12 +00003797 }
anthonyafa3dfc2012-03-03 11:31:30 +00003798 else
anthony92c93bd2012-03-19 14:02:47 +00003799 new_images=DuplicateImages(_images,1,"-1",_exception);
3800 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003801 new_images=(Image *)NULL;
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 'e':
3807 {
anthonyafa3dfc2012-03-03 11:31:30 +00003808 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003809 {
anthony2a0ec8c2012-03-24 04:35:56 +00003810 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3811 if ( parse < 0 )
3812 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3813 option,arg1);
3814 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3815 _exception);
anthony805a2d42011-09-25 08:25:12 +00003816 break;
3817 }
anthonyebb73a22012-03-22 14:25:52 +00003818 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003819 }
3820 case 'f':
3821 {
anthonyafa3dfc2012-03-03 11:31:30 +00003822 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003823 {
anthony92c93bd2012-03-19 14:02:47 +00003824 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003825 break;
3826 }
anthonyafa3dfc2012-03-03 11:31:30 +00003827 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003828 {
anthony319dac62012-03-06 04:12:44 +00003829 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003830 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003831 break;
3832 }
anthonyafa3dfc2012-03-03 11:31:30 +00003833 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003834 {
anthony92c93bd2012-03-19 14:02:47 +00003835 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003836 break;
3837 }
anthonyebb73a22012-03-22 14:25:52 +00003838 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003839 }
3840 case 'h':
3841 {
anthonyafa3dfc2012-03-03 11:31:30 +00003842 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003843 {
anthony31f1bf72012-01-30 12:37:22 +00003844 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003845 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003846 */
anthony805a2d42011-09-25 08:25:12 +00003847 Image
anthony31f1bf72012-01-30 12:37:22 +00003848 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003849
anthony92c93bd2012-03-19 14:02:47 +00003850 new_images=RemoveFirstImageFromList(&_images);
3851 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003852 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003853 break;
anthony92c93bd2012-03-19 14:02:47 +00003854 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003855 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003856 break;
3857 }
anthonyebb73a22012-03-22 14:25:52 +00003858 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003859 }
3860 case 'i':
3861 {
anthonyafa3dfc2012-03-03 11:31:30 +00003862 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003863 {
3864 Image
anthony805a2d42011-09-25 08:25:12 +00003865 *magnitude_image,
3866 *phase_image;
3867
anthony92c93bd2012-03-19 14:02:47 +00003868 magnitude_image=RemoveFirstImageFromList(&_images);
3869 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003870 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003871 if (phase_image == (Image *) NULL)
3872 break;
3873 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003874 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003875 magnitude_image=DestroyImage(magnitude_image);
3876 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003877 break;
3878 }
anthonyafa3dfc2012-03-03 11:31:30 +00003879 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003880 {
3881 Image
anthony31f1bf72012-01-30 12:37:22 +00003882 *insert_image,
3883 *index_image;
3884
3885 ssize_t
3886 index;
anthony805a2d42011-09-25 08:25:12 +00003887
anthony7bcfe7f2012-03-30 14:01:22 +00003888 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00003889 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003890 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003891 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003892 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003893 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003894 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003895 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003896 PrependImageToList(&_images,insert_image);
3897 else if (index == (ssize_t) GetImageListLength(_images))
3898 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003899 else
anthony43f425d2012-02-26 12:58:58 +00003900 {
anthony92c93bd2012-03-19 14:02:47 +00003901 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003902 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00003903 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00003904 InsertImageInList(&index_image,insert_image);
3905 }
anthony92c93bd2012-03-19 14:02:47 +00003906 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003907 break;
3908 }
anthonyebb73a22012-03-22 14:25:52 +00003909 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003910 }
3911 case 'l':
3912 {
anthonyafa3dfc2012-03-03 11:31:30 +00003913 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003914 {
anthonyfe1aa782012-03-24 13:43:04 +00003915 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3916 if ( parse < 0 )
3917 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3918 option,arg1);
3919 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00003920 {
3921 case CoalesceLayer:
3922 {
anthony92c93bd2012-03-19 14:02:47 +00003923 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003924 break;
3925 }
3926 case CompareAnyLayer:
3927 case CompareClearLayer:
3928 case CompareOverlayLayer:
3929 default:
3930 {
anthonyfe1aa782012-03-24 13:43:04 +00003931 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
3932 _exception);
anthony805a2d42011-09-25 08:25:12 +00003933 break;
3934 }
3935 case MergeLayer:
3936 case FlattenLayer:
3937 case MosaicLayer:
3938 case TrimBoundsLayer:
3939 {
anthonyfe1aa782012-03-24 13:43:04 +00003940 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
3941 _exception);
anthony805a2d42011-09-25 08:25:12 +00003942 break;
3943 }
3944 case DisposeLayer:
3945 {
anthony92c93bd2012-03-19 14:02:47 +00003946 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003947 break;
3948 }
3949 case OptimizeImageLayer:
3950 {
anthony92c93bd2012-03-19 14:02:47 +00003951 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003952 break;
3953 }
3954 case OptimizePlusLayer:
3955 {
anthony92c93bd2012-03-19 14:02:47 +00003956 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003957 break;
3958 }
3959 case OptimizeTransLayer:
3960 {
anthony92c93bd2012-03-19 14:02:47 +00003961 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003962 break;
3963 }
3964 case RemoveDupsLayer:
3965 {
anthony92c93bd2012-03-19 14:02:47 +00003966 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003967 break;
3968 }
3969 case RemoveZeroLayer:
3970 {
anthony92c93bd2012-03-19 14:02:47 +00003971 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003972 break;
3973 }
3974 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003975 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003976 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003977 if (new_images == (Image *) NULL)
3978 break;
anthony92c93bd2012-03-19 14:02:47 +00003979 _images=DestroyImageList(_images);
3980 _images=OptimizeImageLayers(new_images,_exception);
3981 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003982 break;
3983 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00003984 OptimizeImageTransparency(_images,_exception);
3985 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3986 _exception);
anthony805a2d42011-09-25 08:25:12 +00003987 break;
3988 }
3989 case CompositeLayer:
3990 {
anthony805a2d42011-09-25 08:25:12 +00003991 Image
3992 *source;
3993
3994 RectangleInfo
3995 geometry;
3996
anthony31f1bf72012-01-30 12:37:22 +00003997 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003998 compose;
3999
4000 const char*
4001 value;
4002
anthony92c93bd2012-03-19 14:02:47 +00004003 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004004 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004005 if (value != (const char *) NULL)
4006 compose=(CompositeOperator) ParseCommandOption(
4007 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004008
anthony31f1bf72012-01-30 12:37:22 +00004009 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004010 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004011 while (source != (Image *) NULL)
4012 {
4013 source=GetNextImageInList(source);
4014 if ((source != (Image *) NULL) &&
4015 (LocaleCompare(source->magick,"NULL") == 0))
4016 break;
4017 }
4018 if (source != (Image *) NULL)
4019 {
4020 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4021 (GetNextImageInList(source) == (Image *) NULL))
4022 source=(Image *) NULL;
4023 else
anthony31f1bf72012-01-30 12:37:22 +00004024 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004025 source=SplitImageList(source->previous);
4026 DeleteImageFromList(&source);
4027 }
4028 }
4029 if (source == (Image *) NULL)
4030 {
anthony92c93bd2012-03-19 14:02:47 +00004031 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004032 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004033 break;
4034 }
anthony31f1bf72012-01-30 12:37:22 +00004035 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004036 SetGeometry(_images,&geometry);
4037 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004038 geometry.width=source->page.width != 0 ?
4039 source->page.width : source->columns;
4040 geometry.height=source->page.height != 0 ?
4041 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004042 GravityAdjustGeometry(_images->page.width != 0 ?
4043 _images->page.width : _images->columns,
4044 _images->page.height != 0 ? _images->page.height :
4045 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004046
anthony31f1bf72012-01-30 12:37:22 +00004047 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004048 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4049 _exception);
anthony805a2d42011-09-25 08:25:12 +00004050 source=DestroyImageList(source);
4051 break;
4052 }
4053 }
anthony805a2d42011-09-25 08:25:12 +00004054 break;
4055 }
anthonyebb73a22012-03-22 14:25:52 +00004056 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004057 }
4058 case 'm':
4059 {
anthonyafa3dfc2012-03-03 11:31:30 +00004060 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004061 {
anthony464f1c42012-04-22 08:51:01 +00004062 CLIWandWarnReplaced("+remap");
anthony92c93bd2012-03-19 14:02:47 +00004063 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004064 break;
4065 }
anthonyafa3dfc2012-03-03 11:31:30 +00004066 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004067 {
4068 Image
4069 *morph_image;
4070
anthony7bcfe7f2012-03-30 14:01:22 +00004071 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004072 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004073 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4074 _exception);
anthony805a2d42011-09-25 08:25:12 +00004075 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004076 break;
anthony92c93bd2012-03-19 14:02:47 +00004077 _images=DestroyImageList(_images);
4078 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004079 break;
4080 }
anthonyafa3dfc2012-03-03 11:31:30 +00004081 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004082 {
anthony319dac62012-03-06 04:12:44 +00004083 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00004084 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004085 break;
4086 }
anthonyebb73a22012-03-22 14:25:52 +00004087 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004088 }
4089 case 'p':
4090 {
anthonyafa3dfc2012-03-03 11:31:30 +00004091 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004092 {
anthony964d28e2012-05-17 23:39:46 +00004093 (void) FormatLocaleFile(stdout,"%s",arg1);
anthony24aa8822012-03-11 00:56:06 +00004094 break;
anthony805a2d42011-09-25 08:25:12 +00004095 }
anthonyafa3dfc2012-03-03 11:31:30 +00004096 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004097 {
anthonyb1d483a2012-04-14 12:53:56 +00004098 /* FUTURE: better parsing using ScriptToken() from string ??? */
anthony805a2d42011-09-25 08:25:12 +00004099 char
4100 **arguments;
4101
4102 int
4103 j,
4104 number_arguments;
4105
anthony31f1bf72012-01-30 12:37:22 +00004106 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004107 if (arguments == (char **) NULL)
4108 break;
anthony31f1bf72012-01-30 12:37:22 +00004109 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004110 {
4111 char
4112 breaker,
4113 quote,
4114 *token;
4115
4116 const char
4117 *arguments;
4118
4119 int
4120 next,
4121 status;
4122
4123 size_t
4124 length;
4125
4126 TokenInfo
4127 *token_info;
4128
4129 /*
anthony24aa8822012-03-11 00:56:06 +00004130 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004131 */
anthony31f1bf72012-01-30 12:37:22 +00004132 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004133 token=(char *) NULL;
4134 if (~length >= (MaxTextExtent-1))
4135 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4136 sizeof(*token));
4137 if (token == (char *) NULL)
4138 break;
4139 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004140 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004141 token_info=AcquireTokenInfo();
4142 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4143 "\"",'\0',&breaker,&next,&quote);
4144 token_info=DestroyTokenInfo(token_info);
4145 if (status == 0)
4146 {
4147 const char
4148 *argv;
4149
4150 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004151 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4152 _exception);
anthony805a2d42011-09-25 08:25:12 +00004153 }
4154 token=DestroyString(token);
4155 break;
4156 }
4157 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004158 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4159 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004160 for (j=0; j < number_arguments; j++)
4161 arguments[j]=DestroyString(arguments[j]);
4162 arguments=(char **) RelinquishMagickMemory(arguments);
4163 break;
4164 }
anthonyebb73a22012-03-22 14:25:52 +00004165 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004166 }
4167 case 'r':
4168 {
anthonyafa3dfc2012-03-03 11:31:30 +00004169 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004170 {
anthony92c93bd2012-03-19 14:02:47 +00004171 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004172 break;
4173 }
anthonyafa3dfc2012-03-03 11:31:30 +00004174 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004175 {
anthony92c93bd2012-03-19 14:02:47 +00004176 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004177 break;
4178 }
anthonyebb73a22012-03-22 14:25:52 +00004179 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004180 }
4181 case 's':
4182 {
anthonyafa3dfc2012-03-03 11:31:30 +00004183 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004184 {
anthonycd358fc2012-04-16 13:59:03 +00004185 /* FUTURE: this option needs more work to make better */
anthony805a2d42011-09-25 08:25:12 +00004186 ssize_t
4187 offset;
4188
anthony7bcfe7f2012-03-30 14:01:22 +00004189 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004190 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004191 offset=(ssize_t) StringToLong(arg1);
anthonycd358fc2012-04-16 13:59:03 +00004192 new_images=SmushImages(_images,normal_op,offset,_exception);
4193 break;
4194 }
4195 if (LocaleCompare("subimage",option+1) == 0)
4196 {
4197 Image
4198 *base_image,
4199 *compare_image;
4200
4201 const char *
4202 value;
4203
4204 MetricType
4205 metric;
4206
4207 double
4208 similarity;
4209
4210 RectangleInfo
4211 offset;
4212
4213 base_image=GetImageFromList(_images,0);
4214 compare_image=GetImageFromList(_images,1);
4215
4216 /* Comparision Metric */
4217 metric=UndefinedMetric;
4218 value=GetImageOption(_image_info,"metric");
4219 if (value != (const char *) NULL)
4220 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4221 MagickFalse,value);
4222
4223 new_images=SimilarityImage(base_image,compare_image,metric,
4224 &offset,&similarity,_exception);
4225
4226 if ( new_images != (Image *)NULL ) {
4227 char
4228 result[MaxTextExtent];
4229
4230 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
4231 (void) SetImageProperty(new_images,"subimage:similarity",result,
4232 _exception);
4233 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4234 (long) offset.x);
4235 (void) SetImageProperty(new_images,"subimage:x",result,
4236 _exception);
4237 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4238 (long) offset.y);
4239 (void) SetImageProperty(new_images,"subimage:y",result,
4240 _exception);
4241 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
4242 (unsigned long) offset.width,(unsigned long) offset.height,
4243 (long) offset.x,(long) offset.y);
4244 (void) SetImageProperty(new_images,"subimage:offset",result,
4245 _exception);
4246 }
anthony805a2d42011-09-25 08:25:12 +00004247 break;
4248 }
anthony0ea037a2012-04-03 12:14:39 +00004249 if (LocaleCompare("swap",option+1) == 0) {
4250 Image
4251 *p,
4252 *q,
4253 *swap;
anthony805a2d42011-09-25 08:25:12 +00004254
anthony0ea037a2012-04-03 12:14:39 +00004255 ssize_t
4256 index,
4257 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004258
anthony0ea037a2012-04-03 12:14:39 +00004259 index=-1;
4260 swap_index=-2;
4261 if (IfNormalOp) {
4262 GeometryInfo
4263 geometry_info;
4264
4265 MagickStatusType
4266 flags;
4267
4268 swap_index=(-1);
anthony0ea037a2012-04-03 12:14:39 +00004269 flags=ParseGeometry(arg1,&geometry_info);
anthonyb1e21ed2012-04-20 12:43:12 +00004270 if ((flags & RhoValue) != 0)
4271 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004272 index=(ssize_t) geometry_info.rho;
4273 if ((flags & SigmaValue) != 0)
4274 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004275 }
anthony0ea037a2012-04-03 12:14:39 +00004276 p=GetImageFromList(_images,index);
4277 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004278 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4279 if (IfNormalOp)
4280 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4281 else
4282 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4283 }
anthony0ea037a2012-04-03 12:14:39 +00004284 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004285 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004286 swap=CloneImage(p,0,0,MagickTrue,_exception);
4287 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4288 ReplaceImageInList(&q,swap);
4289 _images=GetFirstImageInList(q);
4290 break;
4291 }
anthonyebb73a22012-03-22 14:25:52 +00004292 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004293 }
anthony805a2d42011-09-25 08:25:12 +00004294 default:
anthonyebb73a22012-03-22 14:25:52 +00004295 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004296 }
anthony964d28e2012-05-17 23:39:46 +00004297
4298 /* clean up percent escape interpreted strings */
4299 if (arg1 != arg1n )
4300 arg1=DestroyString((char *)arg1);
4301 if (arg2 != arg2n )
4302 arg2=DestroyString((char *)arg2);
4303
4304 /* if new image list generated, replace existing image list */
anthony31f1bf72012-01-30 12:37:22 +00004305 if (new_images == (Image *) NULL)
4306 return;
anthony964d28e2012-05-17 23:39:46 +00004307 _images=DestroyImageList(_images);
anthony92c93bd2012-03-19 14:02:47 +00004308 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004309 return;
4310
anthony92c93bd2012-03-19 14:02:47 +00004311#undef _image_info
4312#undef _images
4313#undef _exception
4314#undef _draw_info
4315#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004316#undef IfNormalOp
4317#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004318#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004319}
anthony43f425d2012-02-26 12:58:58 +00004320
4321/*
4322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4323% %
4324% %
4325% %
anthony964d28e2012-05-17 23:39:46 +00004326+ 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 +00004327% %
4328% %
4329% %
4330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4331%
anthony464f1c42012-04-22 08:51:01 +00004332% CLINoImageOperator() Applies operations that may not actually need images
anthony964d28e2012-05-17 23:39:46 +00004333% in an image list.
anthony43f425d2012-02-26 12:58:58 +00004334%
anthony4837ac22012-05-18 23:39:48 +00004335% The classic operators of this type is "-read", which actually creates
4336% images even when no images are present. Or image stack operators, which
4337% can be applied (push or pop) to an empty image list.
anthonyafa3dfc2012-03-03 11:31:30 +00004338%
anthony4837ac22012-05-18 23:39:48 +00004339% Note that these operators may involve other special 'option' prefix
4340% characters other than '-' or '+', namely parenthesis and braces.
anthony43f425d2012-02-26 12:58:58 +00004341%
anthony464f1c42012-04-22 08:51:01 +00004342% The format of the CLINoImageOption method is:
anthony43f425d2012-02-26 12:58:58 +00004343%
anthony464f1c42012-04-22 08:51:01 +00004344% void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4345% const char *arg1, const char *arg2)
anthony43f425d2012-02-26 12:58:58 +00004346%
4347% A description of each parameter follows:
4348%
4349% o cli_wand: the main CLI Wand to use.
4350%
4351% o option: The special option (with any switch char) to process
4352%
anthony464f1c42012-04-22 08:51:01 +00004353% o arg1 & arg2: Argument for option, if required
4354% Currently arg2 is not used.
anthony43f425d2012-02-26 12:58:58 +00004355%
4356*/
anthony464f1c42012-04-22 08:51:01 +00004357WandExport void CLINoImageOperator(MagickCLI *cli_wand,
4358 const char *option, const char *arg1, const char *magick_unused(arg2))
anthony43f425d2012-02-26 12:58:58 +00004359{
anthony4837ac22012-05-18 23:39:48 +00004360#if 0
4361 const char /* For percent escape interpretImageProperties() */
4362 *arg1,
4363 *arg2;
4364#endif
4365
anthony8226e722012-04-05 14:25:46 +00004366#define _image_info (cli_wand->wand.image_info)
4367#define _images (cli_wand->wand.images)
4368#define _exception (cli_wand->wand.exception)
4369#define IfNormalOp (*option=='-')
4370#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004371
4372 assert(cli_wand != (MagickCLI *) NULL);
4373 assert(cli_wand->signature == WandSignature);
4374 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +00004375 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00004376 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4377
anthonyde897b72012-04-27 00:16:17 +00004378#if 0
anthony4837ac22012-05-18 23:39:48 +00004379 Not able to be used as their may not be any images!
4380 Also the only option that may have arguments that can be percent escaped is
4381 "-clone".
anthony52bef752012-03-27 13:54:47 +00004382
anthony4837ac22012-05-18 23:39:48 +00004383#define _process_flags (cli_wand->process_flags)
4384#define _option_type ((CommandOptionFlags) cli_wand->command->flags)
4385 /* Interpret Percent Escapes in Arguments - using first image */
4386 arg1 = arg1n;
4387 arg2 = arg2n;
4388 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4389 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4390 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4391 /* Interpret Percent escapes in argument 1 */
4392 if (arg1n != (char *) NULL) {
4393 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4394 if (arg1 == (char *) NULL) {
4395 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4396 arg1=arg1n; /* use the given argument as is */
4397 }
4398 }
4399 if (arg2n != (char *) NULL) {
4400 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4401 if (arg2 == (char *) NULL) {
4402 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4403 arg2=arg2n; /* use the given argument as is */
4404 }
4405 }
4406 }
4407#undef _process_flags
4408#undef _option_type
anthonyde897b72012-04-27 00:16:17 +00004409#endif
anthony4837ac22012-05-18 23:39:48 +00004410
4411 do { /* break to exit code */
4412 /*
4413 No-op options (ignore these)
4414 */
4415 if (LocaleCompare("noop",option+1) == 0) /* no argument */
4416 break;
4417 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4418 break;
4419 if (LocaleCompare("sans0",option+1) == 0) /* no argument */
4420 break;
4421 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4422 break;
4423 /*
4424 Image Reading
4425 */
4426 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4427 ( LocaleCompare("--",option) == 0 ) ) {
4428 /* Do Glob filename Expansion for 'arg1' then read all images.
4429 *
4430 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4431 * (but attaching to the filenames in the generated argument list) any
4432 * [...] read modifiers that may be present.
4433 *
4434 * For example: It will expand '*.gif[20x20]' into a list such as
4435 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4436 *
4437 * NOTE: In IMv6 this was done globally across all images. This
4438 * meant you could include IM options in '@filename' lists, but you
4439 * could not include comments. Doing it only for image read makes
4440 * it far more secure.
4441 *
4442 * Note: arguments do not have percent escapes expanded for security
4443 * reasons.
4444 */
4445 int argc;
4446 char **argv;
4447 ssize_t i;
4448
4449 argc = 1;
4450 argv = (char **) &arg1;
4451
4452 /* Expand 'glob' expressions in the given filename.
4453 Expansion handles any 'coder:' prefix, or read modifiers attached
4454 to the filename, including them in the resulting expanded list.
4455 */
4456 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4457 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4458 option,GetExceptionMessage(errno));
4459
4460 /* loop over expanded filename list, and read then all in */
4461 for (i=0; i<argc; i++) {
4462 Image *
4463 new_images;
4464 if (IfMagickTrue(_image_info->ping))
4465 new_images=PingImages(_image_info,argv[i],_exception);
4466 else
4467 new_images=ReadImages(_image_info,argv[i],_exception);
4468 AppendImageToList(&_images, new_images);
4469 }
4470 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4471 break;
4472 }
4473 /*
4474 Image Writing
4475 Note: Writing a empty image list is valid in specific cases
4476 */
4477 if (LocaleCompare("write",option+1) == 0) {
4478 /* Note: arguments do not have percent escapes expanded */
4479 char
4480 key[MaxTextExtent];
4481
4482 Image
4483 *write_images;
4484
4485 ImageInfo
4486 *write_info;
4487
4488 /* Need images, unless a "null:" output coder is used */
4489 if ( cli_wand->wand.images == (Image *) NULL ) {
4490 if ( LocaleCompare(arg1,"null:") == 0 )
4491 break;
4492 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4493 }
4494
4495 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4496 (void) DeleteImageRegistry(key);
4497 write_images=_images;
4498 if (IfPlusOp)
4499 write_images=CloneImageList(_images,_exception);
4500 write_info=CloneImageInfo(_image_info);
4501 (void) WriteImages(write_info,write_images,arg1,_exception);
4502 write_info=DestroyImageInfo(write_info);
4503 if (IfPlusOp)
4504 write_images=DestroyImageList(write_images);
4505 break;
4506 }
4507 /*
4508 Parenthesis and Brace operations
4509 */
4510 if (LocaleCompare("(",option) == 0) {
4511 /* stack 'push' images */
4512 Stack
4513 *node;
4514
4515 size_t
4516 size;
4517
4518 size=0;
4519 node=cli_wand->image_list_stack;
4520 for ( ; node != (Stack *)NULL; node=node->next)
4521 size++;
4522 if ( size >= MAX_STACK_DEPTH )
4523 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4524 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4525 if (node == (Stack *) NULL)
4526 CLIWandExceptionBreak(ResourceLimitFatalError,
4527 "MemoryAllocationFailed",option);
4528 node->data = (void *)cli_wand->wand.images;
4529 cli_wand->wand.images = NewImageList();
4530 node->next = cli_wand->image_list_stack;
4531 cli_wand->image_list_stack = node;
4532
4533 /* handle respect-parenthesis */
4534 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4535 "respect-parenthesis"))))
4536 option="{"; /* fall-thru so as to push image settings too */
anthony52bef752012-03-27 13:54:47 +00004537 else
anthony4837ac22012-05-18 23:39:48 +00004538 break;
4539 /* fall thru to next if */
anthony52bef752012-03-27 13:54:47 +00004540 }
anthony4837ac22012-05-18 23:39:48 +00004541 if (LocaleCompare("{",option) == 0) {
4542 /* stack 'push' of image_info settings */
4543 Stack
4544 *node;
anthony8226e722012-04-05 14:25:46 +00004545
anthony4837ac22012-05-18 23:39:48 +00004546 size_t
4547 size;
anthony8226e722012-04-05 14:25:46 +00004548
anthony4837ac22012-05-18 23:39:48 +00004549 size=0;
4550 node=cli_wand->image_info_stack;
4551 for ( ; node != (Stack *)NULL; node=node->next)
4552 size++;
4553 if ( size >= MAX_STACK_DEPTH )
4554 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4555 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4556 if (node == (Stack *) NULL)
4557 CLIWandExceptionBreak(ResourceLimitFatalError,
4558 "MemoryAllocationFailed",option);
anthony8226e722012-04-05 14:25:46 +00004559
anthony4837ac22012-05-18 23:39:48 +00004560 node->data = (void *)cli_wand->wand.image_info;
4561 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4562 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4563 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4564 option);
4565 cli_wand->wand.image_info = (ImageInfo *)node->data;
4566 node = (Stack *)RelinquishMagickMemory(node);
4567 break;
4568 }
4569
4570 node->next = cli_wand->image_info_stack;
4571 cli_wand->image_info_stack = node;
4572
4573 break;
anthony8226e722012-04-05 14:25:46 +00004574 }
anthony4837ac22012-05-18 23:39:48 +00004575 if (LocaleCompare(")",option) == 0) {
4576 /* pop images from stack */
4577 Stack
4578 *node;
anthony8226e722012-04-05 14:25:46 +00004579
anthony4837ac22012-05-18 23:39:48 +00004580 node = (Stack *)cli_wand->image_list_stack;
4581 if ( node == (Stack *)NULL)
4582 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4583 cli_wand->image_list_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004584
anthony4837ac22012-05-18 23:39:48 +00004585 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4586 cli_wand->wand.images= (Image *)node->data;
4587 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004588
anthony4837ac22012-05-18 23:39:48 +00004589 /* handle respect-parenthesis - of the previous 'pushed' settings */
4590 node = cli_wand->image_info_stack;
4591 if ( node != (Stack *)NULL)
4592 {
4593 if (IfMagickTrue(IsStringTrue(GetImageOption(
4594 cli_wand->wand.image_info,"respect-parenthesis"))))
4595 option="}"; /* fall-thru so as to pop image settings too */
4596 else
4597 break;
4598 }
4599 else
4600 break;
4601 /* fall thru to next if */
4602 }
4603 if (LocaleCompare("}",option) == 0) {
4604 /* pop image_info settings from stack */
4605 Stack
4606 *node;
anthony43f425d2012-02-26 12:58:58 +00004607
anthony4837ac22012-05-18 23:39:48 +00004608 node = (Stack *)cli_wand->image_info_stack;
4609 if ( node == (Stack *)NULL)
4610 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4611 cli_wand->image_info_stack = node->next;
anthony43f425d2012-02-26 12:58:58 +00004612
anthony4837ac22012-05-18 23:39:48 +00004613 (void) DestroyImageInfo(cli_wand->wand.image_info);
anthony43f425d2012-02-26 12:58:58 +00004614 cli_wand->wand.image_info = (ImageInfo *)node->data;
4615 node = (Stack *)RelinquishMagickMemory(node);
anthony4837ac22012-05-18 23:39:48 +00004616
4617 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4618 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4619 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4620
4621 break;
4622 }
4623 if (LocaleCompare("clone",option+1) == 0) {
4624 Image
4625 *new_images;
4626
4627 if (*option == '+')
4628 arg1="-1";
4629 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4630 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
4631 if ( cli_wand->image_list_stack == (Stack *)NULL)
4632 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4633 new_images = (Image *)cli_wand->image_list_stack->data;
4634 if (new_images == (Image *) NULL)
4635 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4636 new_images=CloneImages(new_images,arg1,_exception);
4637 if (new_images == (Image *) NULL)
4638 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4639 AppendImageToList(&_images,new_images);
4640 break;
4641 }
4642 /*
4643 Informational Operations
4644
4645 Note that these do not require either cli-wand or images!
4646 */
4647 if (LocaleCompare("version",option+1) == 0) {
4648 (void) FormatLocaleFile(stdout,"Version: %s\n",
4649 GetMagickVersion((size_t *) NULL));
4650 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4651 GetMagickCopyright());
4652 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4653 GetMagickFeatures());
4654 break;
4655 }
4656 if (LocaleCompare("list",option+1) == 0) {
4657 /*
4658 FUTURE: This 'switch' should really be built into the MagickCore
4659 */
4660 ssize_t
4661 list;
4662
4663 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4664 if ( list < 0 ) {
4665 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4666 break;
4667 }
4668 switch (list)
4669 {
4670 case MagickCoderOptions:
4671 {
4672 (void) ListCoderInfo((FILE *) NULL,_exception);
4673 break;
4674 }
4675 case MagickColorOptions:
4676 {
4677 (void) ListColorInfo((FILE *) NULL,_exception);
4678 break;
4679 }
4680 case MagickConfigureOptions:
4681 {
4682 (void) ListConfigureInfo((FILE *) NULL,_exception);
4683 break;
4684 }
4685 case MagickDelegateOptions:
4686 {
4687 (void) ListDelegateInfo((FILE *) NULL,_exception);
4688 break;
4689 }
4690 case MagickFontOptions:
4691 {
4692 (void) ListTypeInfo((FILE *) NULL,_exception);
4693 break;
4694 }
4695 case MagickFormatOptions:
4696 (void) ListMagickInfo((FILE *) NULL,_exception);
4697 break;
4698 case MagickLocaleOptions:
4699 (void) ListLocaleInfo((FILE *) NULL,_exception);
4700 break;
4701 case MagickLogOptions:
4702 (void) ListLogInfo((FILE *) NULL,_exception);
4703 break;
4704 case MagickMagicOptions:
4705 (void) ListMagicInfo((FILE *) NULL,_exception);
4706 break;
4707 case MagickMimeOptions:
4708 (void) ListMimeInfo((FILE *) NULL,_exception);
4709 break;
4710 case MagickModuleOptions:
4711 (void) ListModuleInfo((FILE *) NULL,_exception);
4712 break;
4713 case MagickPolicyOptions:
4714 (void) ListPolicyInfo((FILE *) NULL,_exception);
4715 break;
4716 case MagickResourceOptions:
4717 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4718 break;
4719 case MagickThresholdOptions:
4720 (void) ListThresholdMaps((FILE *) NULL,_exception);
4721 break;
4722 default:
4723 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4724 _exception);
4725 break;
4726 }
4727 break;
anthony43f425d2012-02-26 12:58:58 +00004728 }
anthony8226e722012-04-05 14:25:46 +00004729
anthony4837ac22012-05-18 23:39:48 +00004730 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony8226e722012-04-05 14:25:46 +00004731
anthony4837ac22012-05-18 23:39:48 +00004732 } while (0); /* break to exit code. */
anthony43f425d2012-02-26 12:58:58 +00004733
4734#if 0
anthony4837ac22012-05-18 23:39:48 +00004735 /* clean up percent escape interpreted strings */
4736 if (arg1 != arg1n )
4737 arg1=DestroyString((char *)arg1);
4738 if (arg2 != arg2n )
4739 arg2=DestroyString((char *)arg2);
anthony43f425d2012-02-26 12:58:58 +00004740#endif
4741
anthony8226e722012-04-05 14:25:46 +00004742#undef _image_info
4743#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004744#undef _exception
anthony8226e722012-04-05 14:25:46 +00004745#undef IfNormalOp
4746#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004747}
anthony464f1c42012-04-22 08:51:01 +00004748
4749/*
4750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4751% %
4752% %
4753% %
anthony964d28e2012-05-17 23:39:46 +00004754+ C L I O p t i o n %
anthony464f1c42012-04-22 08:51:01 +00004755% %
4756% %
4757% %
4758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4759%
4760% CLIOption() Processes the given option using the given CLI Magick Wand.
anthony964d28e2012-05-17 23:39:46 +00004761% The option arguments can be variable in number, though at this time no more
4762% that two is actually used by any option (this may change). Excess options
4763% are simply ignored.
anthony464f1c42012-04-22 08:51:01 +00004764%
4765% If the cli_wand->command pointer is non-null, then it is assumed that the
4766% option has already been search for up from the CommandOptions[] table in
anthony964d28e2012-05-17 23:39:46 +00004767% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
4768% routine will do the lookup instead. The pointer is reset afterward.
4769%
4770% This action allows the caller to lookup and pre-handle any 'special'
4771% options, (such as implicit reads) before calling this general option
4772% handler to deal with 'standard' command line options.
anthony464f1c42012-04-22 08:51:01 +00004773%
4774% The format of the CLIOption method is:
4775%
4776% void CLIOption(MagickCLI *cli_wand,const char *option, ...)
4777%
4778% A description of each parameter follows:
4779%
4780% o cli_wand: the main CLI Wand to use.
4781%
4782% o option: The special option (with any switch char) to process
4783%
anthony964d28e2012-05-17 23:39:46 +00004784% o args: any required arguments for an option (variable number)
anthony464f1c42012-04-22 08:51:01 +00004785%
4786% Example Usage...
4787%
4788% CLIoption(cli_wand,"-read","rose:");
4789% CLIoption(cli_wand,"-virtual-pixel","transparent");
4790% CLIoption(cli_wand,"-distort","SRT:","30");
4791% CLIoption(cli_wand,"-write","rotated_rose.png");
4792%
4793*/
4794WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
4795{
4796 const char
4797 *arg1,
4798 *arg2;
4799
4800 CommandOptionFlags
4801 option_type;
4802
4803 assert(cli_wand != (MagickCLI *) NULL);
4804 assert(cli_wand->signature == WandSignature);
4805 assert(cli_wand->wand.signature == WandSignature);
4806 if (IfMagickTrue(cli_wand->wand.debug))
4807 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4808
anthony964d28e2012-05-17 23:39:46 +00004809 do { /* Break Code Block for error handling */
4810
4811 /* get information about option */
4812 if ( cli_wand->command == (const OptionInfo *) NULL )
4813 cli_wand->command = GetCommandOptionInfo(option);
anthony464f1c42012-04-22 08:51:01 +00004814#if 0
anthony964d28e2012-05-17 23:39:46 +00004815 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
4816 option, cli_wand->command->mnemonic );
anthony464f1c42012-04-22 08:51:01 +00004817#endif
anthony964d28e2012-05-17 23:39:46 +00004818 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthony464f1c42012-04-22 08:51:01 +00004819
anthony964d28e2012-05-17 23:39:46 +00004820 if ( option_type == UndefinedOptionFlag )
4821 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
anthony464f1c42012-04-22 08:51:01 +00004822
anthony964d28e2012-05-17 23:39:46 +00004823 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
anthony464f1c42012-04-22 08:51:01 +00004824
anthony964d28e2012-05-17 23:39:46 +00004825 /* depreciated options */
4826 if ( (option_type & DeprecateOptionFlag) != 0 )
4827 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
anthony464f1c42012-04-22 08:51:01 +00004828
anthony964d28e2012-05-17 23:39:46 +00004829 /* options that this module does not handle */
4830 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
4831 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
anthony464f1c42012-04-22 08:51:01 +00004832
anthony964d28e2012-05-17 23:39:46 +00004833 /* Get argument strings from VarArgs
4834 How can you determine arguments is enough was supplied? */
4835 { size_t
4836 count = cli_wand->command->type;
anthony464f1c42012-04-22 08:51:01 +00004837
anthony964d28e2012-05-17 23:39:46 +00004838 va_list
4839 operands;
anthony464f1c42012-04-22 08:51:01 +00004840
anthony964d28e2012-05-17 23:39:46 +00004841 va_start(operands,option);
anthony464f1c42012-04-22 08:51:01 +00004842
anthony964d28e2012-05-17 23:39:46 +00004843 arg1=arg2=NULL;
4844 if ( count >= 1 )
4845 arg1=(const char *) va_arg(operands, const char *);
4846 if ( count >= 2 )
4847 arg2=(const char *) va_arg(operands, const char *);
anthony464f1c42012-04-22 08:51:01 +00004848
anthony964d28e2012-05-17 23:39:46 +00004849 va_end(operands);
anthony464f1c42012-04-22 08:51:01 +00004850
anthony52cb3df2012-04-24 03:29:32 +00004851#if 0
anthony964d28e2012-05-17 23:39:46 +00004852 (void) FormatLocaleFile(stderr,
4853 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
4854 option,(long) count,option_type,arg1,arg2);
anthony464f1c42012-04-22 08:51:01 +00004855#endif
anthony964d28e2012-05-17 23:39:46 +00004856 }
4857
4858 /*
4859 Call the appropriate option handler
4860 */
4861
4862 /* FUTURE: this is temporary - get 'settings' to handle distribution of
4863 settings to images attributes,proprieties,artifacts */
4864 if ( cli_wand->wand.images != (Image *)NULL )
4865 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4866 cli_wand->wand.exception);
4867
4868 if ( (option_type & SettingOptionFlags) != 0 ) {
4869 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
4870 // FUTURE: Sync Specific Settings into Image Properities (not global)
4871 }
4872
4873 /* Operators that do not need images - read, write, stack, clone */
4874 if ( (option_type & NoImageOperatorFlag) != 0)
4875 CLINoImageOperator(cli_wand, option, arg1, arg2);
4876
4877 /* FUTURE: The not a setting part below is a temporary hack due to
4878 * some options being both a Setting and a Simple operator.
4879 * Specifically -monitor, -depth, and -colorspace */
4880 if ( cli_wand->wand.images == (Image *)NULL )
4881 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
4882 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
4883 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
4884
4885 /* Operators work on single images, and needs a loop over the images */
4886 if ( (option_type & SimpleOperatorFlag) != 0)
4887 CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
4888
4889 /* Operators that work on the image list as a whole */
4890 if ( (option_type & ListOperatorFlag) != 0 )
4891 CLIListOperatorImages(cli_wand, option, arg1, arg2);
4892
4893 } while (0); /* end Break code block */
anthony464f1c42012-04-22 08:51:01 +00004894
4895 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
anthony464f1c42012-04-22 08:51:01 +00004896}