blob: 7d972ea64d18ad43296705fb28fac7ec798ca48b [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"
anthonyfd706f92012-01-19 04:22:02 +000053#include "MagickWand/operation.h"
anthony2052d272012-02-28 12:48:29 +000054#include "MagickWand/operation-private.h"
anthony43f425d2012-02-26 12:58:58 +000055#include "MagickWand/wand.h"
anthony805a2d42011-09-25 08:25:12 +000056#include "MagickCore/monitor-private.h"
57#include "MagickCore/thread-private.h"
58#include "MagickCore/string-private.h"
59
60/*
61 Define declarations.
62*/
anthonyafa3dfc2012-03-03 11:31:30 +000063#define USE_WAND_METHODS 0
64#define MAX_STACK_DEPTH 32
65#define UNDEFINED_COMPRESSION_QUALITY 0UL
66
anthony805a2d42011-09-25 08:25:12 +000067/*
68 Constant declaration. (temporary exports)
69*/
70static const char
71 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000072 BorderColor[] = "#dfdfdf", /* sRGB gray */
73 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony805a2d42011-09-25 08:25:12 +000074
75/*
76** Function to report on the progress of image operations
77*/
78static MagickBooleanType MonitorProgress(const char *text,
79 const MagickOffsetType offset,const MagickSizeType extent,
anthony43f425d2012-02-26 12:58:58 +000080 void *wand_unused(cli_wandent_data))
anthony805a2d42011-09-25 08:25:12 +000081{
82 char
83 message[MaxTextExtent],
84 tag[MaxTextExtent];
85
86 const char
87 *locale_message;
88
89 register char
90 *p;
91
92 if (extent < 2)
93 return(MagickTrue);
94 (void) CopyMagickMemory(tag,text,MaxTextExtent);
95 p=strrchr(tag,'/');
96 if (p != (char *) NULL)
97 *p='\0';
98 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
99 locale_message=GetLocaleMessage(message);
100 if (locale_message == message)
101 locale_message=tag;
102 if (p == (char *) NULL)
103 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
104 locale_message,(long) offset,(unsigned long) extent,(long)
105 (100L*offset/(extent-1)));
106 else
107 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
108 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
109 (100L*offset/(extent-1)));
110 if (offset == (MagickOffsetType) (extent-1))
111 (void) FormatLocaleFile(stderr,"\n");
112 (void) fflush(stderr);
113 return(MagickTrue);
114}
115
116/*
117** GetImageCache() will read an image into a image cache if not already
118** present then return the image that is in the cache under that filename.
119*/
120static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
121 ExceptionInfo *exception)
122{
123 char
124 key[MaxTextExtent];
125
126 ExceptionInfo
127 *sans_exception;
128
129 Image
130 *image;
131
132 ImageInfo
133 *read_info;
134
135 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
136 sans_exception=AcquireExceptionInfo();
137 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
138 sans_exception=DestroyExceptionInfo(sans_exception);
139 if (image != (Image *) NULL)
140 return(image);
141 read_info=CloneImageInfo(image_info);
142 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
143 image=ReadImage(read_info,exception);
144 read_info=DestroyImageInfo(read_info);
145 if (image != (Image *) NULL)
146 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
147 return(image);
148}
149
150/*
anthonya89dd172011-10-04 13:29:35 +0000151 SparseColorOption() parse the complex -sparse-color argument into an
152 an array of floating point values than call SparseColorImage().
153 Argument is a complex mix of floating-point pixel coodinates, and color
154 specifications (or direct floating point numbers). The number of floats
155 needed to represent a color varies depending on teh current channel
156 setting.
anthony43f425d2012-02-26 12:58:58 +0000157
158 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000159*/
160static Image *SparseColorOption(const Image *image,
161 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000162 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000163{
164 char
165 token[MaxTextExtent];
166
167 const char
168 *p;
169
170 double
171 *sparse_arguments;
172
173 Image
174 *sparse_image;
175
176 PixelInfo
177 color;
178
179 MagickBooleanType
180 error;
181
182 register size_t
183 x;
184
185 size_t
186 number_arguments,
187 number_colors;
188
189 assert(image != (Image *) NULL);
190 assert(image->signature == MagickSignature);
191 if (image->debug != MagickFalse)
192 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
193 assert(exception != (ExceptionInfo *) NULL);
194 assert(exception->signature == MagickSignature);
195 /*
196 Limit channels according to image - and add up number of color channel.
197 */
198 number_colors=0;
199 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
200 number_colors++;
201 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
202 number_colors++;
203 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
204 number_colors++;
205 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
206 (image->colorspace == CMYKColorspace))
207 number_colors++;
208 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
209 (image->matte != MagickFalse))
210 number_colors++;
211
212 /*
213 Read string, to determine number of arguments needed,
214 */
215 p=arguments;
216 x=0;
217 while( *p != '\0' )
218 {
219 GetMagickToken(p,&p,token);
220 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000221 if ( isalpha((int) token[0]) || token[0] == '#' )
222 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000223 else
anthony805a2d42011-09-25 08:25:12 +0000224 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000225 }
226 error=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +0000227 /* control points and color values */
228 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
229 number_arguments=x;
anthony805a2d42011-09-25 08:25:12 +0000230 if ( error ) {
231 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000232 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000233 "Invalid number of Arguments");
234 return( (Image *)NULL);
235 }
236
237 /* Allocate and fill in the floating point arguments */
238 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
239 sizeof(*sparse_arguments));
240 if (sparse_arguments == (double *) NULL) {
241 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
242 "MemoryAllocationFailed","%s","SparseColorOption");
243 return( (Image *)NULL);
244 }
245 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
246 sizeof(*sparse_arguments));
247 p=arguments;
248 x=0;
249 while( *p != '\0' && x < number_arguments ) {
250 /* X coordinate */
251 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
252 if ( token[0] == '\0' ) break;
253 if ( isalpha((int) token[0]) || token[0] == '#' ) {
254 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000255 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000256 "Color found, instead of X-coord");
257 error = MagickTrue;
258 break;
259 }
cristydbdd0e32011-11-04 23:29:40 +0000260 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000261 /* Y coordinate */
262 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
263 if ( token[0] == '\0' ) break;
264 if ( isalpha((int) token[0]) || token[0] == '#' ) {
265 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000266 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000267 "Color found, instead of Y-coord");
268 error = MagickTrue;
269 break;
270 }
cristydbdd0e32011-11-04 23:29:40 +0000271 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000272 /* color name or function given in string argument */
273 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
274 if ( token[0] == '\0' ) break;
275 if ( isalpha((int) token[0]) || token[0] == '#' ) {
276 /* Color string given */
277 (void) QueryColorCompliance(token,AllCompliance,&color,
278 exception);
279 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
280 sparse_arguments[x++] = QuantumScale*color.red;
281 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
282 sparse_arguments[x++] = QuantumScale*color.green;
283 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
284 sparse_arguments[x++] = QuantumScale*color.blue;
285 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
286 (image->colorspace == CMYKColorspace))
287 sparse_arguments[x++] = QuantumScale*color.black;
288 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
289 (image->matte != MagickFalse))
290 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000291 }
anthony31f1bf72012-01-30 12:37:22 +0000292 else {
293 /* Colors given as a set of floating point values - experimental */
294 /* NB: token contains the first floating point value to use! */
295 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
296 {
297 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
298 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
299 break;
300 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
301 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000302 }
anthony31f1bf72012-01-30 12:37:22 +0000303 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
304 {
305 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
306 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
307 break;
308 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
309 token[0] = ','; /* used this token - get another */
310 }
311 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
312 {
313 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
314 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
315 break;
316 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
317 token[0] = ','; /* used this token - get another */
318 }
319 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
320 (image->colorspace == CMYKColorspace))
321 {
322 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324 break;
325 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
326 token[0] = ','; /* used this token - get another */
327 }
328 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
329 (image->matte != MagickFalse))
330 {
331 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
332 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
333 break;
334 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
335 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000336 }
337 }
338 }
339 if ( number_arguments != x && !error ) {
340 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000341 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000342 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
343 return( (Image *)NULL);
344 }
345 if ( error )
346 return( (Image *)NULL);
347
anthony31f1bf72012-01-30 12:37:22 +0000348 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000349 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
350 exception);
351 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
352 return( sparse_image );
353}
354
355/*
356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357% %
358% %
359% %
anthony43f425d2012-02-26 12:58:58 +0000360+ A c q u i r e W a n d C L I %
anthony805a2d42011-09-25 08:25:12 +0000361% %
362% %
363% %
364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365%
anthony43f425d2012-02-26 12:58:58 +0000366% AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
367% Wand). The given image_info and exception is included as is if provided.
anthony805a2d42011-09-25 08:25:12 +0000368%
anthony43f425d2012-02-26 12:58:58 +0000369% Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
370% needed.
371%
372% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000373%
anthony43f425d2012-02-26 12:58:58 +0000374% MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
375% ExceptionInfo *exception)
376%
377*/
378WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
379 ExceptionInfo *exception)
380{
381 MagickCLI
382 *cli_wand;
383
384 /* precaution - as per NewMagickWand() */
385 {
386 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
387 const char *quantum = GetMagickQuantumDepth(&depth);
388 if (depth != MAGICKCORE_QUANTUM_DEPTH)
389 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
390 }
391
392 /* allocate memory for MgaickCLI */
393 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
394 if (cli_wand == (MagickCLI *) NULL)
395 {
396 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
397 GetExceptionMessage(errno));
398 return((MagickCLI *)NULL);
399 }
400
401 /* Initialize Wand Part of MagickCLI
402 FUTURE: this is a repeat of code from NewMagickWand()
403 However some parts may be given fro man external source!
404 */
405 cli_wand->wand.id=AcquireWandId();
406 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
407 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
408 cli_wand->wand.images=NewImageList();
409 if ( image_info == (ImageInfo *)NULL)
410 cli_wand->wand.image_info=AcquireImageInfo();
411 else
412 cli_wand->wand.image_info=image_info;
413 if ( exception == (ExceptionInfo *)NULL)
414 cli_wand->wand.exception=AcquireExceptionInfo();
415 else
416 cli_wand->wand.exception=exception;
417 cli_wand->wand.debug=IsEventLogging();
418 cli_wand->wand.signature=WandSignature;
419
420 /* Initialize CLI Part of MagickCLI */
421 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
422 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
423 cli_wand->image_list_stack=(Stack *)NULL;
424 cli_wand->image_info_stack=(Stack *)NULL;
anthony5330ae02012-03-20 14:17:01 +0000425 cli_wand->location="'%s'"; /* option location not known by default */
426 cli_wand->location2="'%s' '%s'";
anthony319dac62012-03-06 04:12:44 +0000427 cli_wand->filename=cli_wand->wand.name;
anthony1cdc5b72012-03-03 02:31:18 +0000428 cli_wand->line=0;
429 cli_wand->column=0;
anthony43f425d2012-02-26 12:58:58 +0000430 cli_wand->signature=WandSignature;
431
432 if (cli_wand->wand.debug != MagickFalse)
433 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
434 return(cli_wand);
435}
436
437/*
438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439% %
440% %
441% %
442+ D e s t r o y W a n d C L I %
443% %
444% %
445% %
446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447%
448% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
449% and any exceptions, if still present in the wand.
450%
451% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000452%
anthony43f425d2012-02-26 12:58:58 +0000453% MagickWand *DestroyMagickCLI()
454% Exception *exception)
455%
456*/
457WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
458{
459 Stack
460 *node;
461
462 assert(cli_wand != (MagickCLI *) NULL);
463 assert(cli_wand->signature == WandSignature);
464 assert(cli_wand->wand.signature == WandSignature);
465 if (cli_wand->wand.debug != MagickFalse)
466 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
467
468 /* Destroy CLI part of MagickCLI */
469 if (cli_wand->draw_info != (DrawInfo *) NULL )
470 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
471 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
472 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
473 while(cli_wand->image_list_stack != (Stack *)NULL)
474 {
475 node=cli_wand->image_list_stack;
476 cli_wand->image_list_stack=node->next;
477 (void) DestroyImageList((Image *)node->data);
478 (void) RelinquishMagickMemory(node);
479 }
480 while(cli_wand->image_info_stack != (Stack *)NULL)
481 {
482 node=cli_wand->image_info_stack;
483 cli_wand->image_info_stack=node->next;
484 (void) DestroyImageInfo((ImageInfo *)node->data);
485 (void) RelinquishMagickMemory(node);
486 }
487 cli_wand->signature=(~WandSignature);
488
489 /* Destroy Wand part MagickCLI */
490 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
491 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
492 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
493 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
494 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
495 RelinquishWandId(cli_wand->wand.id);
496 cli_wand->wand.signature=(~WandSignature);
497
498 return((MagickCLI *)NULL);
499}
500
501/*
502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
503% %
504% %
505% %
anthony2052d272012-02-28 12:48:29 +0000506+ C L I C a t c h E x c e p t i o n %
507% %
508% %
509% %
510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511%
512% CLICatchException() will report exceptions, either just non-fatal warnings
513% only, or all errors, according to 'all_execeptions' boolean argument.
514%
515% The function returns true is errors are fatal, in which case the caller
516% should abort and re-call with an 'all_exceptions' argument of true before
517% quitting.
518%
519% The cut-off level between fatal and non-fatal may be controlled by options
520% (FUTURE), but defaults to 'Error' exceptions.
521%
522% The format of the CLICatchException method is:
523%
524% MagickBooleanType CLICatchException(MagickCLI *cli_wand,
525% const MagickBooleanType all_exceptions );
526%
527*/
528WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
529 const MagickBooleanType all_exceptions )
530{
531 MagickBooleanType
532 status;
533 assert(cli_wand != (MagickCLI *) NULL);
534 assert(cli_wand->signature == WandSignature);
535 assert(cli_wand->wand.signature == WandSignature);
536 if (cli_wand->wand.debug != MagickFalse)
537 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
538
539 // FUTURE: '-regard_warning' should make this more sensitive.
540 // Note pipelined options may like more control over this level
541
542 status = MagickFalse;
543 if (cli_wand->wand.exception->severity > ErrorException)
544 status = MagickTrue;
545
546 if ( status == MagickFalse || all_exceptions != MagickFalse )
547 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
548
549 return(status);
550}
551
552/*
553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554% %
555% %
556% %
anthony43f425d2012-02-26 12:58:58 +0000557+ C L I S e t t i n g O p t i o n I n f o %
558% %
559% %
560% %
561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562%
563% CLISettingOptionInfo() applies a single settings option into a CLI wand
564% holding the image_info, draw_info, quantize_info structures that will be
565% used when processing the images.
566%
567% These options do no require images to be present in the CLI wand for them
568% to be able to be set, in which case they will generally be applied to image
569% that are read in later
anthony80c37752012-01-16 01:03:11 +0000570%
571% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000572% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000573%
anthony2052d272012-02-28 12:48:29 +0000574% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000575%
anthonyafa3dfc2012-03-03 11:31:30 +0000576% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000577% const char *option, const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000578%
579% A description of each parameter follows:
580%
anthony43f425d2012-02-26 12:58:58 +0000581% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000582%
anthonydcf510d2011-10-30 13:51:40 +0000583% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000584%
anthony24aa8822012-03-11 00:56:06 +0000585% o arg1: The single argument used to set this option.
anthonydcf510d2011-10-30 13:51:40 +0000586%
anthony72feaa62012-01-17 06:46:23 +0000587% Example usage...
588%
anthonyafa3dfc2012-03-03 11:31:30 +0000589% CLISettingOptionInfo(cli_wand, "-background", "Red"); // set value
590% CLISettingOptionInfo(cli_wand, "-adjoin", NULL); // set boolean
591% CLISettingOptionInfo(cli_wand, "+adjoin", NULL); // unset
anthony72feaa62012-01-17 06:46:23 +0000592%
anthony24aa8822012-03-11 00:56:06 +0000593% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +0000594%
595% argc,argv
596% i=index in argv
597%
anthony2052d272012-02-28 12:48:29 +0000598% option_info = GetCommandOptionInfo(argv[i]);
599% count=option_info->type;
600% option_type=option_info->flags;
601%
602% if ( (option_type & SettingOperatorOptionFlags) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +0000603% CLISettingOptionInfo(cli_wand, argv[i],
604% (count>0) ? argv[i+1] : (char *)NULL);
anthonydcf510d2011-10-30 13:51:40 +0000605% i += count+1;
606%
anthony805a2d42011-09-25 08:25:12 +0000607*/
anthonyafa3dfc2012-03-03 11:31:30 +0000608WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000609 const char *option,const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000610{
anthony30b912a2012-03-22 01:20:28 +0000611 ssize_t
612 parse; /* option argument parsing (string to value table lookup) */
613
anthony43f425d2012-02-26 12:58:58 +0000614 assert(cli_wand != (MagickCLI *) NULL);
615 assert(cli_wand->signature == WandSignature);
616 assert(cli_wand->wand.signature == WandSignature);
617 if (cli_wand->wand.debug != MagickFalse)
618 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000619
anthony92c93bd2012-03-19 14:02:47 +0000620#define _image_info (cli_wand->wand.image_info)
621#define _exception (cli_wand->wand.exception)
622#define _draw_info (cli_wand->draw_info)
623#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000624#define IfSetOption (*option=='-')
625#define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
626#define ArgBooleanNot (IfSetOption?MagickFalse:MagickTrue)
627#define ArgBooleanString (IfSetOption?"true":"false")
628#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000629
anthonyafa3dfc2012-03-03 11:31:30 +0000630 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000631 {
632 case 'a':
633 {
anthonyafa3dfc2012-03-03 11:31:30 +0000634 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000635 {
anthony92c93bd2012-03-19 14:02:47 +0000636 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000637 break;
638 }
anthonyafa3dfc2012-03-03 11:31:30 +0000639 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000640 {
anthony92c93bd2012-03-19 14:02:47 +0000641 /* DEPRECIATED: _draw_info setting only: for -draw and -transform */
anthony74b1cfc2011-10-06 12:44:16 +0000642 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000643 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000644 else
anthony92c93bd2012-03-19 14:02:47 +0000645 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000646 break;
647 }
anthonyafa3dfc2012-03-03 11:31:30 +0000648 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000649 {
anthony92c93bd2012-03-19 14:02:47 +0000650 _image_info->antialias =
651 _draw_info->stroke_antialias =
652 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000653 break;
654 }
anthony31f1bf72012-01-30 12:37:22 +0000655 if (LocaleCompare("attenuate",option+1) == 0)
656 {
anthony92c93bd2012-03-19 14:02:47 +0000657 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
658 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
659 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000660 break;
661 }
anthonyafa3dfc2012-03-03 11:31:30 +0000662 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000663 {
anthony92c93bd2012-03-19 14:02:47 +0000664 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000665 break;
666 }
anthonyebb73a22012-03-22 14:25:52 +0000667 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000668 }
669 case 'b':
670 {
anthonyafa3dfc2012-03-03 11:31:30 +0000671 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000672 {
anthony92c93bd2012-03-19 14:02:47 +0000673 /* FUTURE: both _image_info attribute & ImageOption in use!
674 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000675 SyncImageSettings() used to set per-image attribute.
676
anthony92c93bd2012-03-19 14:02:47 +0000677 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000678 we should fall back to per-image background_color
679
680 At this time -background will 'wipe out' the per-image
681 background color!
682
683 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000684 */
anthony92c93bd2012-03-19 14:02:47 +0000685 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000686 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000687 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000688 break;
689 }
anthonyafa3dfc2012-03-03 11:31:30 +0000690 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000691 {
anthony52bef752012-03-27 13:54:47 +0000692 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000693 as it is actually rarely used except in direct convolve operations
694 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000695
696 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000697 */
anthony5330ae02012-03-20 14:17:01 +0000698 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
699 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000700 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000701 break;
702 }
anthonyafa3dfc2012-03-03 11:31:30 +0000703 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000704 {
anthony72feaa62012-01-17 06:46:23 +0000705 /* Used as a image chromaticity setting
706 SyncImageSettings() used to set per-image attribute.
707 */
anthony92c93bd2012-03-19 14:02:47 +0000708 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000709 break;
710 }
anthonyafa3dfc2012-03-03 11:31:30 +0000711 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000712 {
anthonyafbaed72011-10-26 12:05:04 +0000713 /* Image chromaticity X,Y NB: Y=X if Y not defined
714 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000715 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000716 */
anthonyf42014d2012-03-25 09:53:06 +0000717 arg1=ArgOption("0.0");
718 if (IsGeometry(arg1) == MagickFalse)
anthony5330ae02012-03-20 14:17:01 +0000719 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000720 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000721 break;
722 }
anthonyafa3dfc2012-03-03 11:31:30 +0000723 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000724 {
anthony92c93bd2012-03-19 14:02:47 +0000725 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000726 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000727 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000728 */
anthony74b1cfc2011-10-06 12:44:16 +0000729 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000730 {
anthony92c93bd2012-03-19 14:02:47 +0000731 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000732 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000733 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000734 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000735 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000736 break;
737 }
anthony92c93bd2012-03-19 14:02:47 +0000738 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000739 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000740 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000741 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000742 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000743 break;
744 }
anthonyafa3dfc2012-03-03 11:31:30 +0000745 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000746 {
anthonyfd706f92012-01-19 04:22:02 +0000747 /* DEPRECIATED - now "undercolor" */
anthony24aa8822012-03-11 00:56:06 +0000748 CLISettingOptionInfo(cli_wand,"undercolor",arg1);
anthonyfd706f92012-01-19 04:22:02 +0000749 break;
anthony805a2d42011-09-25 08:25:12 +0000750 }
anthonyebb73a22012-03-22 14:25:52 +0000751 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000752 }
753 case 'c':
754 {
anthonyafa3dfc2012-03-03 11:31:30 +0000755 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000756 {
757 MagickSizeType
758 limit;
759
anthony5330ae02012-03-20 14:17:01 +0000760 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
761 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000762 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000763 if (LocaleCompare("unlimited",arg1) != 0)
764 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000765 (void) SetMagickResourceLimit(MemoryResource,limit);
766 (void) SetMagickResourceLimit(MapResource,2*limit);
767 break;
768 }
anthonyafa3dfc2012-03-03 11:31:30 +0000769 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000770 {
anthony92c93bd2012-03-19 14:02:47 +0000771 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000772 break;
773 }
anthonyafa3dfc2012-03-03 11:31:30 +0000774 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000775 {
anthony30b912a2012-03-22 01:20:28 +0000776 arg1=ArgOption("default");
777 parse=ParseChannelOption(arg1);
778 if (parse < 0)
779 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
780 option,arg1);
781 _image_info->channel=(ChannelType) parse;
782 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000783 break;
784 }
anthonyafa3dfc2012-03-03 11:31:30 +0000785 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000786 {
anthonyafbaed72011-10-26 12:05:04 +0000787 /* Setting used for new images via AquireImage()
788 But also used as a SimpleImageOperator
789 Undefined colorspace means don't modify images on
790 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000791 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
792 ArgOption("undefined"));
793 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000794 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
795 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000796 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000797 break;
798 }
anthonyafa3dfc2012-03-03 11:31:30 +0000799 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000800 {
anthony92c93bd2012-03-19 14:02:47 +0000801 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000802 break;
803 }
anthonyafa3dfc2012-03-03 11:31:30 +0000804 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000805 {
anthony92c93bd2012-03-19 14:02:47 +0000806 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000807 SyncImageSettings() used to set per-image attribute. - REMOVE
808
anthonyafbaed72011-10-26 12:05:04 +0000809 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000810 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000811 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000812 */
anthonyebb73a22012-03-22 14:25:52 +0000813 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
814 ArgOption("undefined"));
815 if (parse < 0)
816 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
817 option,arg1);
818 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000819 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000820 break;
821 }
anthonyafa3dfc2012-03-03 11:31:30 +0000822 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000823 {
anthony92c93bd2012-03-19 14:02:47 +0000824 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000825 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000826 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000827
anthony92c93bd2012-03-19 14:02:47 +0000828 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000829 however the image attribute (for save) is set from the
830 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000831
832 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000833 */
anthonyebb73a22012-03-22 14:25:52 +0000834 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
835 ArgOption("undefined"));
836 if (parse < 0)
837 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
838 option,arg1);
839 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000840 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000841 break;
842 }
anthonyebb73a22012-03-22 14:25:52 +0000843 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000844 }
845 case 'd':
846 {
anthonyafa3dfc2012-03-03 11:31:30 +0000847 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000848 {
anthony72feaa62012-01-17 06:46:23 +0000849 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000850 arg1=ArgOption("none");
851 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
852 if (parse < 0)
853 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
854 option,arg1);
855 (void) SetLogEventMask(arg1);
856 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000857 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000858 break;
859 }
anthonyafa3dfc2012-03-03 11:31:30 +0000860 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000861 {
anthony24aa8822012-03-11 00:56:06 +0000862 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000863 {
anthony5f867ae2011-10-09 10:28:34 +0000864 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000865 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000866 else
anthony24aa8822012-03-11 00:56:06 +0000867 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000868 break;
869 }
anthony24aa8822012-03-11 00:56:06 +0000870 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000871 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000872 (void) DefineImageOption(_image_info,arg1);
anthonyebb73a22012-03-22 14:25:52 +0000873 else if ( DeleteImageOption(_image_info,arg1) == MagickFalse )
874 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000875 break;
876 }
anthonyafa3dfc2012-03-03 11:31:30 +0000877 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000878 {
anthonyafbaed72011-10-26 12:05:04 +0000879 /* Only used for new images via AcquireImage()
880 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000881 */
anthonyebb73a22012-03-22 14:25:52 +0000882 arg1=ArgOption("0");
883 if (IsGeometry(arg1) == MagickFalse)
884 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
885 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000886 break;
887 }
anthonyafa3dfc2012-03-03 11:31:30 +0000888 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000889 {
anthony92c93bd2012-03-19 14:02:47 +0000890 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000891 Basically as density can be in a XxY form!
892
893 SyncImageSettings() used to set per-image attribute.
894 */
anthonyebb73a22012-03-22 14:25:52 +0000895 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
896 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000897 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
898 (void) CloneString(&_image_info->density,ArgOption(NULL));
899 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000900 break;
901 }
anthonyafa3dfc2012-03-03 11:31:30 +0000902 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000903 {
anthony72feaa62012-01-17 06:46:23 +0000904 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
905 SyncImageSettings() used to set per-image attribute.
906 */
anthonyebb73a22012-03-22 14:25:52 +0000907 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
908 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000909 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000910 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000911 break;
912 }
anthonyafa3dfc2012-03-03 11:31:30 +0000913 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000914 {
anthony92c93bd2012-03-19 14:02:47 +0000915 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000916 arg1=ArgOption("undefined");
917 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
918 if (parse < 0)
919 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
920 option,arg1);
921 _draw_info->direction=(DirectionType) parse;
922 (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("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000926 {
anthony92c93bd2012-03-19 14:02:47 +0000927 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
928 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000929 break;
930 }
anthonyafa3dfc2012-03-03 11:31:30 +0000931 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000932 {
anthony72feaa62012-01-17 06:46:23 +0000933 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000934 arg1=ArgOption("undefined");
935 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
936 if (parse < 0)
937 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
938 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000939 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000940 break;
941 }
anthonyafa3dfc2012-03-03 11:31:30 +0000942 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000943 {
anthony92c93bd2012-03-19 14:02:47 +0000944 /* _image_info attr (on/off), _quantize_info attr (on/off)
945 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000946 FUTURE: merge the duality of the dithering options
947 */
anthony92c93bd2012-03-19 14:02:47 +0000948 _image_info->dither = _quantize_info->dither = ArgBoolean;
949 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
950 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000951 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000952 if (_quantize_info->dither_method == NoDitherMethod)
953 _image_info->dither = _quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000954 break;
955 }
anthonyebb73a22012-03-22 14:25:52 +0000956 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000957 }
958 case 'e':
959 {
anthonyafa3dfc2012-03-03 11:31:30 +0000960 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000961 {
anthony92c93bd2012-03-19 14:02:47 +0000962 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
963 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000964 break;
965 }
anthonyafa3dfc2012-03-03 11:31:30 +0000966 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000967 {
anthony92c93bd2012-03-19 14:02:47 +0000968 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000969 arg1 = ArgOption("undefined");
970 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
971 if (parse < 0)
972 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
973 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000974 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000975 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000976 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000977 break;
978 }
anthonyafa3dfc2012-03-03 11:31:30 +0000979 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000980 {
anthony92c93bd2012-03-19 14:02:47 +0000981 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000982 break;
983 }
anthonyebb73a22012-03-22 14:25:52 +0000984 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000985 }
986 case 'f':
987 {
anthonyafa3dfc2012-03-03 11:31:30 +0000988 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000989 {
anthony92c93bd2012-03-19 14:02:47 +0000990 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000991 break;
992 }
anthonyafa3dfc2012-03-03 11:31:30 +0000993 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000994 {
anthony92c93bd2012-03-19 14:02:47 +0000995 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000996 The original fill color is preserved if a fill-pattern is given.
997 That way it does not effect other operations that directly using
998 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000999 */
anthony72feaa62012-01-17 06:46:23 +00001000 MagickBooleanType
1001 status;
anthony6dc09cd2011-10-12 08:56:49 +00001002
1003 ExceptionInfo
1004 *sans;
1005
anthonyfd706f92012-01-19 04:22:02 +00001006 PixelInfo
1007 color;
1008
anthony2a0ec8c2012-03-24 04:35:56 +00001009 arg1 = ArgOption("none"); /* +fill turns it off! */
1010 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001011 if (_draw_info->fill_pattern != (Image *) NULL)
1012 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +00001013
1014 /* is it a color or a image? -- ignore exceptions */
1015 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001016 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +00001017 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001018
anthony6dc09cd2011-10-12 08:56:49 +00001019 if (status == MagickFalse)
anthony2a0ec8c2012-03-24 04:35:56 +00001020 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001021 else
anthony92c93bd2012-03-19 14:02:47 +00001022 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +00001023 break;
1024 }
anthonyafa3dfc2012-03-03 11:31:30 +00001025 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001026 {
anthony72feaa62012-01-17 06:46:23 +00001027 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +00001028 arg1 = ArgOption("undefined");
1029 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
1030 if (parse < 0)
1031 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
1032 option,arg1);
1033 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001034 break;
1035 }
anthonyafa3dfc2012-03-03 11:31:30 +00001036 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001037 {
anthony92c93bd2012-03-19 14:02:47 +00001038 (void) CloneString(&_draw_info->font,ArgOption(NULL));
1039 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +00001040 break;
1041 }
anthonyafa3dfc2012-03-03 11:31:30 +00001042 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001043 {
anthonydcf510d2011-10-30 13:51:40 +00001044 /* FUTURE: why the ping test, you could set ping after this! */
1045 /*
anthony805a2d42011-09-25 08:25:12 +00001046 register const char
1047 *q;
1048
anthony24aa8822012-03-11 00:56:06 +00001049 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +00001050 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00001051 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +00001052 */
anthony92c93bd2012-03-19 14:02:47 +00001053 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001054 break;
1055 }
anthonyafa3dfc2012-03-03 11:31:30 +00001056 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001057 {
anthony72feaa62012-01-17 06:46:23 +00001058 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +00001059 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +00001060 SyncImageSettings() used to set per-image attribute.
1061
anthony2a0ec8c2012-03-24 04:35:56 +00001062 FUTURE: Can't find anything else using _image_info->fuzz directly!
1063 remove direct sttribute from image_info
anthony6613bf32011-10-15 07:24:44 +00001064 */
anthony2a0ec8c2012-03-24 04:35:56 +00001065 arg1=ArgOption("0");
1066 if (IsGeometry(arg1) == MagickFalse)
1067 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1068 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +00001069 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00001070 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001071 break;
1072 }
anthonyebb73a22012-03-22 14:25:52 +00001073 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001074 }
1075 case 'g':
1076 {
anthonyafa3dfc2012-03-03 11:31:30 +00001077 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001078 {
anthony72feaa62012-01-17 06:46:23 +00001079 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001080 arg1 = ArgOption("none");
1081 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
1082 if (parse < 0)
1083 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
1084 option,arg1);
1085 (void) SetImageOption(_image_info,option+1,arg1);
1086 _draw_info->gravity=(GravityType) parse;
anthony805a2d42011-09-25 08:25:12 +00001087 break;
1088 }
anthonyafa3dfc2012-03-03 11:31:30 +00001089 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001090 {
anthonydcf510d2011-10-30 13:51:40 +00001091 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +00001092 SyncImageSettings() used to set per-image attribute.
1093 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +00001094 */
anthonyf42014d2012-03-25 09:53:06 +00001095 arg1=ArgOption("0.0");
1096 if (IsGeometry(arg1) == MagickFalse)
anthonyfe1aa782012-03-24 13:43:04 +00001097 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001098 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001099 break;
1100 }
anthonyebb73a22012-03-22 14:25:52 +00001101 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001102 }
1103 case 'i':
1104 {
anthonyafa3dfc2012-03-03 11:31:30 +00001105 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001106 {
anthony72feaa62012-01-17 06:46:23 +00001107 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +00001108 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +00001109 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001110 */
anthonyfe1aa782012-03-24 13:43:04 +00001111 arg1 = ArgOption("indefined");
1112 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
1113 if (parse < 0)
1114 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
1115 option,arg1);
1116 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001117 break;
1118 }
anthonyafa3dfc2012-03-03 11:31:30 +00001119 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001120 {
anthony92c93bd2012-03-19 14:02:47 +00001121 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +00001122 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001123 */
anthonyfe1aa782012-03-24 13:43:04 +00001124 arg1 = ArgOption("undefined");
1125 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
1126 if (parse < 0)
1127 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
1128 option,arg1);
1129 _image_info->interlace=(InterlaceType) parse;
1130 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001131 break;
1132 }
anthonyafa3dfc2012-03-03 11:31:30 +00001133 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001134 {
anthonyfe1aa782012-03-24 13:43:04 +00001135 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1136 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001137 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1138 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001139 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001140 break;
1141 }
anthonyafa3dfc2012-03-03 11:31:30 +00001142 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001143 {
anthonyfd706f92012-01-19 04:22:02 +00001144 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001145 arg1 = ArgOption("undefined");
1146 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1147 if (parse < 0)
1148 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1149 option,arg1);
1150 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001151 break;
1152 }
anthonyafa3dfc2012-03-03 11:31:30 +00001153 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001154 {
anthonyfe1aa782012-03-24 13:43:04 +00001155 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1156 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001157 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1158 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001159 break;
1160 }
anthonyebb73a22012-03-22 14:25:52 +00001161 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001162 }
1163 case 'k':
1164 {
anthonyafa3dfc2012-03-03 11:31:30 +00001165 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001166 {
anthonyfe1aa782012-03-24 13:43:04 +00001167 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1168 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001169 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1170 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001171 break;
1172 }
anthonyebb73a22012-03-22 14:25:52 +00001173 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001174 }
1175 case 'l':
1176 {
anthonyafa3dfc2012-03-03 11:31:30 +00001177 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001178 {
anthony72feaa62012-01-17 06:46:23 +00001179 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001180 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001181 break;
1182 }
anthonyafa3dfc2012-03-03 11:31:30 +00001183 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001184 {
anthonyfe1aa782012-03-24 13:43:04 +00001185 if (IfSetOption) {
1186 if ((strchr(arg1,'%') == (char *) NULL))
1187 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001188 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001189 }
anthony805a2d42011-09-25 08:25:12 +00001190 break;
1191 }
anthonyafa3dfc2012-03-03 11:31:30 +00001192 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001193 {
anthony72feaa62012-01-17 06:46:23 +00001194 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001195 arg1=ArgOption("0");
1196 if (IsGeometry(arg1) == MagickFalse)
1197 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1198 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001199 break;
1200 }
anthonyebb73a22012-03-22 14:25:52 +00001201 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001202 }
1203 case 'm':
1204 {
anthonyafa3dfc2012-03-03 11:31:30 +00001205 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001206 {
anthony72feaa62012-01-17 06:46:23 +00001207 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001208 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001209 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001210 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001211 break;
1212 }
anthonyafa3dfc2012-03-03 11:31:30 +00001213 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001214 {
anthony92c93bd2012-03-19 14:02:47 +00001215 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001216 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001217 break;
1218 }
anthonyafa3dfc2012-03-03 11:31:30 +00001219 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001220 {
anthony24aa8822012-03-11 00:56:06 +00001221 /* Setting (used by some input coders!) -- why?
1222 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001223 */
anthony92c93bd2012-03-19 14:02:47 +00001224 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001225 break;
1226 }
anthonyebb73a22012-03-22 14:25:52 +00001227 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001228 }
1229 case 'o':
1230 {
anthonyafa3dfc2012-03-03 11:31:30 +00001231 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001232 {
anthony72feaa62012-01-17 06:46:23 +00001233 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001234 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001235 FUTURE: make set meta-data operator instead.
1236 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001237 */
anthony7bc87992012-03-25 02:32:51 +00001238 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1239 ArgOption("undefined"));
1240 if (parse < 0)
1241 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1242 option,arg1);
1243 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001244 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001245 break;
1246 }
anthonyebb73a22012-03-22 14:25:52 +00001247 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001248 }
1249 case 'p':
1250 {
anthonyafa3dfc2012-03-03 11:31:30 +00001251 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001252 {
anthony7bc87992012-03-25 02:32:51 +00001253 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001254 SyncImageSettings() used to set per-image attribute. ?????
1255 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001256 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001257 */
anthony805a2d42011-09-25 08:25:12 +00001258 char
1259 *canonical_page,
1260 page[MaxTextExtent];
1261
1262 const char
1263 *image_option;
1264
1265 MagickStatusType
1266 flags;
1267
1268 RectangleInfo
1269 geometry;
1270
anthonydcf510d2011-10-30 13:51:40 +00001271 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001272 {
anthony92c93bd2012-03-19 14:02:47 +00001273 (void) DeleteImageOption(_image_info,option+1);
1274 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001275 break;
1276 }
1277 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001278 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001279 if (image_option != (const char *) NULL)
1280 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001281 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001282 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1283 canonical_page=DestroyString(canonical_page);
1284 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1285 (unsigned long) geometry.width,(unsigned long) geometry.height);
1286 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1287 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1288 (unsigned long) geometry.width,(unsigned long) geometry.height,
1289 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001290 (void) SetImageOption(_image_info,option+1,page);
1291 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001292 break;
1293 }
anthonyafa3dfc2012-03-03 11:31:30 +00001294 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001295 {
anthony92c93bd2012-03-19 14:02:47 +00001296 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001297 break;
1298 }
anthonyafa3dfc2012-03-03 11:31:30 +00001299 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001300 {
anthonyf42014d2012-03-25 09:53:06 +00001301 if (IfSetOption) {
1302 if (IsGeometry(arg1) == MagickFalse)
1303 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1304 _image_info->pointsize =
1305 _draw_info->pointsize =
1306 StringToDouble(arg1,(char **) NULL);
1307 }
1308 else {
1309 _image_info->pointsize=0.0; /* unset pointsize */
1310 _draw_info->pointsize=12.0;
1311 }
anthony805a2d42011-09-25 08:25:12 +00001312 break;
1313 }
anthonyafa3dfc2012-03-03 11:31:30 +00001314 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001315 {
anthonyf42014d2012-03-25 09:53:06 +00001316 arg1=ArgOption("-1");
1317 if (IsGeometry(arg1) == MagickFalse)
1318 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1319 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001320 break;
1321 }
anthonydcf510d2011-10-30 13:51:40 +00001322 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001323 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001324 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001325 {
anthony92c93bd2012-03-19 14:02:47 +00001326 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001327 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001328 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001329 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001330 break;
1331 }
anthonydcf510d2011-10-30 13:51:40 +00001332 */
anthonyebb73a22012-03-22 14:25:52 +00001333 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001334 }
1335 case 'q':
1336 {
anthonyafa3dfc2012-03-03 11:31:30 +00001337 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001338 {
anthony7bc87992012-03-25 02:32:51 +00001339 if (IsGeometry(arg1) == MagickFalse)
1340 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001341 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1342 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001343 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001344 break;
1345 }
anthonyafa3dfc2012-03-03 11:31:30 +00001346 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001347 {
anthony92c93bd2012-03-19 14:02:47 +00001348 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001349 arg1=ArgOption("undefined");
1350 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1351 if (parse < 0)
1352 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1353 option,arg1);
1354 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001355 break;
1356 }
anthonyafa3dfc2012-03-03 11:31:30 +00001357 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001358 {
anthonyf42014d2012-03-25 09:53:06 +00001359 /* FUTURE: if two -quiet is performed you can not do +quiet!
1360 This needs to be checked over thoughly.
1361 */
anthony805a2d42011-09-25 08:25:12 +00001362 static WarningHandler
1363 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001364
anthonyafbaed72011-10-26 12:05:04 +00001365 WarningHandler
1366 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001367
anthonyafbaed72011-10-26 12:05:04 +00001368 if ( tmp != (WarningHandler) NULL)
1369 warning_handler = tmp; /* remember the old handler */
1370 if (!IfSetOption) /* set the old handler */
1371 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001372 break;
1373 }
anthonyebb73a22012-03-22 14:25:52 +00001374 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001375 }
1376 case 'r':
1377 {
anthonyafa3dfc2012-03-03 11:31:30 +00001378 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001379 {
anthonydcf510d2011-10-30 13:51:40 +00001380 /* Image chromaticity X,Y NB: Y=X if Y not defined
1381 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001382 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001383 */
anthonyf42014d2012-03-25 09:53:06 +00001384 arg1=ArgOption("0.0");
1385 if (IsGeometry(arg1) == MagickFalse)
anthonyfe1aa782012-03-24 13:43:04 +00001386 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001387 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001388 break;
1389 }
anthonyafa3dfc2012-03-03 11:31:30 +00001390 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001391 {
anthony92c93bd2012-03-19 14:02:47 +00001392 /* _draw_info only setting */
1393 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001394 break;
1395 }
anthonyebb73a22012-03-22 14:25:52 +00001396 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001397 }
1398 case 's':
1399 {
anthonyafa3dfc2012-03-03 11:31:30 +00001400 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001401 {
anthonyafbaed72011-10-26 12:05:04 +00001402 /* FUTURE: should be converted to jpeg:sampling_factor */
anthonyf42014d2012-03-25 09:53:06 +00001403 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1404 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001405 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001406 break;
1407 }
anthonyafa3dfc2012-03-03 11:31:30 +00001408 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001409 {
anthonyf42014d2012-03-25 09:53:06 +00001410 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001411 What ??? Why ????
1412 */
anthonyf42014d2012-03-25 09:53:06 +00001413 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1414 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001415 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1416 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001417 break;
1418 }
anthonyafa3dfc2012-03-03 11:31:30 +00001419 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001420 {
anthonyf42014d2012-03-25 09:53:06 +00001421 if (IsGeometry(arg1) == MagickFalse)
1422 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafbaed72011-10-26 12:05:04 +00001423 SeedPseudoRandomGenerator(
anthony24aa8822012-03-11 00:56:06 +00001424 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001425 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001426 break;
1427 }
anthonyafa3dfc2012-03-03 11:31:30 +00001428 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001429 {
anthony92c93bd2012-03-19 14:02:47 +00001430 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001431 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001432 */
anthony92c93bd2012-03-19 14:02:47 +00001433 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001434 break;
1435 }
anthonyafa3dfc2012-03-03 11:31:30 +00001436 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001437 {
anthonyf42014d2012-03-25 09:53:06 +00001438 arg1=ArgOption("undefined");
1439 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1440 if (parse < 0)
1441 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1442 option,arg1);
1443 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001444 break;
1445 }
anthonyafa3dfc2012-03-03 11:31:30 +00001446 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001447 {
anthonyafbaed72011-10-26 12:05:04 +00001448 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001449 UPDATE: ensure stroke color is not destroyed is a pattern
1450 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001451 */
anthony72feaa62012-01-17 06:46:23 +00001452 MagickBooleanType
1453 status;
anthonyafbaed72011-10-26 12:05:04 +00001454
1455 ExceptionInfo
1456 *sans;
1457
anthonyfd706f92012-01-19 04:22:02 +00001458 PixelInfo
1459 color;
1460
anthony2a0ec8c2012-03-24 04:35:56 +00001461 arg1 = ArgOption("none"); /* +fill turns it off! */
1462 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001463 if (_draw_info->stroke_pattern != (Image *) NULL)
1464 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001465
1466 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001467 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001468 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001469 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001470
anthonyafbaed72011-10-26 12:05:04 +00001471 if (status == MagickFalse)
anthony2a0ec8c2012-03-24 04:35:56 +00001472 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001473 else
anthony92c93bd2012-03-19 14:02:47 +00001474 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001475 break;
1476 }
anthonyafa3dfc2012-03-03 11:31:30 +00001477 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001478 {
anthonyf42014d2012-03-25 09:53:06 +00001479 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1480 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001481 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1482 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001483 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001484 break;
1485 }
anthonyafa3dfc2012-03-03 11:31:30 +00001486 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001487 {
anthonyf42014d2012-03-25 09:53:06 +00001488 arg1=ArgOption("undefined");
1489 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1490 if (parse < 0)
1491 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1492 option,arg1);
1493 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001494 break;
1495 }
anthonyafa3dfc2012-03-03 11:31:30 +00001496 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001497 {
anthonyf42014d2012-03-25 09:53:06 +00001498 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001499 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001500 break;
1501 }
anthonyebb73a22012-03-22 14:25:52 +00001502 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001503 }
1504 case 't':
1505 {
anthonyafa3dfc2012-03-03 11:31:30 +00001506 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001507 {
anthony72feaa62012-01-17 06:46:23 +00001508 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001509 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001510 break;
1511 }
anthonyafa3dfc2012-03-03 11:31:30 +00001512 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001513 {
anthony52bef752012-03-27 13:54:47 +00001514 /* FUTURE: move _image_info string to option splay-tree
1515 Other than "montage" what uses "texture" ????
1516 */
anthony92c93bd2012-03-19 14:02:47 +00001517 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001518 break;
1519 }
anthonyafa3dfc2012-03-03 11:31:30 +00001520 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001521 {
anthony92c93bd2012-03-19 14:02:47 +00001522 _draw_info->fill_pattern=IfSetOption
1523 ?GetImageCache(_image_info,arg1,_exception)
1524 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001525 break;
1526 }
anthonyafa3dfc2012-03-03 11:31:30 +00001527 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001528 {
anthony72feaa62012-01-17 06:46:23 +00001529 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001530 arg1=ArgOption("0");
1531 if (IsGeometry(arg1) == MagickFalse)
1532 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1533 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001534 break;
1535 }
anthonyafa3dfc2012-03-03 11:31:30 +00001536 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001537 {
anthony92c93bd2012-03-19 14:02:47 +00001538 /* FUTURE: both _image_info attribute & ImageOption in use!
1539 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001540 SyncImageSettings() used to set per-image attribute.
1541
anthonyafbaed72011-10-26 12:05:04 +00001542 Note that +transparent-color, means fall-back to image
1543 attribute so ImageOption is deleted, not set to a default.
1544 */
anthony52bef752012-03-27 13:54:47 +00001545 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1546 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001547 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001548 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001549 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001550 break;
1551 }
anthonyafa3dfc2012-03-03 11:31:30 +00001552 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001553 {
anthony92c93bd2012-03-19 14:02:47 +00001554 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1555 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001556 break;
1557 }
anthonyafa3dfc2012-03-03 11:31:30 +00001558 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001559 {
anthony72feaa62012-01-17 06:46:23 +00001560 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001561 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1562 ArgOption("undefined"));
1563 if (parse < 0)
1564 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1565 option,arg1);
1566 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001567 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001568 break;
1569 }
anthonyebb73a22012-03-22 14:25:52 +00001570 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001571 }
1572 case 'u':
1573 {
anthonyafa3dfc2012-03-03 11:31:30 +00001574 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001575 {
anthony92c93bd2012-03-19 14:02:47 +00001576 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001577 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001578 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001579 break;
1580 }
anthonyafa3dfc2012-03-03 11:31:30 +00001581 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001582 {
anthony72feaa62012-01-17 06:46:23 +00001583 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001584 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001585 FUTURE: this probably should be part of the density setting
1586 */
anthony52bef752012-03-27 13:54:47 +00001587 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1588 ArgOption("undefined"));
1589 if (parse < 0)
1590 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1591 option,arg1);
1592 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001593 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001594 break;
1595 }
anthonyebb73a22012-03-22 14:25:52 +00001596 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001597 }
1598 case 'v':
1599 {
anthonyafa3dfc2012-03-03 11:31:30 +00001600 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001601 {
anthony24aa8822012-03-11 00:56:06 +00001602 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001603 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001604 */
anthony92c93bd2012-03-19 14:02:47 +00001605 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1606 _image_info->verbose= ArgBoolean;
1607 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001608 break;
1609 }
anthonyafa3dfc2012-03-03 11:31:30 +00001610 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001611 {
anthony92c93bd2012-03-19 14:02:47 +00001612 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001613 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001614 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001615 */
anthony92c93bd2012-03-19 14:02:47 +00001616 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001617 break;
1618 }
anthonyafa3dfc2012-03-03 11:31:30 +00001619 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001620 {
anthonyfd706f92012-01-19 04:22:02 +00001621 /* SyncImageSettings() used to set per-image attribute.
1622 This is VERY deep in the image caching structure.
1623 */
anthony52bef752012-03-27 13:54:47 +00001624 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1625 ArgOption("undefined"));
1626 if (parse < 0)
1627 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1628 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001629 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001630 break;
1631 }
anthonyebb73a22012-03-22 14:25:52 +00001632 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001633 }
1634 case 'w':
1635 {
anthonyafa3dfc2012-03-03 11:31:30 +00001636 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001637 {
anthony72feaa62012-01-17 06:46:23 +00001638 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001639 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001640 */
anthony52bef752012-03-27 13:54:47 +00001641 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001642 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001643 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001644 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001645 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001646 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001647 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001648 if (_draw_info->weight <= 800)
1649 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001650 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001651 if (_draw_info->weight >= 100)
1652 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001653 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001654 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001655 break;
1656 }
anthonyafa3dfc2012-03-03 11:31:30 +00001657 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001658 {
anthony72feaa62012-01-17 06:46:23 +00001659 /* Used as a image chromaticity setting
1660 SyncImageSettings() used to set per-image attribute.
1661 */
anthony52bef752012-03-27 13:54:47 +00001662 arg1=ArgOption("0.0");
1663 if (IsGeometry(arg1) == MagickFalse)
1664 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1665 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001666 break;
1667 }
anthonyebb73a22012-03-22 14:25:52 +00001668 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001669 }
1670 default:
anthonyebb73a22012-03-22 14:25:52 +00001671 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001672 }
anthony24aa8822012-03-11 00:56:06 +00001673
anthony92c93bd2012-03-19 14:02:47 +00001674#undef _image_info
1675#undef _exception
1676#undef _draw_info
1677#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001678#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001679#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001680#undef ArgBooleanNot
1681#undef ArgBooleanString
1682#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001683
anthony31f1bf72012-01-30 12:37:22 +00001684 return;
anthony805a2d42011-09-25 08:25:12 +00001685}
1686
1687/*
1688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1689% %
1690% %
1691% %
anthony43f425d2012-02-26 12:58:58 +00001692+ 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 +00001693% %
1694% %
1695% %
1696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1697%
anthony31f1bf72012-01-30 12:37:22 +00001698% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001699% the images in the CLI wand, with the settings that was previously saved in
1700% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001701%
1702% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001703% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001704%
anthonyd1447672012-01-19 05:33:53 +00001705% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001706%
anthony43f425d2012-02-26 12:58:58 +00001707% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001708% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001709%
1710% A description of each parameter follows:
1711%
anthony43f425d2012-02-26 12:58:58 +00001712% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001713%
anthonyfd706f92012-01-19 04:22:02 +00001714% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001715%
anthonyfd706f92012-01-19 04:22:02 +00001716% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001717%
anthony31f1bf72012-01-30 12:37:22 +00001718% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001719%
anthony31f1bf72012-01-30 12:37:22 +00001720% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001721%
anthonyafa3dfc2012-03-03 11:31:30 +00001722% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1723% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1724% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001725%
anthony24aa8822012-03-11 00:56:06 +00001726% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001727%
anthony43f425d2012-02-26 12:58:58 +00001728% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001729% argc,argv
1730% i=index in argv
1731%
anthony2052d272012-02-28 12:48:29 +00001732% option_info = GetCommandOptionInfo(argv[i]);
1733% count=option_info->type;
1734% option_type=option_info->flags;
1735%
1736% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001737% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001738% count>=1 ? argv[i+1] : (char *)NULL,
1739% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001740% i += count+1;
1741%
anthony805a2d42011-09-25 08:25:12 +00001742*/
anthony31f1bf72012-01-30 12:37:22 +00001743
1744/*
1745 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001746 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001747
1748 The image in the list may be modified in three different ways...
1749 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1750 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1751 * one image replace by a list of images (-separate and -crop only!)
1752
anthonyafa3dfc2012-03-03 11:31:30 +00001753 In each case the result replaces the single original image in the list, as
1754 well as the pointer to the modified image (last image added if replaced by a
1755 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001756
1757 As the image pointed to may be replaced, the first image in the list may
1758 also change. GetFirstImageInList() should be used by caller if they wish
1759 return the Image pointer to the first image in list.
1760*/
anthony43f425d2012-02-26 12:58:58 +00001761static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001762 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001763{
1764 Image *
1765 new_image;
1766
anthony805a2d42011-09-25 08:25:12 +00001767 GeometryInfo
1768 geometry_info;
1769
1770 RectangleInfo
1771 geometry;
1772
1773 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001774 flags;
1775
anthony92c93bd2012-03-19 14:02:47 +00001776 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001777 parse;
anthony92c93bd2012-03-19 14:02:47 +00001778
1779#define _image_info (cli_wand->wand.image_info)
1780#define _image (cli_wand->wand.images)
1781#define _exception (cli_wand->wand.exception)
1782#define _draw_info (cli_wand->draw_info)
1783#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001784#define IfNormalOp (*option=='-')
1785#define IfPlusOp (*option!='-')
1786#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1787#define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001788
anthony43f425d2012-02-26 12:58:58 +00001789 assert(cli_wand != (MagickCLI *) NULL);
1790 assert(cli_wand->signature == WandSignature);
1791 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001792 assert(_image != (Image *) NULL); /* an image must be present */
anthony43f425d2012-02-26 12:58:58 +00001793 if (cli_wand->wand.debug != MagickFalse)
1794 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001795
anthony92c93bd2012-03-19 14:02:47 +00001796 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001797
anthony805a2d42011-09-25 08:25:12 +00001798 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001799
anthony5330ae02012-03-20 14:17:01 +00001800 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001801
anthonyfd706f92012-01-19 04:22:02 +00001802 /* FUTURE: We may need somthing a little more optimized than this!
1803 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1804 */
anthonyafa3dfc2012-03-03 11:31:30 +00001805 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001806 {
1807 case 'a':
1808 {
anthonyafa3dfc2012-03-03 11:31:30 +00001809 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001810 {
anthony92c93bd2012-03-19 14:02:47 +00001811 if (IsGeometry(arg1) == MagickFalse)
1812 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001813 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001814 if ((flags & SigmaValue) == 0)
1815 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001816 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001817 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001818 break;
1819 }
anthonyafa3dfc2012-03-03 11:31:30 +00001820 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001821 {
anthonyfe1aa782012-03-24 13:43:04 +00001822 /* FUTURE: Roll into a resize special operator */
anthony92c93bd2012-03-19 14:02:47 +00001823 if (IsGeometry(arg1) == MagickFalse)
1824 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1825 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1826 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001827 _exception);
anthony805a2d42011-09-25 08:25:12 +00001828 break;
1829 }
anthonyafa3dfc2012-03-03 11:31:30 +00001830 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001831 {
anthony92c93bd2012-03-19 14:02:47 +00001832 if (IsGeometry(arg1) == MagickFalse)
1833 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001834 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001835 if ((flags & SigmaValue) == 0)
1836 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001837 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001838 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001839 break;
1840 }
anthonyafa3dfc2012-03-03 11:31:30 +00001841 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001842 {
anthony2a0ec8c2012-03-24 04:35:56 +00001843 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1844 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001845 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1846 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001847 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1848 _exception);
anthony805a2d42011-09-25 08:25:12 +00001849 break;
1850 }
anthonyafa3dfc2012-03-03 11:31:30 +00001851 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001852 {
1853 char
1854 *text,
1855 geometry[MaxTextExtent];
1856
anthony92c93bd2012-03-19 14:02:47 +00001857 if (IsGeometry(arg1) == MagickFalse)
1858 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001859 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001860 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001861 if ((flags & SigmaValue) == 0)
1862 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001863 text=InterpretImageProperties(_image_info,_image,arg2,
1864 _exception);
anthony805a2d42011-09-25 08:25:12 +00001865 if (text == (char *) NULL)
1866 break;
anthony92c93bd2012-03-19 14:02:47 +00001867 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001868 text=DestroyString(text);
1869 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1870 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001871 (void) CloneString(&_draw_info->geometry,geometry);
1872 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001873 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001874 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001875 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001876 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001877 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001878 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001879 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001880 (void) AnnotateImage(_image,_draw_info,_exception);
1881 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001882 break;
1883 }
anthonyafa3dfc2012-03-03 11:31:30 +00001884 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001885 {
anthony92c93bd2012-03-19 14:02:47 +00001886 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001887 break;
1888 }
anthonyafa3dfc2012-03-03 11:31:30 +00001889 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001890 {
anthony92c93bd2012-03-19 14:02:47 +00001891 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001892 break;
1893 }
anthonyafa3dfc2012-03-03 11:31:30 +00001894 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001895 {
anthony5330ae02012-03-20 14:17:01 +00001896 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001897 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001898 {
1899 case TopRightOrientation:
1900 {
anthony92c93bd2012-03-19 14:02:47 +00001901 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001902 break;
1903 }
1904 case BottomRightOrientation:
1905 {
anthony92c93bd2012-03-19 14:02:47 +00001906 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001907 break;
1908 }
1909 case BottomLeftOrientation:
1910 {
anthony92c93bd2012-03-19 14:02:47 +00001911 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001912 break;
1913 }
1914 case LeftTopOrientation:
1915 {
anthony92c93bd2012-03-19 14:02:47 +00001916 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001917 break;
1918 }
1919 case RightTopOrientation:
1920 {
anthony92c93bd2012-03-19 14:02:47 +00001921 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001922 break;
1923 }
1924 case RightBottomOrientation:
1925 {
anthony92c93bd2012-03-19 14:02:47 +00001926 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001927 break;
1928 }
1929 case LeftBottomOrientation:
1930 {
anthony92c93bd2012-03-19 14:02:47 +00001931 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001932 break;
1933 }
1934 default:
1935 break;
1936 }
1937 if (new_image != (Image *) NULL)
1938 new_image->orientation=TopLeftOrientation;
1939 break;
1940 }
anthonyebb73a22012-03-22 14:25:52 +00001941 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001942 }
1943 case 'b':
1944 {
anthonyafa3dfc2012-03-03 11:31:30 +00001945 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001946 {
anthony5330ae02012-03-20 14:17:01 +00001947 if (IsGeometry(arg1) == MagickFalse)
1948 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001949 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001950 break;
1951 }
anthonyafa3dfc2012-03-03 11:31:30 +00001952 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001953 {
anthony805a2d42011-09-25 08:25:12 +00001954 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001955 if (IfNormalOp) {
1956 if (IsGeometry(arg1) == MagickFalse)
1957 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001958 flags=ParseGeometry(arg1,&geometry_info);
anthony5330ae02012-03-20 14:17:01 +00001959 }
anthony92c93bd2012-03-19 14:02:47 +00001960 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001961 break;
1962 }
anthonyafa3dfc2012-03-03 11:31:30 +00001963 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001964 {
anthony5330ae02012-03-20 14:17:01 +00001965 if (IsGeometry(arg1) == MagickFalse)
1966 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001967 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001968 if ((flags & SigmaValue) == 0)
1969 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001970 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1971 _exception);
anthony805a2d42011-09-25 08:25:12 +00001972 break;
1973 }
anthonyafa3dfc2012-03-03 11:31:30 +00001974 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001975 {
anthony31f1bf72012-01-30 12:37:22 +00001976 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001977 compose;
1978
1979 const char*
anthony5f867ae2011-10-09 10:28:34 +00001980 value;
1981
anthony5330ae02012-03-20 14:17:01 +00001982 if (IsGeometry(arg1) == MagickFalse)
1983 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1984
anthony92c93bd2012-03-19 14:02:47 +00001985 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001986 if (value != (const char *) NULL)
1987 compose=(CompositeOperator) ParseCommandOption(
1988 MagickComposeOptions,MagickFalse,value);
1989 else
anthony92c93bd2012-03-19 14:02:47 +00001990 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001991
anthony92c93bd2012-03-19 14:02:47 +00001992 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001993 if ((flags & SigmaValue) == 0)
1994 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001995 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001996 break;
1997 }
anthonyafa3dfc2012-03-03 11:31:30 +00001998 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001999 {
2000 double
2001 brightness,
2002 contrast;
2003
2004 GeometryInfo
2005 geometry_info;
2006
2007 MagickStatusType
2008 flags;
2009
anthony5330ae02012-03-20 14:17:01 +00002010 if (IsGeometry(arg1) == MagickFalse)
2011 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002012 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002013 brightness=geometry_info.rho;
2014 contrast=0.0;
2015 if ((flags & SigmaValue) != 0)
2016 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00002017 (void) BrightnessContrastImage(_image,brightness,contrast,
2018 _exception);
anthony805a2d42011-09-25 08:25:12 +00002019 break;
2020 }
anthonyebb73a22012-03-22 14:25:52 +00002021 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002022 }
2023 case 'c':
2024 {
anthonyafa3dfc2012-03-03 11:31:30 +00002025 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002026 {
2027 char
2028 *color_correction_collection;
2029
2030 /*
2031 Color correct with a color decision list.
2032 */
anthony92c93bd2012-03-19 14:02:47 +00002033 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002034 if (color_correction_collection == (char *) NULL)
2035 break;
anthony92c93bd2012-03-19 14:02:47 +00002036 (void) ColorDecisionListImage(_image,color_correction_collection,
2037 _exception);
anthony805a2d42011-09-25 08:25:12 +00002038 break;
2039 }
anthonyafa3dfc2012-03-03 11:31:30 +00002040 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002041 {
anthony5330ae02012-03-20 14:17:01 +00002042 if (IsGeometry(arg1) == MagickFalse)
2043 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002044 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002045 if ((flags & SigmaValue) == 0)
2046 geometry_info.sigma=1.0;
2047 if ((flags & XiValue) == 0)
2048 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002049 new_image=CharcoalImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002050 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002051 break;
2052 }
anthonyafa3dfc2012-03-03 11:31:30 +00002053 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002054 {
anthony5330ae02012-03-20 14:17:01 +00002055 if (IsGeometry(arg1) == MagickFalse)
2056 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002057 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
2058 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002059 break;
2060 }
anthonyafa3dfc2012-03-03 11:31:30 +00002061 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002062 {
anthony92c93bd2012-03-19 14:02:47 +00002063 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002064 break;
2065 }
anthonyafa3dfc2012-03-03 11:31:30 +00002066 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002067 {
anthonyafa3dfc2012-03-03 11:31:30 +00002068 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002069 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00002070 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002071 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002072 break;
2073 }
anthonyafa3dfc2012-03-03 11:31:30 +00002074 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002075 {
2076 CacheView
2077 *mask_view;
2078
2079 Image
2080 *mask_image;
2081
2082 register Quantum
2083 *restrict q;
2084
2085 register ssize_t
2086 x;
2087
2088 ssize_t
2089 y;
2090
anthonyafa3dfc2012-03-03 11:31:30 +00002091 if (IfPlusOp) {
2092 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002093 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002094 break;
2095 }
anthony92c93bd2012-03-19 14:02:47 +00002096 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002097 if (mask_image == (Image *) NULL)
2098 break;
anthony92c93bd2012-03-19 14:02:47 +00002099 if (SetImageStorageClass(mask_image,DirectClass,_exception)
anthonyfd706f92012-01-19 04:22:02 +00002100 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00002101 break;
anthony5330ae02012-03-20 14:17:01 +00002102 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002103 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00002104 mask_view=AcquireCacheView(mask_image);
2105 for (y=0; y < (ssize_t) mask_image->rows; y++)
2106 {
2107 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002108 _exception);
anthony805a2d42011-09-25 08:25:12 +00002109 if (q == (Quantum *) NULL)
2110 break;
2111 for (x=0; x < (ssize_t) mask_image->columns; x++)
2112 {
2113 if (mask_image->matte == MagickFalse)
2114 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2115 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2116 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2117 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2118 q+=GetPixelChannels(mask_image);
2119 }
anthony92c93bd2012-03-19 14:02:47 +00002120 if (SyncCacheViewAuthenticPixels(mask_view,_exception) == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002121 break;
2122 }
anthonyfd706f92012-01-19 04:22:02 +00002123 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002124 mask_view=DestroyCacheView(mask_view);
2125 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002126 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002127 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002128 break;
2129 }
anthonyafa3dfc2012-03-03 11:31:30 +00002130 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002131 {
anthony92c93bd2012-03-19 14:02:47 +00002132 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002133 break;
2134 }
anthonyafa3dfc2012-03-03 11:31:30 +00002135 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002136 {
anthony5330ae02012-03-20 14:17:01 +00002137 if (IsGeometry(arg1) == MagickFalse)
2138 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002139 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002140 break;
2141 }
anthonyafa3dfc2012-03-03 11:31:30 +00002142 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002143 {
2144 KernelInfo
2145 *kernel;
2146
anthonyfd706f92012-01-19 04:22:02 +00002147 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002148 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002149 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002150 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002151 kernel=DestroyKernelInfo(kernel);
2152 break;
2153 }
anthonyafa3dfc2012-03-03 11:31:30 +00002154 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002155 {
anthony5330ae02012-03-20 14:17:01 +00002156 /* Reduce the number of colors in the image.
2157 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002158 */
anthony92c93bd2012-03-19 14:02:47 +00002159 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2160 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002161 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002162 if ((_image->storage_class == DirectClass) ||
2163 _image->colors > _quantize_info->number_colors)
2164 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002165 else
anthony92c93bd2012-03-19 14:02:47 +00002166 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002167 break;
2168 }
anthonyafa3dfc2012-03-03 11:31:30 +00002169 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002170 {
anthony5330ae02012-03-20 14:17:01 +00002171 /* WARNING: this is both a image_info setting (already done)
2172 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002173
2174 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002175 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002176
anthonyd2cdc862011-10-07 14:07:17 +00002177 Note that +colorspace sets "undefined" or no effect on
2178 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002179 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002180 */
anthony92c93bd2012-03-19 14:02:47 +00002181 (void) TransformImageColorspace(_image,
2182 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2183 _exception);
anthony805a2d42011-09-25 08:25:12 +00002184 break;
2185 }
anthonyafa3dfc2012-03-03 11:31:30 +00002186 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002187 {
anthonydcf3a912012-03-22 14:33:17 +00002188 /* DEPRECIATED: The -/+level provides far more controlled form */
anthony92c93bd2012-03-19 14:02:47 +00002189 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002190 break;
2191 }
anthonyafa3dfc2012-03-03 11:31:30 +00002192 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002193 {
2194 double
2195 black_point,
2196 white_point;
2197
2198 MagickStatusType
2199 flags;
2200
anthonyebb73a22012-03-22 14:25:52 +00002201 if (IsGeometry(arg1) == MagickFalse)
2202 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002203 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002204 black_point=geometry_info.rho;
2205 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2206 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002207 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002208 black_point*=(double) _image->columns*_image->rows/100.0;
2209 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002210 }
anthony92c93bd2012-03-19 14:02:47 +00002211 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002212 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002213 (void) ContrastStretchImage(_image,black_point,white_point,
2214 _exception);
anthony805a2d42011-09-25 08:25:12 +00002215 break;
2216 }
anthonyafa3dfc2012-03-03 11:31:30 +00002217 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002218 {
2219 KernelInfo
2220 *kernel_info;
2221
anthonyfd706f92012-01-19 04:22:02 +00002222 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002223 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002224 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +00002225 /* kernel_info->bias=_image->bias; -- FUTURE: check this path! */
anthony92c93bd2012-03-19 14:02:47 +00002226 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002227 kernel_info=DestroyKernelInfo(kernel_info);
2228 break;
2229 }
anthonyafa3dfc2012-03-03 11:31:30 +00002230 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002231 {
anthony31f1bf72012-01-30 12:37:22 +00002232 /* WARNING: This can generate multiple images! */
anthonyebb73a22012-03-22 14:25:52 +00002233 if (IsGeometry(arg1) == MagickFalse)
2234 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002235 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002236 break;
2237 }
anthonyafa3dfc2012-03-03 11:31:30 +00002238 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002239 {
anthonyebb73a22012-03-22 14:25:52 +00002240 if (IsGeometry(arg1) == MagickFalse)
2241 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002242 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2243 _exception);
anthony805a2d42011-09-25 08:25:12 +00002244 break;
2245 }
anthonyebb73a22012-03-22 14:25:52 +00002246 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002247 }
2248 case 'd':
2249 {
anthonyafa3dfc2012-03-03 11:31:30 +00002250 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002251 {
2252 StringInfo
2253 *passkey;
2254
anthony92c93bd2012-03-19 14:02:47 +00002255 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002256 if (passkey == (StringInfo *) NULL)
2257 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2258
2259 (void) PasskeyDecipherImage(_image,passkey,_exception);
2260 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002261 break;
2262 }
anthonyafa3dfc2012-03-03 11:31:30 +00002263 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002264 {
anthony92c93bd2012-03-19 14:02:47 +00002265 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002266 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002267
anthonydcf510d2011-10-30 13:51:40 +00002268 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2269 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002270
anthonyfd706f92012-01-19 04:22:02 +00002271 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002272 */
anthony92c93bd2012-03-19 14:02:47 +00002273 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002274 break;
2275 }
anthonyafa3dfc2012-03-03 11:31:30 +00002276 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002277 {
2278 double
2279 threshold;
2280
anthonyebb73a22012-03-22 14:25:52 +00002281 if (IfNormalOp) {
2282 if (IsGeometry(arg1) == MagickFalse)
2283 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002284 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002285 }
anthonyafa3dfc2012-03-03 11:31:30 +00002286 else
2287 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002288 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002289 break;
2290 }
anthonyafa3dfc2012-03-03 11:31:30 +00002291 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002292 {
anthony92c93bd2012-03-19 14:02:47 +00002293 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002294 break;
2295 }
anthonyafa3dfc2012-03-03 11:31:30 +00002296 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002297 {
2298 char
2299 *args,
2300 token[MaxTextExtent];
2301
2302 const char
2303 *p;
2304
anthony805a2d42011-09-25 08:25:12 +00002305 double
2306 *arguments;
2307
2308 register ssize_t
2309 x;
2310
2311 size_t
2312 number_arguments;
2313
anthony2a0ec8c2012-03-24 04:35:56 +00002314 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2315 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002316 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2317 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002318 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002319 {
anthony80c37752012-01-16 01:03:11 +00002320 double
2321 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002322 /* Special Case - Argument is actually a resize geometry!
2323 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002324 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002325 Roll into a resize special operator */
anthonyebb73a22012-03-22 14:25:52 +00002326 if (IsGeometry(arg2) == MagickFalse)
2327 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2328 option,arg2);
2329 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002330 resize_args[0]=(double) geometry.width;
2331 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002332 new_image=DistortImage(_image,(DistortImageMethod) parse,
2333 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002334 break;
2335 }
anthonyfd706f92012-01-19 04:22:02 +00002336 /* handle percent arguments */
anthonyebb73a22012-03-22 14:25:52 +00002337 args=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00002338 if (args == (char *) NULL)
2339 break;
anthonyfd706f92012-01-19 04:22:02 +00002340 /* convert arguments into an array of doubles
2341 FUTURE: make this a separate function.
2342 Also make use of new 'sentinal' feature to avoid need for
2343 tokenization.
2344 */
anthony805a2d42011-09-25 08:25:12 +00002345 p=(char *) args;
2346 for (x=0; *p != '\0'; x++)
2347 {
2348 GetMagickToken(p,&p,token);
2349 if (*token == ',')
2350 GetMagickToken(p,&p,token);
2351 }
2352 number_arguments=(size_t) x;
2353 arguments=(double *) AcquireQuantumMemory(number_arguments,
2354 sizeof(*arguments));
2355 if (arguments == (double *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002356 CLIWandExceptionBreak(ResourceLimitFatalError,
2357 "MemoryAllocationFailed",option);
anthony805a2d42011-09-25 08:25:12 +00002358 (void) ResetMagickMemory(arguments,0,number_arguments*
anthonyebb73a22012-03-22 14:25:52 +00002359 sizeof(*arguments));
anthony805a2d42011-09-25 08:25:12 +00002360 p=(char *) args;
2361 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2362 {
2363 GetMagickToken(p,&p,token);
2364 if (*token == ',')
2365 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002366 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002367 }
2368 args=DestroyString(args);
anthony2a0ec8c2012-03-24 04:35:56 +00002369 new_image=DistortImage(_image,(DistortImageMethod) parse,
2370 number_arguments,arguments,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002371 arguments=(double *) RelinquishMagickMemory(arguments);
2372 break;
2373 }
anthonyafa3dfc2012-03-03 11:31:30 +00002374 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002375 {
anthony92c93bd2012-03-19 14:02:47 +00002376 (void) CloneString(&_draw_info->primitive,arg1);
2377 (void) DrawImage(_image,_draw_info,_exception);
2378 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002379 break;
2380 }
anthonyebb73a22012-03-22 14:25:52 +00002381 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002382 }
2383 case 'e':
2384 {
anthonyafa3dfc2012-03-03 11:31:30 +00002385 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002386 {
anthony2a0ec8c2012-03-24 04:35:56 +00002387 if (IsGeometry(arg1) == MagickFalse)
2388 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002389 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002390 if ((flags & SigmaValue) == 0)
2391 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002392 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2393 _exception);
anthony805a2d42011-09-25 08:25:12 +00002394 break;
2395 }
anthonyafa3dfc2012-03-03 11:31:30 +00002396 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002397 {
anthony2a0ec8c2012-03-24 04:35:56 +00002398 if (IsGeometry(arg1) == MagickFalse)
2399 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002400 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002401 if ((flags & SigmaValue) == 0)
2402 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002403 new_image=EmbossImage(_image,geometry_info.rho,
2404 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002405 break;
2406 }
anthonyafa3dfc2012-03-03 11:31:30 +00002407 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002408 {
2409 StringInfo
2410 *passkey;
2411
anthony92c93bd2012-03-19 14:02:47 +00002412 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002413 if (passkey != (StringInfo *) NULL)
2414 {
anthony92c93bd2012-03-19 14:02:47 +00002415 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002416 passkey=DestroyStringInfo(passkey);
2417 }
2418 break;
2419 }
anthonyafa3dfc2012-03-03 11:31:30 +00002420 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002421 {
anthony92c93bd2012-03-19 14:02:47 +00002422 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002423 break;
2424 }
anthonyafa3dfc2012-03-03 11:31:30 +00002425 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002426 {
anthony92c93bd2012-03-19 14:02:47 +00002427 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002428 break;
2429 }
anthonyafa3dfc2012-03-03 11:31:30 +00002430 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002431 {
2432 double
2433 constant;
2434
anthony2a0ec8c2012-03-24 04:35:56 +00002435 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2436 if ( parse < 0 )
2437 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2438 option,arg1);
2439 if (IsGeometry(arg2) == MagickFalse)
2440 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002441 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002442 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2443 _exception);
anthony805a2d42011-09-25 08:25:12 +00002444 break;
2445 }
anthonyafa3dfc2012-03-03 11:31:30 +00002446 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002447 {
anthony2a0ec8c2012-03-24 04:35:56 +00002448 if (IsGeometry(arg1) == MagickFalse)
2449 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002450 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002451 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002452 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002453 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002454 geometry.height=_image->rows;
2455 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002456 break;
2457 }
anthonyebb73a22012-03-22 14:25:52 +00002458 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002459 }
2460 case 'f':
2461 {
anthonyafa3dfc2012-03-03 11:31:30 +00002462 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002463 {
anthony31f1bf72012-01-30 12:37:22 +00002464 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002465 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002466 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002467 break;
2468 }
anthony92c93bd2012-03-19 14:02:47 +00002469 (void) SetImageArtifact(_image,"identify:features","true");
2470 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002471 break;
2472 }
anthonyafa3dfc2012-03-03 11:31:30 +00002473 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002474 {
anthony92c93bd2012-03-19 14:02:47 +00002475 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002476 break;
2477 }
anthonyafa3dfc2012-03-03 11:31:30 +00002478 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002479 {
anthony92c93bd2012-03-19 14:02:47 +00002480 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002481 break;
2482 }
anthonyafa3dfc2012-03-03 11:31:30 +00002483 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002484 {
2485 PixelInfo
2486 target;
2487
anthony2a0ec8c2012-03-24 04:35:56 +00002488 if (IsGeometry(arg1) == MagickFalse)
2489 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002490 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2491 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2492 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2493 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002494 break;
2495 }
anthonyafa3dfc2012-03-03 11:31:30 +00002496 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002497 {
2498 FrameInfo
2499 frame_info;
2500
anthony31f1bf72012-01-30 12:37:22 +00002501 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002502 compose;
2503
2504 const char*
2505 value;
2506
anthony92c93bd2012-03-19 14:02:47 +00002507 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002508 if (value != (const char *) NULL)
2509 compose=(CompositeOperator) ParseCommandOption(
2510 MagickComposeOptions,MagickFalse,value);
2511 else
anthony92c93bd2012-03-19 14:02:47 +00002512 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002513
anthony2a0ec8c2012-03-24 04:35:56 +00002514 if (IsGeometry(arg1) == MagickFalse)
2515 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002516 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002517 frame_info.width=geometry.width;
2518 frame_info.height=geometry.height;
2519 if ((flags & HeightValue) == 0)
2520 frame_info.height=geometry.width;
2521 frame_info.outer_bevel=geometry.x;
2522 frame_info.inner_bevel=geometry.y;
2523 frame_info.x=(ssize_t) frame_info.width;
2524 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002525 frame_info.width=_image->columns+2*frame_info.width;
2526 frame_info.height=_image->rows+2*frame_info.height;
2527 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002528 break;
2529 }
anthonyafa3dfc2012-03-03 11:31:30 +00002530 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002531 {
2532 char
2533 *arguments,
2534 token[MaxTextExtent];
2535
2536 const char
2537 *p;
2538
2539 double
2540 *parameters;
2541
anthony805a2d42011-09-25 08:25:12 +00002542 register ssize_t
2543 x;
2544
2545 size_t
2546 number_parameters;
2547
cristy947cb4c2011-10-20 18:41:46 +00002548 /*
2549 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002550 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002551 */
anthony2a0ec8c2012-03-24 04:35:56 +00002552 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2553 if ( parse < 0 )
2554 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2555 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002556 arguments=InterpretImageProperties(_image_info,_image,arg2,
2557 _exception);
anthony805a2d42011-09-25 08:25:12 +00002558 if (arguments == (char *) NULL)
anthony2a0ec8c2012-03-24 04:35:56 +00002559 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony805a2d42011-09-25 08:25:12 +00002560 p=(char *) arguments;
2561 for (x=0; *p != '\0'; x++)
2562 {
2563 GetMagickToken(p,&p,token);
2564 if (*token == ',')
2565 GetMagickToken(p,&p,token);
2566 }
2567 number_parameters=(size_t) x;
2568 parameters=(double *) AcquireQuantumMemory(number_parameters,
2569 sizeof(*parameters));
2570 if (parameters == (double *) NULL)
2571 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002572 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002573 (void) ResetMagickMemory(parameters,0,number_parameters*
2574 sizeof(*parameters));
2575 p=(char *) arguments;
anthony2a0ec8c2012-03-24 04:35:56 +00002576 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++) {
anthony805a2d42011-09-25 08:25:12 +00002577 GetMagickToken(p,&p,token);
2578 if (*token == ',')
2579 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002580 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002581 }
2582 arguments=DestroyString(arguments);
anthony2a0ec8c2012-03-24 04:35:56 +00002583 (void) FunctionImage(_image,(MagickFunction)parse,number_parameters,
2584 parameters,_exception);
anthony805a2d42011-09-25 08:25:12 +00002585 parameters=(double *) RelinquishMagickMemory(parameters);
2586 break;
2587 }
anthonyebb73a22012-03-22 14:25:52 +00002588 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002589 }
2590 case 'g':
2591 {
anthonyafa3dfc2012-03-03 11:31:30 +00002592 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002593 {
anthonyfe1aa782012-03-24 13:43:04 +00002594 if (IsGeometry(arg1) == MagickFalse)
2595 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafa3dfc2012-03-03 11:31:30 +00002596 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002597 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2598 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002599 else
anthony92c93bd2012-03-19 14:02:47 +00002600 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002601 break;
2602 }
anthonyafa3dfc2012-03-03 11:31:30 +00002603 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2604 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002605 {
anthonyfe1aa782012-03-24 13:43:04 +00002606 if (IsGeometry(arg1) == MagickFalse)
2607 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002608 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002609 if ((flags & SigmaValue) == 0)
2610 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002611 new_image=GaussianBlurImage(_image,geometry_info.rho,
2612 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002613 break;
2614 }
anthonyafa3dfc2012-03-03 11:31:30 +00002615 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002616 {
anthonyfd706f92012-01-19 04:22:02 +00002617 /*
anthony31f1bf72012-01-30 12:37:22 +00002618 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002619 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002620 FUTURE: Why if no 'offset' does this resize ALL images?
2621 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002622 */
anthonyafa3dfc2012-03-03 11:31:30 +00002623 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002624 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002625 if (_image->geometry != (char *) NULL)
2626 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002627 break;
2628 }
anthonyfe1aa782012-03-24 13:43:04 +00002629 if (IsGeometry(arg1) == MagickFalse)
2630 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002631 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002632 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002633 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002634 else
anthony92c93bd2012-03-19 14:02:47 +00002635 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002636 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002637 break;
2638 }
anthonyebb73a22012-03-22 14:25:52 +00002639 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002640 }
2641 case 'h':
2642 {
anthonyafa3dfc2012-03-03 11:31:30 +00002643 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002644 {
anthony92c93bd2012-03-19 14:02:47 +00002645 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002646 break;
2647 }
anthonyebb73a22012-03-22 14:25:52 +00002648 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002649 }
2650 case 'i':
2651 {
anthonyafa3dfc2012-03-03 11:31:30 +00002652 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002653 {
anthony31f1bf72012-01-30 12:37:22 +00002654 const char
2655 *format,
anthony805a2d42011-09-25 08:25:12 +00002656 *text;
2657
anthony92c93bd2012-03-19 14:02:47 +00002658 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002659 if (format == (char *) NULL)
2660 {
anthony92c93bd2012-03-19 14:02:47 +00002661 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2662 _exception);
anthony805a2d42011-09-25 08:25:12 +00002663 break;
2664 }
anthony92c93bd2012-03-19 14:02:47 +00002665 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002666 if (text == (char *) NULL)
2667 break;
2668 (void) fputs(text,stdout);
2669 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002670 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002671 break;
2672 }
anthonyafa3dfc2012-03-03 11:31:30 +00002673 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002674 {
anthonyfe1aa782012-03-24 13:43:04 +00002675 if (IsGeometry(arg1) == MagickFalse)
2676 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002677 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002678 new_image=ImplodeImage(_image,geometry_info.rho,
2679 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002680 break;
2681 }
anthonyafa3dfc2012-03-03 11:31:30 +00002682 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002683 {
anthonyfe1aa782012-03-24 13:43:04 +00002684 /* FUTURE: New to IMv7
2685 Roll into a resize special operator */
2686 if (IsGeometry(arg1) == MagickFalse)
2687 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002688 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2689 new_image=InterpolativeResizeImage(_image,geometry.width,
2690 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002691 break;
2692 }
anthonyebb73a22012-03-22 14:25:52 +00002693 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002694 }
2695 case 'l':
2696 {
anthonyafa3dfc2012-03-03 11:31:30 +00002697 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002698 {
anthonyfe1aa782012-03-24 13:43:04 +00002699 if (IsGeometry(arg1) == MagickFalse)
2700 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002701 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002702 if ((flags & PercentValue) != 0)
2703 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002704 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002705 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002706 _exception);
anthony805a2d42011-09-25 08:25:12 +00002707 break;
2708 }
anthonyafa3dfc2012-03-03 11:31:30 +00002709 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002710 {
2711 MagickRealType
2712 black_point,
2713 gamma,
2714 white_point;
2715
2716 MagickStatusType
2717 flags;
2718
anthonyfe1aa782012-03-24 13:43:04 +00002719 if (IsGeometry(arg1) == MagickFalse)
2720 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002721 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002722 black_point=geometry_info.rho;
2723 white_point=(MagickRealType) QuantumRange;
2724 if ((flags & SigmaValue) != 0)
2725 white_point=geometry_info.sigma;
2726 gamma=1.0;
2727 if ((flags & XiValue) != 0)
2728 gamma=geometry_info.xi;
2729 if ((flags & PercentValue) != 0)
2730 {
2731 black_point*=(MagickRealType) (QuantumRange/100.0);
2732 white_point*=(MagickRealType) (QuantumRange/100.0);
2733 }
2734 if ((flags & SigmaValue) == 0)
2735 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002736 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002737 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002738 else
anthony92c93bd2012-03-19 14:02:47 +00002739 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002740 break;
2741 }
anthonyafa3dfc2012-03-03 11:31:30 +00002742 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002743 {
2744 char
2745 token[MaxTextExtent];
2746
2747 const char
2748 *p;
2749
2750 PixelInfo
2751 black_point,
2752 white_point;
2753
anthonyfd706f92012-01-19 04:22:02 +00002754 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002755 GetMagickToken(p,&p,token); /* get black point color */
2756 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002757 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002758 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002759 else
cristy269c9412011-10-13 23:41:15 +00002760 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002761 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002762 if (isalpha((int) token[0]) || (token[0] == '#'))
2763 GetMagickToken(p,&p,token);
2764 if (*token == '\0')
2765 white_point=black_point; /* set everything to that color */
2766 else
2767 {
2768 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2769 GetMagickToken(p,&p,token); /* Get white point color. */
2770 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002771 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002772 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002773 else
cristy269c9412011-10-13 23:41:15 +00002774 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002775 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002776 }
anthony92c93bd2012-03-19 14:02:47 +00002777 (void) LevelImageColors(_image,&black_point,&white_point,
2778 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002779 break;
2780 }
anthonyafa3dfc2012-03-03 11:31:30 +00002781 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002782 {
2783 double
2784 black_point,
2785 white_point;
2786
2787 MagickStatusType
2788 flags;
2789
anthonyfe1aa782012-03-24 13:43:04 +00002790 if (IsGeometry(arg1) == MagickFalse)
2791 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002792 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002793 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002794 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002795 if ((flags & SigmaValue) != 0)
2796 white_point=geometry_info.sigma;
2797 if ((flags & PercentValue) != 0)
2798 {
anthony92c93bd2012-03-19 14:02:47 +00002799 black_point*=(double) _image->columns*_image->rows/100.0;
2800 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002801 }
2802 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002803 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002804 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002805 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002806 break;
2807 }
anthonyafa3dfc2012-03-03 11:31:30 +00002808 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002809 {
anthonyfe1aa782012-03-24 13:43:04 +00002810 /* FUTURE: Roll into a resize special operator */
2811 if (IsGeometry(arg1) == MagickFalse)
2812 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002813 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002814 if ((flags & XValue) == 0)
2815 geometry.x=1;
2816 if ((flags & YValue) == 0)
2817 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002818 new_image=LiquidRescaleImage(_image,geometry.width,
2819 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002820 break;
2821 }
anthonyafa3dfc2012-03-03 11:31:30 +00002822 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002823 {
anthony92c93bd2012-03-19 14:02:47 +00002824 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002825 break;
2826 }
anthonyebb73a22012-03-22 14:25:52 +00002827 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002828 }
2829 case 'm':
2830 {
anthonyafa3dfc2012-03-03 11:31:30 +00002831 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002832 {
2833 Image
2834 *remap_image;
2835
anthony31f1bf72012-01-30 12:37:22 +00002836 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002837 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002838 if (remap_image == (Image *) NULL)
2839 break;
anthony92c93bd2012-03-19 14:02:47 +00002840 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002841 remap_image=DestroyImage(remap_image);
2842 break;
2843 }
anthonyafa3dfc2012-03-03 11:31:30 +00002844 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002845 {
2846 Image
2847 *mask;
2848
anthonyafa3dfc2012-03-03 11:31:30 +00002849 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002850 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002851 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002852 break;
2853 }
anthony5330ae02012-03-20 14:17:01 +00002854 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002855 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002856 if (mask == (Image *) NULL)
2857 break;
anthony92c93bd2012-03-19 14:02:47 +00002858 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002859 mask=DestroyImage(mask);
2860 break;
2861 }
anthonyafa3dfc2012-03-03 11:31:30 +00002862 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002863 {
anthony31f1bf72012-01-30 12:37:22 +00002864 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002865 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2866 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002867 break;
2868 }
anthonya3ef4ed2012-03-17 06:52:53 +00002869 if (LocaleCompare("median",option+1) == 0)
2870 {
2871 /* DEPRECIATED - use -statistic Median */
anthony7bc87992012-03-25 02:32:51 +00002872 if (IsGeometry(arg1) == MagickFalse)
2873 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya3ef4ed2012-03-17 06:52:53 +00002874 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2875 break;
2876 }
anthonyafa3dfc2012-03-03 11:31:30 +00002877 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002878 {
anthony7bc87992012-03-25 02:32:51 +00002879 if (IsGeometry(arg1) == MagickFalse)
2880 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002881 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002882 if ((flags & SigmaValue) == 0)
2883 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002884 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2885 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002886 break;
2887 }
anthonyafa3dfc2012-03-03 11:31:30 +00002888 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002889 {
anthony7bc87992012-03-25 02:32:51 +00002890 if (IsGeometry(arg1) == MagickFalse)
2891 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002892 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002893 break;
2894 }
anthonyafa3dfc2012-03-03 11:31:30 +00002895 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002896 {
anthony92c93bd2012-03-19 14:02:47 +00002897 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002898 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002899 break;
2900 }
anthonyafa3dfc2012-03-03 11:31:30 +00002901 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002902 {
anthony92c93bd2012-03-19 14:02:47 +00002903 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002904 break;
2905 }
anthonyafa3dfc2012-03-03 11:31:30 +00002906 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002907 {
2908 char
2909 token[MaxTextExtent];
2910
2911 const char
2912 *p;
2913
2914 KernelInfo
2915 *kernel;
2916
anthony805a2d42011-09-25 08:25:12 +00002917 ssize_t
2918 iterations;
2919
anthonyfd706f92012-01-19 04:22:02 +00002920 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002921 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002922 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2923 if ( parse < 0 )
2924 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2925 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002926 iterations=1L;
2927 GetMagickToken(p,&p,token);
2928 if ((*p == ':') || (*p == ','))
2929 GetMagickToken(p,&p,token);
2930 if ((*p != '\0'))
2931 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002932 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002933 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002934 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2935 option,arg2);
2936 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2937 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002938 kernel=DestroyKernelInfo(kernel);
2939 break;
2940 }
anthonyafa3dfc2012-03-03 11:31:30 +00002941 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002942 {
anthony7bc87992012-03-25 02:32:51 +00002943 if (IsGeometry(arg1) == MagickFalse)
2944 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002945 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002946 if ((flags & SigmaValue) == 0)
2947 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002948 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002949 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002950 break;
2951 }
anthonyebb73a22012-03-22 14:25:52 +00002952 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002953 }
2954 case 'n':
2955 {
anthonyafa3dfc2012-03-03 11:31:30 +00002956 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002957 {
anthony92c93bd2012-03-19 14:02:47 +00002958 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002959 break;
2960 }
anthonyafa3dfc2012-03-03 11:31:30 +00002961 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002962 {
anthonyafa3dfc2012-03-03 11:31:30 +00002963 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002964 {
anthony7bc87992012-03-25 02:32:51 +00002965 if (IsGeometry(arg1) == MagickFalse)
2966 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002967 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002968 if ((flags & SigmaValue) == 0)
2969 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002970 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2971 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002972 }
2973 else
2974 {
anthony31f1bf72012-01-30 12:37:22 +00002975 double
2976 attenuate;
2977
2978 const char*
2979 value;
2980
anthony7bc87992012-03-25 02:32:51 +00002981 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2982 if ( parse < 0 )
2983 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2984 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002985 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002986 if (value != (const char *) NULL)
2987 attenuate=StringToDouble(value,(char **) NULL);
2988 else
2989 attenuate=1.0;
2990
anthony7bc87992012-03-25 02:32:51 +00002991 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2992 _exception);
anthony805a2d42011-09-25 08:25:12 +00002993 }
2994 break;
2995 }
anthonyafa3dfc2012-03-03 11:31:30 +00002996 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002997 {
anthony92c93bd2012-03-19 14:02:47 +00002998 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002999 break;
3000 }
anthonyebb73a22012-03-22 14:25:52 +00003001 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003002 }
3003 case 'o':
3004 {
anthonyafa3dfc2012-03-03 11:31:30 +00003005 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003006 {
3007 PixelInfo
3008 target;
3009
anthony92c93bd2012-03-19 14:02:47 +00003010 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3011 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
3012 _exception);
anthony805a2d42011-09-25 08:25:12 +00003013 break;
3014 }
anthonyafa3dfc2012-03-03 11:31:30 +00003015 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003016 {
anthony92c93bd2012-03-19 14:02:47 +00003017 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003018 break;
3019 }
anthonyebb73a22012-03-22 14:25:52 +00003020 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003021 }
3022 case 'p':
3023 {
anthonyafa3dfc2012-03-03 11:31:30 +00003024 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003025 {
anthonyfd706f92012-01-19 04:22:02 +00003026 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003027 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
3028 _exception);
anthony805a2d42011-09-25 08:25:12 +00003029 break;
3030 }
anthonyafa3dfc2012-03-03 11:31:30 +00003031 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003032 {
cristye9e3d382011-12-14 01:50:13 +00003033 const char
3034 *caption;
3035
anthony805a2d42011-09-25 08:25:12 +00003036 double
3037 angle;
3038
anthony7bc87992012-03-25 02:32:51 +00003039 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00003040 RandomInfo
3041 *random_info;
anthony805a2d42011-09-25 08:25:12 +00003042
anthonyf42014d2012-03-25 09:53:06 +00003043 random_info=AcquireRandomInfo();
3044 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
3045 random_info=DestroyRandomInfo(random_info);
3046 }
anthony7bc87992012-03-25 02:32:51 +00003047 else {
anthonyf42014d2012-03-25 09:53:06 +00003048 if (IsGeometry(arg1) == MagickFalse)
3049 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3050 flags=ParseGeometry(arg1,&geometry_info);
3051 angle=geometry_info.rho;
3052 }
anthony92c93bd2012-03-19 14:02:47 +00003053 caption=GetImageProperty(_image,"caption",_exception);
3054 new_image=PolaroidImage(_image,_draw_info,caption,angle,
3055 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003056 break;
3057 }
anthonyafa3dfc2012-03-03 11:31:30 +00003058 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003059 {
anthony7bc87992012-03-25 02:32:51 +00003060 if (IsGeometry(arg1) == MagickFalse)
3061 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003062 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003063 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
3064 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00003065 break;
3066 }
anthonyafa3dfc2012-03-03 11:31:30 +00003067 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003068 {
anthony31f1bf72012-01-30 12:37:22 +00003069 /* FUTURE: should be a 'Genesis' option?
3070 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00003071 Why???
cristy947cb4c2011-10-20 18:41:46 +00003072 */
anthony7bc87992012-03-25 02:32:51 +00003073 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
3074 if ( parse < 0 )
3075 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
3076 option,arg1);
3077 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003078 break;
3079 }
anthonyafa3dfc2012-03-03 11:31:30 +00003080 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003081 {
3082 const char
3083 *name;
3084
3085 const StringInfo
3086 *profile;
3087
3088 Image
3089 *profile_image;
3090
3091 ImageInfo
3092 *profile_info;
3093
anthonyafa3dfc2012-03-03 11:31:30 +00003094 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003095 { /* Remove a profile from the _image. */
3096 (void) ProfileImage(_image,arg1,(const unsigned char *)
3097 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003098 break;
3099 }
anthony92c93bd2012-03-19 14:02:47 +00003100 /* Associate a profile with the _image. */
3101 profile_info=CloneImageInfo(_image_info);
3102 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003103 if (profile != (StringInfo *) NULL)
3104 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003105 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003106 profile_info=DestroyImageInfo(profile_info);
3107 if (profile_image == (Image *) NULL)
3108 {
3109 StringInfo
3110 *profile;
3111
anthony92c93bd2012-03-19 14:02:47 +00003112 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003113 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00003114 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00003115 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003116 if (profile != (StringInfo *) NULL)
3117 {
anthony92c93bd2012-03-19 14:02:47 +00003118 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003119 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003120 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003121 profile=DestroyStringInfo(profile);
3122 }
3123 profile_info=DestroyImageInfo(profile_info);
3124 break;
3125 }
3126 ResetImageProfileIterator(profile_image);
3127 name=GetNextImageProfile(profile_image);
3128 while (name != (const char *) NULL)
3129 {
3130 profile=GetImageProfile(profile_image,name);
3131 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003132 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3133 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003134 name=GetNextImageProfile(profile_image);
3135 }
3136 profile_image=DestroyImage(profile_image);
3137 break;
3138 }
anthonyebb73a22012-03-22 14:25:52 +00003139 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003140 }
anthony805a2d42011-09-25 08:25:12 +00003141 case 'r':
3142 {
anthonyafa3dfc2012-03-03 11:31:30 +00003143 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003144 {
anthonyf42014d2012-03-25 09:53:06 +00003145 if (IsGeometry(arg1) == MagickFalse)
3146 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003147 flags=ParseGeometry(arg1,&geometry_info);
cristyaa2c16c2012-03-25 22:21:35 +00003148 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003149 break;
3150 }
anthonyafa3dfc2012-03-03 11:31:30 +00003151 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003152 {
anthonyf42014d2012-03-25 09:53:06 +00003153 if (IsGeometry(arg1) == MagickFalse)
3154 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003155 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003156 if ((flags & SigmaValue) == 0)
3157 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00003158 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003159 break;
3160 }
anthonyafa3dfc2012-03-03 11:31:30 +00003161 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003162 {
anthonyf42014d2012-03-25 09:53:06 +00003163 if (IsGeometry(arg1) == MagickFalse)
3164 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003165 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003166 break;
3167 }
anthonyafa3dfc2012-03-03 11:31:30 +00003168 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003169 {
3170 Image
3171 *remap_image;
3172
anthony92c93bd2012-03-19 14:02:47 +00003173 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003174 if (remap_image == (Image *) NULL)
3175 break;
anthony92c93bd2012-03-19 14:02:47 +00003176 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003177 remap_image=DestroyImage(remap_image);
3178 break;
3179 }
anthonyafa3dfc2012-03-03 11:31:30 +00003180 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003181 {
anthonyafa3dfc2012-03-03 11:31:30 +00003182 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00003183 {
3184 if (IsGeometry(arg1) == MagickFalse)
3185 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3186 arg1);
3187 (void) ResetImagePage(_image,arg1);
3188 }
anthony31f1bf72012-01-30 12:37:22 +00003189 else
anthony92c93bd2012-03-19 14:02:47 +00003190 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003191 break;
3192 }
anthonyafa3dfc2012-03-03 11:31:30 +00003193 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003194 {
anthonyf46d4262012-03-26 03:30:34 +00003195 /* FUTURE: Roll into a resize special operation */
anthonyf42014d2012-03-25 09:53:06 +00003196 if (IsGeometry(arg1) == MagickFalse)
3197 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003198 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003199 if ((flags & SigmaValue) == 0)
3200 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003201 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003202 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003203 break;
3204 }
anthonyafa3dfc2012-03-03 11:31:30 +00003205 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003206 {
anthonyf42014d2012-03-25 09:53:06 +00003207 if (IsGeometry(arg1) == MagickFalse)
3208 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003209 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3210 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003211 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003212 break;
3213 }
anthonyafa3dfc2012-03-03 11:31:30 +00003214 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003215 {
anthonyf42014d2012-03-25 09:53:06 +00003216 if (IsGeometry(arg1) == MagickFalse)
3217 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003218 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3219 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003220 break;
3221 }
anthonyafa3dfc2012-03-03 11:31:30 +00003222 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003223 {
anthonyf42014d2012-03-25 09:53:06 +00003224 if (IsGeometry(arg1) == MagickFalse)
3225 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003226 if (strchr(arg1,'>') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003227 if (_image->columns <= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003228 break;
anthonyfd706f92012-01-19 04:22:02 +00003229 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003230 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003231 break;
anthonyfd706f92012-01-19 04:22:02 +00003232 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003233 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003234 break;
3235 }
anthonyebb73a22012-03-22 14:25:52 +00003236 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003237 }
3238 case 's':
3239 {
anthonyafa3dfc2012-03-03 11:31:30 +00003240 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003241 {
anthonyfe1aa782012-03-24 13:43:04 +00003242 /* FUTURE: Roll into a resize special operator */
anthonyf42014d2012-03-25 09:53:06 +00003243 if (IsGeometry(arg1) == MagickFalse)
3244 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003245 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3246 new_image=SampleImage(_image,geometry.width,geometry.height,
3247 _exception);
anthony805a2d42011-09-25 08:25:12 +00003248 break;
3249 }
anthonyafa3dfc2012-03-03 11:31:30 +00003250 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003251 {
anthonyfe1aa782012-03-24 13:43:04 +00003252 /* FUTURE: Roll into a resize special operator */
anthonyf42014d2012-03-25 09:53:06 +00003253 if (IsGeometry(arg1) == MagickFalse)
3254 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003255 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3256 new_image=ScaleImage(_image,geometry.width,geometry.height,
3257 _exception);
anthony805a2d42011-09-25 08:25:12 +00003258 break;
3259 }
anthonyf42014d2012-03-25 09:53:06 +00003260 if (LocaleCompare("segment",option+1) == 0)
3261 {
3262 if (IsGeometry(arg1) == MagickFalse)
3263 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3264 flags=ParseGeometry(arg1,&geometry_info);
3265 if ((flags & SigmaValue) == 0)
3266 geometry_info.sigma=1.0;
3267 (void) SegmentImage(_image,_image->colorspace,
3268 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3269 _exception);
3270 break;
3271 }
anthonyafa3dfc2012-03-03 11:31:30 +00003272 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003273 {
anthonyf42014d2012-03-25 09:53:06 +00003274 if (IsGeometry(arg1) == MagickFalse)
3275 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003276 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003277 if ((flags & PercentValue) != 0)
3278 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003279 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003280 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003281 break;
3282 }
anthonyafa3dfc2012-03-03 11:31:30 +00003283 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003284 {
anthony31f1bf72012-01-30 12:37:22 +00003285 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003286 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003287 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003288 break;
3289 }
anthonyafa3dfc2012-03-03 11:31:30 +00003290 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003291 {
anthonyf42014d2012-03-25 09:53:06 +00003292 if (IsGeometry(arg1) == MagickFalse)
3293 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3294 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3295 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003296 break;
3297 }
anthonyafa3dfc2012-03-03 11:31:30 +00003298 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003299 {
3300 char
3301 *value;
3302
anthonyf42014d2012-03-25 09:53:06 +00003303 if (IfPlusOp) {
anthonyfd706f92012-01-19 04:22:02 +00003304 if (LocaleNCompare(arg1,"registry:",9) == 0)
3305 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003306 else
anthony31f1bf72012-01-30 12:37:22 +00003307 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003308 {
anthony92c93bd2012-03-19 14:02:47 +00003309 (void) DeleteImageOption(_image_info,arg1+7);
3310 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003311 }
3312 else
anthony92c93bd2012-03-19 14:02:47 +00003313 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003314 break;
3315 }
anthonyf42014d2012-03-25 09:53:06 +00003316 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003317 if (value == (char *) NULL)
3318 break;
anthonyfd706f92012-01-19 04:22:02 +00003319 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003320 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003321 else
anthonyfd706f92012-01-19 04:22:02 +00003322 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003323 {
anthony92c93bd2012-03-19 14:02:47 +00003324 (void) SetImageOption(_image_info,arg1+7,value);
3325 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003326 }
3327 else
anthony92c93bd2012-03-19 14:02:47 +00003328 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003329 value=DestroyString(value);
3330 break;
3331 }
anthonyafa3dfc2012-03-03 11:31:30 +00003332 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003333 {
anthonyf42014d2012-03-25 09:53:06 +00003334 if (IsGeometry(arg1) == MagickFalse)
3335 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003336 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003337 if ((flags & SigmaValue) == 0)
3338 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003339 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3340 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003341 break;
3342 }
anthonyafa3dfc2012-03-03 11:31:30 +00003343 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003344 {
anthonyf42014d2012-03-25 09:53:06 +00003345 if (IsGeometry(arg1) == MagickFalse)
3346 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003347 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003348 if ((flags & SigmaValue) == 0)
3349 geometry_info.sigma=1.0;
3350 if ((flags & XiValue) == 0)
3351 geometry_info.xi=4.0;
3352 if ((flags & PsiValue) == 0)
3353 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003354 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3355 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3356 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003357 break;
3358 }
anthonyafa3dfc2012-03-03 11:31:30 +00003359 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003360 {
anthonyf42014d2012-03-25 09:53:06 +00003361 if (IsGeometry(arg1) == MagickFalse)
3362 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003363 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003364 if ((flags & SigmaValue) == 0)
3365 geometry_info.sigma=1.0;
3366 if ((flags & XiValue) == 0)
3367 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003368 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3369 _exception);
anthony805a2d42011-09-25 08:25:12 +00003370 break;
3371 }
anthonyafa3dfc2012-03-03 11:31:30 +00003372 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003373 {
anthonyf42014d2012-03-25 09:53:06 +00003374 if (IsGeometry(arg1) == MagickFalse)
3375 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003376 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3377 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003378 break;
3379 }
anthonyafa3dfc2012-03-03 11:31:30 +00003380 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003381 {
anthonyf42014d2012-03-25 09:53:06 +00003382 if (IsGeometry(arg1) == MagickFalse)
3383 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003384 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003385 if ((flags & SigmaValue) == 0)
3386 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003387 new_image=ShearImage(_image,geometry_info.rho,
3388 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003389 break;
3390 }
anthonyafa3dfc2012-03-03 11:31:30 +00003391 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003392 {
anthonyf42014d2012-03-25 09:53:06 +00003393 if (IsGeometry(arg1) == MagickFalse)
3394 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003395 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003396 if ((flags & SigmaValue) == 0)
3397 geometry_info.sigma=(double) QuantumRange/2.0;
3398 if ((flags & PercentValue) != 0)
3399 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3400 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003401 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003402 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003403 _exception);
anthony805a2d42011-09-25 08:25:12 +00003404 break;
3405 }
anthonyafa3dfc2012-03-03 11:31:30 +00003406 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003407 {
anthonyf42014d2012-03-25 09:53:06 +00003408 if (IsGeometry(arg1) == MagickFalse)
3409 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003410 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003411 if ((flags & SigmaValue) == 0)
3412 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003413 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003414 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003415 break;
3416 }
anthonyafa3dfc2012-03-03 11:31:30 +00003417 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003418 {
anthonyf42014d2012-03-25 09:53:06 +00003419 if (IsGeometry(arg1) == MagickFalse)
3420 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003421 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3422 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003423 break;
3424 }
anthonyafa3dfc2012-03-03 11:31:30 +00003425 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003426 {
anthony805a2d42011-09-25 08:25:12 +00003427 char
3428 *arguments;
3429
anthonyf42014d2012-03-25 09:53:06 +00003430 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3431 if ( parse < 0 )
3432 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3433 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003434 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003435 if (arguments == (char *) NULL)
anthonyf42014d2012-03-25 09:53:06 +00003436 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3437 new_image=SparseColorOption(_image,(SparseColorMethod)parse,
3438 arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003439 arguments=DestroyString(arguments);
3440 break;
3441 }
anthonyafa3dfc2012-03-03 11:31:30 +00003442 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003443 {
anthonyf42014d2012-03-25 09:53:06 +00003444 if (IsGeometry(arg1) == MagickFalse)
3445 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003446 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3447 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003448 break;
3449 }
anthonyafa3dfc2012-03-03 11:31:30 +00003450 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003451 {
anthonyf42014d2012-03-25 09:53:06 +00003452 if (IsGeometry(arg1) == MagickFalse)
3453 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003454 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003455 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3456 _exception);
anthony805a2d42011-09-25 08:25:12 +00003457 break;
3458 }
anthonyafa3dfc2012-03-03 11:31:30 +00003459 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003460 {
anthony7bc87992012-03-25 02:32:51 +00003461 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3462 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003463 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003464 option,arg1);
3465 if (IsGeometry(arg2) == MagickFalse)
3466 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00003467 (void) ParseGeometry(arg2,&geometry_info);
anthony7bc87992012-03-25 02:32:51 +00003468 new_image=StatisticImage(_image,(StatisticType)parse,
3469 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3470 _exception);
anthony805a2d42011-09-25 08:25:12 +00003471 break;
3472 }
anthonyafa3dfc2012-03-03 11:31:30 +00003473 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003474 {
anthony92c93bd2012-03-19 14:02:47 +00003475 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003476 break;
3477 }
anthonyafa3dfc2012-03-03 11:31:30 +00003478 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003479 {
anthonyf42014d2012-03-25 09:53:06 +00003480 if (IsGeometry(arg1) == MagickFalse)
3481 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003482 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003483 new_image=SwirlImage(_image,geometry_info.rho,
3484 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003485 break;
3486 }
anthonyebb73a22012-03-22 14:25:52 +00003487 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003488 }
3489 case 't':
3490 {
anthonyafa3dfc2012-03-03 11:31:30 +00003491 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003492 {
3493 double
3494 threshold;
3495
anthony52bef752012-03-27 13:54:47 +00003496 threshold=(double) QuantumRange/2;
3497 if (normal_op) {
3498 if (IsGeometry(arg1) == MagickFalse)
3499 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003500 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003501 }
anthony92c93bd2012-03-19 14:02:47 +00003502 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003503 break;
3504 }
anthonyafa3dfc2012-03-03 11:31:30 +00003505 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003506 {
anthony52bef752012-03-27 13:54:47 +00003507 if (IsGeometry(arg1) == MagickFalse)
3508 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003509 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3510 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3511 _exception);
anthony805a2d42011-09-25 08:25:12 +00003512 break;
3513 }
anthonyafa3dfc2012-03-03 11:31:30 +00003514 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003515 {
anthony52bef752012-03-27 13:54:47 +00003516 if (IsGeometry(arg1) == MagickFalse)
3517 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003518 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003519 break;
3520 }
anthonyafa3dfc2012-03-03 11:31:30 +00003521 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003522 {
anthonya3ef4ed2012-03-17 06:52:53 +00003523 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony52bef752012-03-27 13:54:47 +00003524 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003525 break;
3526 }
anthonyafa3dfc2012-03-03 11:31:30 +00003527 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003528 {
3529 PixelInfo
3530 target;
3531
anthony92c93bd2012-03-19 14:02:47 +00003532 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3533 (void) TransparentPaintImage(_image,&target,(Quantum)
3534 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003535 break;
3536 }
anthonyafa3dfc2012-03-03 11:31:30 +00003537 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003538 {
anthony92c93bd2012-03-19 14:02:47 +00003539 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003540 break;
3541 }
anthonyafa3dfc2012-03-03 11:31:30 +00003542 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003543 {
anthony92c93bd2012-03-19 14:02:47 +00003544 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003545 break;
3546 }
anthonyafa3dfc2012-03-03 11:31:30 +00003547 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003548 {
anthony92c93bd2012-03-19 14:02:47 +00003549 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003550 break;
3551 }
anthonyafa3dfc2012-03-03 11:31:30 +00003552 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003553 {
anthonyab3a50c2011-10-27 11:48:57 +00003554 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003555 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003556 break;
3557 }
anthonyebb73a22012-03-22 14:25:52 +00003558 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003559 }
3560 case 'u':
3561 {
anthonyafa3dfc2012-03-03 11:31:30 +00003562 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003563 {
anthony52bef752012-03-27 13:54:47 +00003564 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3565 Option is not documented, bt appears to be for "identify".
3566 We may need a identify specific verbose!
3567 */
3568 if (plus_alt_op) {
anthony92c93bd2012-03-19 14:02:47 +00003569 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003570 break;
3571 }
anthony92c93bd2012-03-19 14:02:47 +00003572 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3573 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003574 break;
3575 }
anthonyafa3dfc2012-03-03 11:31:30 +00003576 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003577 {
anthony92c93bd2012-03-19 14:02:47 +00003578 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003579 break;
3580 }
anthonyafa3dfc2012-03-03 11:31:30 +00003581 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003582 {
anthony52bef752012-03-27 13:54:47 +00003583 if (IsGeometry(arg1) == MagickFalse)
3584 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003585 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003586 if ((flags & SigmaValue) == 0)
3587 geometry_info.sigma=1.0;
3588 if ((flags & XiValue) == 0)
3589 geometry_info.xi=1.0;
3590 if ((flags & PsiValue) == 0)
3591 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003592 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3593 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003594 break;
3595 }
anthonyebb73a22012-03-22 14:25:52 +00003596 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003597 }
3598 case 'v':
3599 {
anthonyafa3dfc2012-03-03 11:31:30 +00003600 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003601 {
anthonyafa3dfc2012-03-03 11:31:30 +00003602 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003603 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003604 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003605 */
anthony92c93bd2012-03-19 14:02:47 +00003606 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003607 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003608 break;
3609 }
anthonyafa3dfc2012-03-03 11:31:30 +00003610 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003611 {
anthony52bef752012-03-27 13:54:47 +00003612 if (IsGeometry(arg1) == MagickFalse)
3613 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003614 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003615 if ((flags & SigmaValue) == 0)
3616 geometry_info.sigma=1.0;
3617 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003618 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003619 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003620 geometry_info.psi=0.1*_image->rows;
3621 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003622 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3623 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003624 break;
3625 }
anthonyebb73a22012-03-22 14:25:52 +00003626 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003627 }
3628 case 'w':
3629 {
anthonyafa3dfc2012-03-03 11:31:30 +00003630 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003631 {
anthony52bef752012-03-27 13:54:47 +00003632 if (IsGeometry(arg1) == MagickFalse)
3633 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003634 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003635 if ((flags & SigmaValue) == 0)
3636 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003637 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3638 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003639 break;
3640 }
anthonyafa3dfc2012-03-03 11:31:30 +00003641 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003642 {
anthony52bef752012-03-27 13:54:47 +00003643 if (IsGeometry(arg1) == MagickFalse)
3644 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003645 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003646 break;
3647 }
anthonyebb73a22012-03-22 14:25:52 +00003648 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003649 }
3650 default:
anthonyebb73a22012-03-22 14:25:52 +00003651 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003652 }
3653 /*
3654 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003655 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003656 */
3657 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003658 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003659
anthony31f1bf72012-01-30 12:37:22 +00003660 return;
anthony92c93bd2012-03-19 14:02:47 +00003661#undef _image_info
3662#undef _draw_info
3663#undef _quantize_info
3664#undef _image
3665#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003666#undef IfNormalOp
3667#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003668#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003669#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003670}
anthonyfd706f92012-01-19 04:22:02 +00003671
anthony43f425d2012-02-26 12:58:58 +00003672WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003673 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003674{
3675 size_t
anthony43f425d2012-02-26 12:58:58 +00003676 n,
anthony31f1bf72012-01-30 12:37:22 +00003677 i;
3678
anthony43f425d2012-02-26 12:58:58 +00003679 assert(cli_wand != (MagickCLI *) NULL);
3680 assert(cli_wand->signature == WandSignature);
3681 assert(cli_wand->wand.signature == WandSignature);
3682 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3683 if (cli_wand->wand.debug != MagickFalse)
3684 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003685
anthonyafa3dfc2012-03-03 11:31:30 +00003686#if !USE_WAND_METHODS
3687 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003688 i=0;
anthony43f425d2012-02-26 12:58:58 +00003689 n=GetImageListLength(cli_wand->wand.images);
3690 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003691 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003692 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003693 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003694 if ( cli_wand->wand.images->next == (Image *) NULL )
3695 break;
3696 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003697 }
anthony43f425d2012-02-26 12:58:58 +00003698 assert( i == n );
3699 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003700#else
3701 MagickResetIterator(&cli_wand->wand);
3702 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3703 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3704 MagickResetIterator(&cli_wand->wand);
3705#endif
anthony31f1bf72012-01-30 12:37:22 +00003706 return;
anthony805a2d42011-09-25 08:25:12 +00003707}
3708
3709/*
3710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3711% %
3712% %
3713% %
anthony43f425d2012-02-26 12:58:58 +00003714+ 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 +00003715% %
3716% %
3717% %
3718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3719%
anthony43f425d2012-02-26 12:58:58 +00003720% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003721% entire image list as a whole. The result is often a complete replacment
3722% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003723%
3724% The format of the MogrifyImage method is:
3725%
anthony43f425d2012-02-26 12:58:58 +00003726% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003727% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003728%
3729% A description of each parameter follows:
3730%
anthony43f425d2012-02-26 12:58:58 +00003731% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003732%
anthony36a8c2c2012-02-10 00:08:44 +00003733% o option: The option string for the operation
3734%
anthony31f1bf72012-01-30 12:37:22 +00003735% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003736%
anthonyfe1aa782012-03-24 13:43:04 +00003737% NOTE: only "limit" uses two arguments.
anthony8b10b462012-02-08 12:32:44 +00003738%
3739% Example usage...
3740%
anthonyafa3dfc2012-03-03 11:31:30 +00003741% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3742% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003743%
anthony24aa8822012-03-11 00:56:06 +00003744% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003745%
anthony43f425d2012-02-26 12:58:58 +00003746% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003747% argc,argv
3748% i=index in argv
3749%
anthony2052d272012-02-28 12:48:29 +00003750% option_info = GetCommandOptionInfo(argv[i]);
3751% count=option_info->type;
3752% option_type=option_info->flags;
3753%
3754% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003755% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003756% count>=1 ? argv[i+1] : (char *)NULL,
3757% count>=2 ? argv[i+2] : (char *)NULL );
3758% i += count+1;
3759%
anthony805a2d42011-09-25 08:25:12 +00003760*/
anthony43f425d2012-02-26 12:58:58 +00003761WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003762 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003763{
anthony2a0ec8c2012-03-24 04:35:56 +00003764 ssize_t
3765 parse;
3766
anthony31f1bf72012-01-30 12:37:22 +00003767 Image
3768 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003769
anthony92c93bd2012-03-19 14:02:47 +00003770#define _image_info (cli_wand->wand.image_info)
3771#define _images (cli_wand->wand.images)
3772#define _exception (cli_wand->wand.exception)
3773#define _draw_info (cli_wand->draw_info)
3774#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003775#define IfNormalOp (*option=='-')
3776#define IfPlusOp (*option!='-')
3777#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003778
anthony43f425d2012-02-26 12:58:58 +00003779 assert(cli_wand != (MagickCLI *) NULL);
3780 assert(cli_wand->signature == WandSignature);
3781 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003782 assert(_images != (Image *) NULL); /* _images must be present */
anthony43f425d2012-02-26 12:58:58 +00003783 if (cli_wand->wand.debug != MagickFalse)
3784 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003785
anthony92c93bd2012-03-19 14:02:47 +00003786 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003787
3788 new_images=NewImageList();
3789
anthonyafa3dfc2012-03-03 11:31:30 +00003790 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003791 {
3792 case 'a':
3793 {
anthonyafa3dfc2012-03-03 11:31:30 +00003794 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003795 {
anthony92c93bd2012-03-19 14:02:47 +00003796 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003797 break;
3798 }
anthonyafa3dfc2012-03-03 11:31:30 +00003799 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003800 {
anthony31f1bf72012-01-30 12:37:22 +00003801 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003802 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003803 break;
3804 }
anthonyebb73a22012-03-22 14:25:52 +00003805 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003806 }
3807 case 'c':
3808 {
cristy5f257b22012-03-07 00:27:29 +00003809 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003810 {
anthony92c93bd2012-03-19 14:02:47 +00003811 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003812 break;
3813 }
anthonyafa3dfc2012-03-03 11:31:30 +00003814 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003815 {
anthony805a2d42011-09-25 08:25:12 +00003816 Image
anthony31f1bf72012-01-30 12:37:22 +00003817 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003818
anthonyafa3dfc2012-03-03 11:31:30 +00003819 /* FUTURE - make this a compose option, and thus can be used
3820 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003821 _images.
cristy87c02f42012-02-24 00:19:10 +00003822 */
anthony92c93bd2012-03-19 14:02:47 +00003823 new_images=RemoveFirstImageFromList(&_images);
3824 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003825 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003826 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003827 break;
anthony92c93bd2012-03-19 14:02:47 +00003828 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003829 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003830 break;
3831 }
anthonyafa3dfc2012-03-03 11:31:30 +00003832 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003833 {
anthony92c93bd2012-03-19 14:02:47 +00003834 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003835 break;
3836 }
anthonyafa3dfc2012-03-03 11:31:30 +00003837 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003838 {
anthony43f425d2012-02-26 12:58:58 +00003839 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003840 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003841 break;
3842 }
anthonyafa3dfc2012-03-03 11:31:30 +00003843 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003844 {
cristyfeb3e962012-03-29 17:25:55 +00003845 CompositeOperator
3846 compose;
3847
3848 const char*
3849 value;
3850
3851 MagickBooleanType
3852 clip_to_self;
3853
anthony805a2d42011-09-25 08:25:12 +00003854 Image
3855 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003856 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003857
3858 RectangleInfo
3859 geometry;
3860
anthony92c93bd2012-03-19 14:02:47 +00003861 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003862 if (value != (const char *) NULL)
3863 compose=(CompositeOperator) ParseCommandOption(
3864 MagickComposeOptions,MagickFalse,value);
3865 else
anthony31f1bf72012-01-30 12:37:22 +00003866 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003867
anthony92c93bd2012-03-19 14:02:47 +00003868 new_images=RemoveFirstImageFromList(&_images);
3869 source_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 (source_image == (Image *) NULL)
3872 break;
anthonye8f56492012-02-12 12:39:02 +00003873
anthony31f1bf72012-01-30 12:37:22 +00003874 /* FUTURE - this should not be here! - should be part of -geometry */
3875 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003876 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003877
anthony31f1bf72012-01-30 12:37:22 +00003878 SetGeometry(source_image,&geometry);
3879 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3880 GravityAdjustGeometry(new_images->columns,new_images->rows,
3881 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003882
anthony92c93bd2012-03-19 14:02:47 +00003883 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003884 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003885 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003886 if ((compose == DisplaceCompositeOp) ||
3887 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003888 { /* Merge Y displacement into X displace/distort map. */
cristyfeb3e962012-03-29 17:25:55 +00003889 (void) CompositeImage(source_image,mask_image,
3890 CopyGreenCompositeOp,MagickFalse,0,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003891 mask_image=DestroyImage(mask_image);
3892 }
3893 else
3894 {
3895 /*
3896 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003897 */
anthony92c93bd2012-03-19 14:02:47 +00003898 (void) NegateImage(mask_image,MagickFalse,_exception);
3899 (void) SetImageMask(new_images,mask_image,_exception);
cristy1539afd2012-01-30 01:32:59 +00003900 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003901 }
3902 }
cristyfeb3e962012-03-29 17:25:55 +00003903 clip_to_self=MagickFalse;
3904 value=GetImageArtifact(source_image,"compose:outside-overlay");
3905 if (value != (const char *) NULL)
3906 clip_to_self=IsMagickTrue(value) == MagickFalse ? MagickTrue :
3907 MagickFalse;
3908 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3909 geometry.x,geometry.y,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003910 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003911 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003912 break;
3913 }
anthonyebb73a22012-03-22 14:25:52 +00003914 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003915 }
3916 case 'd':
3917 {
anthonyafa3dfc2012-03-03 11:31:30 +00003918 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003919 {
anthony31f1bf72012-01-30 12:37:22 +00003920 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003921 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003922 break;
3923 }
anthonyafa3dfc2012-03-03 11:31:30 +00003924 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003925 {
anthonyafa3dfc2012-03-03 11:31:30 +00003926 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003927 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003928 else
anthony92c93bd2012-03-19 14:02:47 +00003929 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003930 break;
3931 }
anthonyafa3dfc2012-03-03 11:31:30 +00003932 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003933 {
anthonyafa3dfc2012-03-03 11:31:30 +00003934 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003935 {
3936 const char
3937 *p;
3938
3939 size_t
3940 number_duplicates;
3941
anthonyebb73a22012-03-22 14:25:52 +00003942 if (IsGeometry(arg1) == MagickFalse)
3943 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3944 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003945 number_duplicates=(size_t) StringToLong(arg1);
3946 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003947 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003948 new_images=DuplicateImages(_images,number_duplicates,"-1",
3949 _exception);
anthony805a2d42011-09-25 08:25:12 +00003950 else
anthony92c93bd2012-03-19 14:02:47 +00003951 new_images=DuplicateImages(_images,number_duplicates,p,
3952 _exception);
anthony805a2d42011-09-25 08:25:12 +00003953 }
anthonyafa3dfc2012-03-03 11:31:30 +00003954 else
anthony92c93bd2012-03-19 14:02:47 +00003955 new_images=DuplicateImages(_images,1,"-1",_exception);
3956 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003957 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003958 break;
3959 }
anthonyebb73a22012-03-22 14:25:52 +00003960 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003961 }
3962 case 'e':
3963 {
anthonyafa3dfc2012-03-03 11:31:30 +00003964 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003965 {
anthony2a0ec8c2012-03-24 04:35:56 +00003966 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3967 if ( parse < 0 )
3968 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3969 option,arg1);
3970 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3971 _exception);
anthony805a2d42011-09-25 08:25:12 +00003972 break;
3973 }
anthonyebb73a22012-03-22 14:25:52 +00003974 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003975 }
3976 case 'f':
3977 {
anthonyafa3dfc2012-03-03 11:31:30 +00003978 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003979 {
anthony92c93bd2012-03-19 14:02:47 +00003980 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003981 break;
3982 }
anthonyafa3dfc2012-03-03 11:31:30 +00003983 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003984 {
anthony319dac62012-03-06 04:12:44 +00003985 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003986 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003987 break;
3988 }
anthonyafa3dfc2012-03-03 11:31:30 +00003989 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003990 {
anthony92c93bd2012-03-19 14:02:47 +00003991 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003992 break;
3993 }
anthonyebb73a22012-03-22 14:25:52 +00003994 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003995 }
3996 case 'h':
3997 {
anthonyafa3dfc2012-03-03 11:31:30 +00003998 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003999 {
anthony31f1bf72012-01-30 12:37:22 +00004000 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00004001 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00004002 */
anthony805a2d42011-09-25 08:25:12 +00004003 Image
anthony31f1bf72012-01-30 12:37:22 +00004004 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00004005
anthony92c93bd2012-03-19 14:02:47 +00004006 new_images=RemoveFirstImageFromList(&_images);
4007 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004008 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004009 break;
anthony92c93bd2012-03-19 14:02:47 +00004010 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00004011 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00004012 break;
4013 }
anthonyebb73a22012-03-22 14:25:52 +00004014 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004015 }
4016 case 'i':
4017 {
anthonyafa3dfc2012-03-03 11:31:30 +00004018 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004019 {
4020 Image
anthony805a2d42011-09-25 08:25:12 +00004021 *magnitude_image,
4022 *phase_image;
4023
anthony92c93bd2012-03-19 14:02:47 +00004024 magnitude_image=RemoveFirstImageFromList(&_images);
4025 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00004026 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00004027 if (phase_image == (Image *) NULL)
4028 break;
4029 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00004030 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004031 magnitude_image=DestroyImage(magnitude_image);
4032 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00004033 break;
4034 }
anthonyafa3dfc2012-03-03 11:31:30 +00004035 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004036 {
4037 Image
anthony31f1bf72012-01-30 12:37:22 +00004038 *insert_image,
4039 *index_image;
4040
4041 ssize_t
4042 index;
anthony805a2d42011-09-25 08:25:12 +00004043
anthonyfe1aa782012-03-24 13:43:04 +00004044 if (IfNormalOp && IsGeometry(arg1) == MagickFalse)
4045 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004046 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004047 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004048 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004049 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004050 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004051 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004052 PrependImageToList(&_images,insert_image);
4053 else if (index == (ssize_t) GetImageListLength(_images))
4054 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004055 else
anthony43f425d2012-02-26 12:58:58 +00004056 {
anthony92c93bd2012-03-19 14:02:47 +00004057 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004058 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004059 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004060 InsertImageInList(&index_image,insert_image);
4061 }
anthony92c93bd2012-03-19 14:02:47 +00004062 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004063 break;
4064 }
anthonyebb73a22012-03-22 14:25:52 +00004065 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004066 }
4067 case 'l':
4068 {
anthonyafa3dfc2012-03-03 11:31:30 +00004069 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004070 {
anthonyfe1aa782012-03-24 13:43:04 +00004071 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4072 if ( parse < 0 )
4073 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4074 option,arg1);
4075 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004076 {
4077 case CoalesceLayer:
4078 {
anthony92c93bd2012-03-19 14:02:47 +00004079 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004080 break;
4081 }
4082 case CompareAnyLayer:
4083 case CompareClearLayer:
4084 case CompareOverlayLayer:
4085 default:
4086 {
anthonyfe1aa782012-03-24 13:43:04 +00004087 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
4088 _exception);
anthony805a2d42011-09-25 08:25:12 +00004089 break;
4090 }
4091 case MergeLayer:
4092 case FlattenLayer:
4093 case MosaicLayer:
4094 case TrimBoundsLayer:
4095 {
anthonyfe1aa782012-03-24 13:43:04 +00004096 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
4097 _exception);
anthony805a2d42011-09-25 08:25:12 +00004098 break;
4099 }
4100 case DisposeLayer:
4101 {
anthony92c93bd2012-03-19 14:02:47 +00004102 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004103 break;
4104 }
4105 case OptimizeImageLayer:
4106 {
anthony92c93bd2012-03-19 14:02:47 +00004107 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004108 break;
4109 }
4110 case OptimizePlusLayer:
4111 {
anthony92c93bd2012-03-19 14:02:47 +00004112 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004113 break;
4114 }
4115 case OptimizeTransLayer:
4116 {
anthony92c93bd2012-03-19 14:02:47 +00004117 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004118 break;
4119 }
4120 case RemoveDupsLayer:
4121 {
anthony92c93bd2012-03-19 14:02:47 +00004122 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004123 break;
4124 }
4125 case RemoveZeroLayer:
4126 {
anthony92c93bd2012-03-19 14:02:47 +00004127 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004128 break;
4129 }
4130 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004131 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004132 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004133 if (new_images == (Image *) NULL)
4134 break;
anthony92c93bd2012-03-19 14:02:47 +00004135 _images=DestroyImageList(_images);
4136 _images=OptimizeImageLayers(new_images,_exception);
4137 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004138 break;
4139 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004140 OptimizeImageTransparency(_images,_exception);
4141 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4142 _exception);
anthony805a2d42011-09-25 08:25:12 +00004143 break;
4144 }
4145 case CompositeLayer:
4146 {
anthony805a2d42011-09-25 08:25:12 +00004147 Image
4148 *source;
4149
4150 RectangleInfo
4151 geometry;
4152
anthony31f1bf72012-01-30 12:37:22 +00004153 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004154 compose;
4155
4156 const char*
4157 value;
4158
anthony92c93bd2012-03-19 14:02:47 +00004159 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004160 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004161 if (value != (const char *) NULL)
4162 compose=(CompositeOperator) ParseCommandOption(
4163 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004164
anthony31f1bf72012-01-30 12:37:22 +00004165 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004166 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004167 while (source != (Image *) NULL)
4168 {
4169 source=GetNextImageInList(source);
4170 if ((source != (Image *) NULL) &&
4171 (LocaleCompare(source->magick,"NULL") == 0))
4172 break;
4173 }
4174 if (source != (Image *) NULL)
4175 {
4176 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4177 (GetNextImageInList(source) == (Image *) NULL))
4178 source=(Image *) NULL;
4179 else
anthony31f1bf72012-01-30 12:37:22 +00004180 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004181 source=SplitImageList(source->previous);
4182 DeleteImageFromList(&source);
4183 }
4184 }
4185 if (source == (Image *) NULL)
4186 {
anthony92c93bd2012-03-19 14:02:47 +00004187 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004188 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004189 break;
4190 }
anthony31f1bf72012-01-30 12:37:22 +00004191 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004192 SetGeometry(_images,&geometry);
4193 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004194 geometry.width=source->page.width != 0 ?
4195 source->page.width : source->columns;
4196 geometry.height=source->page.height != 0 ?
4197 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004198 GravityAdjustGeometry(_images->page.width != 0 ?
4199 _images->page.width : _images->columns,
4200 _images->page.height != 0 ? _images->page.height :
4201 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004202
anthony31f1bf72012-01-30 12:37:22 +00004203 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004204 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4205 _exception);
anthony805a2d42011-09-25 08:25:12 +00004206 source=DestroyImageList(source);
4207 break;
4208 }
4209 }
anthony805a2d42011-09-25 08:25:12 +00004210 break;
4211 }
anthonyafa3dfc2012-03-03 11:31:30 +00004212 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00004213 {
4214 MagickSizeType
4215 limit;
4216
anthony72feaa62012-01-17 06:46:23 +00004217 limit=MagickResourceInfinity;
anthonyfe1aa782012-03-24 13:43:04 +00004218 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4219 if ( parse < 0 )
4220 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4221 option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004222 if (LocaleCompare("unlimited",arg2) != 0)
4223 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthonyfe1aa782012-03-24 13:43:04 +00004224 (void) SetMagickResourceLimit((ResourceType)parse,limit);
anthony72feaa62012-01-17 06:46:23 +00004225 break;
4226 }
anthonyebb73a22012-03-22 14:25:52 +00004227 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004228 }
4229 case 'm':
4230 {
anthonyafa3dfc2012-03-03 11:31:30 +00004231 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004232 {
anthony31f1bf72012-01-30 12:37:22 +00004233 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004234 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004235 break;
4236 }
anthonyafa3dfc2012-03-03 11:31:30 +00004237 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004238 {
4239 Image
4240 *morph_image;
4241
anthony7bc87992012-03-25 02:32:51 +00004242 if (IsGeometry(arg1) == MagickFalse)
4243 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004244 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4245 _exception);
anthony805a2d42011-09-25 08:25:12 +00004246 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004247 break;
anthony92c93bd2012-03-19 14:02:47 +00004248 _images=DestroyImageList(_images);
4249 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004250 break;
4251 }
anthonyafa3dfc2012-03-03 11:31:30 +00004252 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004253 {
anthony319dac62012-03-06 04:12:44 +00004254 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00004255 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004256 break;
4257 }
anthonyebb73a22012-03-22 14:25:52 +00004258 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004259 }
4260 case 'p':
4261 {
anthonyafa3dfc2012-03-03 11:31:30 +00004262 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004263 {
4264 char
4265 *string;
4266
anthony92c93bd2012-03-19 14:02:47 +00004267 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004268 if (string == (char *) NULL)
4269 break;
4270 (void) FormatLocaleFile(stdout,"%s",string);
4271 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004272 break;
anthony805a2d42011-09-25 08:25:12 +00004273 }
anthonyafa3dfc2012-03-03 11:31:30 +00004274 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004275 {
4276 char
4277 **arguments;
4278
4279 int
4280 j,
4281 number_arguments;
4282
anthony31f1bf72012-01-30 12:37:22 +00004283 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004284 if (arguments == (char **) NULL)
4285 break;
anthony31f1bf72012-01-30 12:37:22 +00004286 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004287 {
4288 char
4289 breaker,
4290 quote,
4291 *token;
4292
4293 const char
4294 *arguments;
4295
4296 int
4297 next,
4298 status;
4299
4300 size_t
4301 length;
4302
4303 TokenInfo
4304 *token_info;
4305
4306 /*
anthony24aa8822012-03-11 00:56:06 +00004307 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004308 */
anthony31f1bf72012-01-30 12:37:22 +00004309 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004310 token=(char *) NULL;
4311 if (~length >= (MaxTextExtent-1))
4312 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4313 sizeof(*token));
4314 if (token == (char *) NULL)
4315 break;
4316 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004317 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004318 token_info=AcquireTokenInfo();
4319 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4320 "\"",'\0',&breaker,&next,&quote);
4321 token_info=DestroyTokenInfo(token_info);
4322 if (status == 0)
4323 {
4324 const char
4325 *argv;
4326
4327 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004328 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4329 _exception);
anthony805a2d42011-09-25 08:25:12 +00004330 }
4331 token=DestroyString(token);
4332 break;
4333 }
4334 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004335 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4336 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004337 for (j=0; j < number_arguments; j++)
4338 arguments[j]=DestroyString(arguments[j]);
4339 arguments=(char **) RelinquishMagickMemory(arguments);
4340 break;
4341 }
anthonyebb73a22012-03-22 14:25:52 +00004342 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004343 }
4344 case 'r':
4345 {
anthonyafa3dfc2012-03-03 11:31:30 +00004346 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004347 {
anthony92c93bd2012-03-19 14:02:47 +00004348 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004349 break;
4350 }
anthonyafa3dfc2012-03-03 11:31:30 +00004351 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004352 {
anthony92c93bd2012-03-19 14:02:47 +00004353 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004354 break;
4355 }
anthonyebb73a22012-03-22 14:25:52 +00004356 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004357 }
4358 case 's':
4359 {
anthonyafa3dfc2012-03-03 11:31:30 +00004360 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004361 {
4362 Image
4363 *smush_image;
4364
4365 ssize_t
4366 offset;
4367
anthonyf42014d2012-03-25 09:53:06 +00004368 if (IsGeometry(arg1) == MagickFalse)
4369 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004370 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004371 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004372 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004373 break;
anthony92c93bd2012-03-19 14:02:47 +00004374 _images=DestroyImageList(_images);
4375 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004376 break;
4377 }
anthonyafa3dfc2012-03-03 11:31:30 +00004378 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004379 {
4380 Image
4381 *p,
4382 *q,
4383 *swap;
4384
4385 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004386 index,
anthony805a2d42011-09-25 08:25:12 +00004387 swap_index;
4388
anthonyf42014d2012-03-25 09:53:06 +00004389 if (IsGeometry(arg1) == MagickFalse)
4390 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004391 index=-1;
4392 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004393 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004394 {
4395 GeometryInfo
4396 geometry_info;
4397
4398 MagickStatusType
4399 flags;
4400
4401 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004402 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004403 index=(ssize_t) geometry_info.rho;
4404 if ((flags & SigmaValue) != 0)
4405 swap_index=(ssize_t) geometry_info.sigma;
4406 }
anthony92c93bd2012-03-19 14:02:47 +00004407 p=GetImageFromList(_images,index);
4408 q=GetImageFromList(_images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004409 if ((p == (Image *) NULL) || (q == (Image *) NULL))
anthonyf42014d2012-03-25 09:53:06 +00004410 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004411 if (p == q)
anthonyf42014d2012-03-25 09:53:06 +00004412 break; /* same image - no-op - not an error */
anthony92c93bd2012-03-19 14:02:47 +00004413 swap=CloneImage(p,0,0,MagickTrue,_exception);
4414 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
anthony805a2d42011-09-25 08:25:12 +00004415 ReplaceImageInList(&q,swap);
anthony92c93bd2012-03-19 14:02:47 +00004416 _images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004417 break;
4418 }
anthonyebb73a22012-03-22 14:25:52 +00004419 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004420 }
4421 case 'w':
4422 {
anthonyafa3dfc2012-03-03 11:31:30 +00004423 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004424 {
4425 char
4426 key[MaxTextExtent];
4427
4428 Image
4429 *write_images;
4430
4431 ImageInfo
4432 *write_info;
4433
anthony31f1bf72012-01-30 12:37:22 +00004434 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004435 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004436 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004437 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004438 write_images=CloneImageList(_images,_exception);
4439 write_info=CloneImageInfo(_image_info);
4440 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004441 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004442 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004443 write_images=DestroyImageList(write_images);
4444 break;
4445 }
anthonyebb73a22012-03-22 14:25:52 +00004446 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004447 }
4448 default:
anthonyebb73a22012-03-22 14:25:52 +00004449 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004450 }
anthony31f1bf72012-01-30 12:37:22 +00004451 if (new_images == (Image *) NULL)
4452 return;
anthony805a2d42011-09-25 08:25:12 +00004453
anthony92c93bd2012-03-19 14:02:47 +00004454 if (_images != (Image *) NULL)
4455 _images=DestroyImageList(_images);
4456 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004457 return;
4458
anthony92c93bd2012-03-19 14:02:47 +00004459#undef _image_info
4460#undef _images
4461#undef _exception
4462#undef _draw_info
4463#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004464#undef IfNormalOp
4465#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004466#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004467}
anthony43f425d2012-02-26 12:58:58 +00004468
4469/*
4470%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4471% %
4472% %
4473% %
4474+ C L I S p e c i a l O p e r a t i o n s %
4475% %
4476% %
4477% %
4478%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4479%
4480% CLISpecialOption() Applies operations that may involve empty image lists
4481% and or stacks of image lists or image_info settings.
4482%
anthonyafa3dfc2012-03-03 11:31:30 +00004483% The classic operators of this type is -read, and image stack operators,
4484% which can be applied to empty image lists.
4485%
4486% Note: unlike other Operators, these may involve other special 'option'
4487% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004488%
4489% The format of the CLISpecialOption method is:
4490%
4491% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004492% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004493%
4494% A description of each parameter follows:
4495%
4496% o cli_wand: the main CLI Wand to use.
4497%
4498% o option: The special option (with any switch char) to process
4499%
anthony24aa8822012-03-11 00:56:06 +00004500% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004501%
anthony2052d272012-02-28 12:48:29 +00004502% Example Usage...
4503%
anthonyce8dcb32012-03-21 13:20:31 +00004504% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004505%
anthony24aa8822012-03-11 00:56:06 +00004506% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004507%
4508% cli_wand
4509% argc,argv
4510% i=index in argv
4511%
4512% option_info = GetCommandOptionInfo(argv[i]);
4513% count=option_info->type;
4514% option_type=option_info->flags;
4515%
4516% if ( (option_type & SpecialOptionFlag) != 0 )
4517% CLISpecialOperator(cli_wand,argv[i],
4518% count>=1 ? argv[i+1] : (char *)NULL);
4519% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004520%
4521*/
4522
anthony43f425d2012-02-26 12:58:58 +00004523WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004524 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004525{
anthony92c93bd2012-03-19 14:02:47 +00004526#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004527
4528 assert(cli_wand != (MagickCLI *) NULL);
4529 assert(cli_wand->signature == WandSignature);
4530 assert(cli_wand->wand.signature == WandSignature);
4531 if (cli_wand->wand.debug != MagickFalse)
4532 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4533
anthony24aa8822012-03-11 00:56:06 +00004534 if(cli_wand->wand.images != (Image *)NULL)
4535 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004536 _exception);
anthony24aa8822012-03-11 00:56:06 +00004537
anthony52bef752012-03-27 13:54:47 +00004538 /*
4539 No-op options
4540 */
4541 if (LocaleCompare("noop",option+1) == 0)
4542 return;
4543 if (LocaleCompare("sans",option+1) == 0)
4544 return;
4545 if (LocaleCompare("sans0",option+1) == 0)
4546 return;
4547 if (LocaleCompare("sans2",option+1) == 0)
4548 return;
4549 /*
4550 Image Reading
4551 */
4552 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4553 ( LocaleCompare("--",option) == 0 ) ) {
4554/*
4555 int argc = 1
4556 char **argv = &arg1;
4557 MagickBooleanType
4558 status=ExpandFilenames(&argc,&argv);
4559
4560 if (status == MagickFalse)
4561 ThrowConvertException(ResourceLimitError,"MemoryAllocationFailed",
4562 GetExceptionMessage(errno));
4563 ...loop over images to read...
4564*/
4565#if !USE_WAND_METHODS
4566 Image *
4567 new_images;
4568 if (cli_wand->wand.image_info->ping != MagickFalse)
4569 new_images=PingImages(cli_wand->wand.image_info,arg1,_exception);
4570 else
4571 new_images=ReadImages(cli_wand->wand.image_info,arg1,_exception);
4572 AppendImageToList(&cli_wand->wand.images, new_images);
4573#else
4574 /* read images using MagickWand method - no ping */
4575 /* This is not working! - it locks up in a CPU loop! */
4576 MagickSetLastIterator(&cli_wand->wand);
4577 MagickReadImage(&cli_wand->wand,arg1);
4578 MagickSetFirstIterator(&cli_wand->wand);
4579#endif
4580 return;
4581 }
4582 /*
4583 Parenthesis and Brace operations
4584 */
anthonyce8dcb32012-03-21 13:20:31 +00004585 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
anthonyf42014d2012-03-25 09:53:06 +00004586 /* link image and setting stacks - option is itself saved on stack! */
anthonyce8dcb32012-03-21 13:20:31 +00004587 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4588 *option == '-' ? "true" : (char *) NULL);
4589 return;
4590 }
4591 if (LocaleCompare("(",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004592 /* stack 'push' images */
4593 Stack
4594 *node;
4595
4596 size_t
4597 size;
4598
anthony43f425d2012-02-26 12:58:58 +00004599 size=0;
4600 node=cli_wand->image_list_stack;
4601 for ( ; node != (Stack *)NULL; node=node->next)
4602 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004603 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004604 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004605 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4606 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004607 CLIWandExceptionReturn(ResourceLimitFatalError,
4608 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004609 node->data = (void *)cli_wand->wand.images;
4610 cli_wand->wand.images = NewImageList();
4611 node->next = cli_wand->image_list_stack;
4612 cli_wand->image_list_stack = node;
4613
4614 /* handle respect-parenthesis */
anthonyf42014d2012-03-25 09:53:06 +00004615 if (IsMagickTrue(GetImageOption(cli_wand->wand.image_info,
anthonyce8dcb32012-03-21 13:20:31 +00004616 "respect-parenthesis")) != MagickFalse )
anthonyf42014d2012-03-25 09:53:06 +00004617 option="{"; /* fall-thru so as to push image settings too */
anthony43f425d2012-02-26 12:58:58 +00004618 else
4619 return;
4620 }
anthonyce8dcb32012-03-21 13:20:31 +00004621 if (LocaleCompare("{",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004622 /* stack 'push' of image_info settings */
4623 Stack
4624 *node;
4625
4626 size_t
4627 size;
4628
4629 size=0;
4630 node=cli_wand->image_info_stack;
4631 for ( ; node != (Stack *)NULL; node=node->next)
4632 size++;
anthony92c93bd2012-03-19 14:02:47 +00004633 if ( size >= MAX_STACK_DEPTH )
anthony4d4f2c72012-03-22 03:22:03 +00004634 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004635 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004636 if (node == (Stack *) NULL)
4637 CLIWandExceptionReturn(ResourceLimitFatalError,
4638 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004639
4640 node->data = (void *)cli_wand->wand.image_info;
4641 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004642 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
anthony92c93bd2012-03-19 14:02:47 +00004643 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4644 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004645 cli_wand->wand.image_info = (ImageInfo *)node->data;
4646 node = (Stack *)RelinquishMagickMemory(node);
4647 return;
4648 }
anthony43f425d2012-02-26 12:58:58 +00004649
4650 node->next = cli_wand->image_info_stack;
4651 cli_wand->image_info_stack = node;
4652
4653 return;
4654 }
anthonyce8dcb32012-03-21 13:20:31 +00004655 if (LocaleCompare(")",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004656 /* pop images from stack */
4657 Stack
4658 *node;
4659
cristyaa2c16c2012-03-25 22:21:35 +00004660 node = (Stack *)cli_wand->image_list_stack;
anthony43f425d2012-02-26 12:58:58 +00004661 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004662 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004663 cli_wand->image_list_stack = node->next;
4664
4665 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4666 cli_wand->wand.images= (Image *)node->data;
4667 node = (Stack *)RelinquishMagickMemory(node);
4668
anthony4d4f2c72012-03-22 03:22:03 +00004669 /* handle respect-parenthesis - of the previous 'pushed' settings */
anthony43f425d2012-02-26 12:58:58 +00004670 node = cli_wand->image_info_stack;
4671 if ( node != (Stack *)NULL)
4672 {
anthonyce8dcb32012-03-21 13:20:31 +00004673 if (IsMagickTrue(GetImageOption((ImageInfo *)node->data,
4674 "respect-parenthesis")) != MagickFalse )
anthonyf42014d2012-03-25 09:53:06 +00004675 option="}"; /* fall-thru so as to pop image settings too */
anthony43f425d2012-02-26 12:58:58 +00004676 else
4677 return;
4678 }
4679 else
4680 return;
4681 }
anthonyce8dcb32012-03-21 13:20:31 +00004682 if (LocaleCompare("}",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004683 /* pop image_info settings from stack */
4684 Stack
4685 *node;
4686
cristyaa2c16c2012-03-25 22:21:35 +00004687 node = (Stack *)cli_wand->image_info_stack;
anthony43f425d2012-02-26 12:58:58 +00004688 if ( node == (Stack *)NULL)
anthony4d4f2c72012-03-22 03:22:03 +00004689 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
anthony43f425d2012-02-26 12:58:58 +00004690 cli_wand->image_info_stack = node->next;
4691
4692 (void) DestroyImageInfo(cli_wand->wand.image_info);
4693 cli_wand->wand.image_info = (ImageInfo *)node->data;
4694 node = (Stack *)RelinquishMagickMemory(node);
4695
4696 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4697 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4698 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4699
4700 return;
4701 }
anthonyce8dcb32012-03-21 13:20:31 +00004702 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004703 Image
4704 *new_images;
4705
4706 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004707 arg1="-1";
4708 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004709 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004710 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004711 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004712 new_images = (Image *)cli_wand->image_list_stack->data;
4713 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004714 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4715 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004716 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004717 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004718 AppendImageToList(&cli_wand->wand.images,new_images);
4719 return;
4720 }
anthony52bef752012-03-27 13:54:47 +00004721 /*
4722 Informational Operations
4723 */
4724 if (LocaleCompare("verbose",option+1) == 0) {
4725 (void) FormatLocaleFile(stdout,"Version: %s\n",
4726 GetMagickVersion((size_t *) NULL));
4727 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4728 GetMagickCopyright());
4729 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4730 GetMagickFeatures());
anthony43f425d2012-02-26 12:58:58 +00004731 return;
4732 }
anthonyce8dcb32012-03-21 13:20:31 +00004733 if (LocaleCompare("list",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004734 /* FUTURE: This should really be built into the MagickCore
4735 It does not actually require any wand or images at all!
4736 */
4737 ssize_t
4738 list;
4739
anthony24aa8822012-03-11 00:56:06 +00004740 list=ParseCommandOption(MagickListOptions,MagickFalse, arg1);
anthonyfe1aa782012-03-24 13:43:04 +00004741 if ( list < 0 ) {
4742 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4743 return;
4744 }
anthony43f425d2012-02-26 12:58:58 +00004745 switch (list)
4746 {
4747 case MagickCoderOptions:
4748 {
anthony92c93bd2012-03-19 14:02:47 +00004749 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004750 break;
4751 }
4752 case MagickColorOptions:
4753 {
anthony92c93bd2012-03-19 14:02:47 +00004754 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004755 break;
4756 }
4757 case MagickConfigureOptions:
4758 {
anthony92c93bd2012-03-19 14:02:47 +00004759 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004760 break;
4761 }
4762 case MagickDelegateOptions:
4763 {
anthony92c93bd2012-03-19 14:02:47 +00004764 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004765 break;
4766 }
4767 case MagickFontOptions:
4768 {
anthony92c93bd2012-03-19 14:02:47 +00004769 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004770 break;
4771 }
4772 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004773 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004774 break;
4775 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004776 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004777 break;
4778 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004779 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004780 break;
4781 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004782 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004783 break;
4784 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004785 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004786 break;
4787 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004788 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004789 break;
4790 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004791 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004792 break;
4793 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004794 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004795 break;
4796 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004797 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004798 break;
4799 default:
4800 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004801 _exception);
anthony43f425d2012-02-26 12:58:58 +00004802 break;
4803 }
4804 return;
4805 }
4806
4807#if 0
4808 // adjust stack handling
4809 // Other 'special' options this should handle
4810 // "region" "list" "version"
4811 // It does not do "exit" however as due to its side-effect requirements
4812#endif
4813#if 0
4814 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004815#endif
anthonyebb73a22012-03-22 14:25:52 +00004816 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004817
anthony92c93bd2012-03-19 14:02:47 +00004818#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004819}