blob: b9fdd63fbd4cacde44995b57995699692035449c [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 {
anthony74b1cfc2011-10-06 12:44:16 +0000692 /* FUTURE: bias OBSOLETED, replaced by "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 {
anthony92c93bd2012-03-19 14:02:47 +00001514 /* FUTURE: move _image_info string to option splay-tree */
1515 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001516 break;
1517 }
anthonyafa3dfc2012-03-03 11:31:30 +00001518 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001519 {
anthony92c93bd2012-03-19 14:02:47 +00001520 _draw_info->fill_pattern=IfSetOption
1521 ?GetImageCache(_image_info,arg1,_exception)
1522 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001523 break;
1524 }
anthonyafa3dfc2012-03-03 11:31:30 +00001525 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001526 {
anthony72feaa62012-01-17 06:46:23 +00001527 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony92c93bd2012-03-19 14:02:47 +00001528 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001529 break;
1530 }
anthonyafa3dfc2012-03-03 11:31:30 +00001531 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001532 {
anthony92c93bd2012-03-19 14:02:47 +00001533 /* FUTURE: both _image_info attribute & ImageOption in use!
1534 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001535 SyncImageSettings() used to set per-image attribute.
1536
anthonyafbaed72011-10-26 12:05:04 +00001537 Note that +transparent-color, means fall-back to image
1538 attribute so ImageOption is deleted, not set to a default.
1539 */
anthony92c93bd2012-03-19 14:02:47 +00001540 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001541 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001542 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001543 break;
1544 }
anthonyafa3dfc2012-03-03 11:31:30 +00001545 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001546 {
anthony92c93bd2012-03-19 14:02:47 +00001547 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1548 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001549 break;
1550 }
anthonyafa3dfc2012-03-03 11:31:30 +00001551 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001552 {
anthony72feaa62012-01-17 06:46:23 +00001553 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001554 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1555 _image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
anthony72feaa62012-01-17 06:46:23 +00001556 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001557 break;
1558 }
anthonyebb73a22012-03-22 14:25:52 +00001559 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001560 }
1561 case 'u':
1562 {
anthonyafa3dfc2012-03-03 11:31:30 +00001563 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001564 {
anthony92c93bd2012-03-19 14:02:47 +00001565 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001566 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001567 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001568 break;
1569 }
anthonyafa3dfc2012-03-03 11:31:30 +00001570 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001571 {
anthony72feaa62012-01-17 06:46:23 +00001572 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001573 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001574 FUTURE: this probably should be part of the density setting
1575 */
anthony92c93bd2012-03-19 14:02:47 +00001576 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1577 _image_info->units=(ResolutionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001578 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001579 break;
1580 }
anthonyebb73a22012-03-22 14:25:52 +00001581 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001582 }
1583 case 'v':
1584 {
anthonyafa3dfc2012-03-03 11:31:30 +00001585 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001586 {
anthony24aa8822012-03-11 00:56:06 +00001587 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001588 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001589 */
anthony92c93bd2012-03-19 14:02:47 +00001590 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1591 _image_info->verbose= ArgBoolean;
1592 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001593 break;
1594 }
anthonyafa3dfc2012-03-03 11:31:30 +00001595 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001596 {
anthony92c93bd2012-03-19 14:02:47 +00001597 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001598 Only used by coder FPX
1599 */
anthony92c93bd2012-03-19 14:02:47 +00001600 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001601 break;
1602 }
anthonyafa3dfc2012-03-03 11:31:30 +00001603 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001604 {
anthonyfd706f92012-01-19 04:22:02 +00001605 /* SyncImageSettings() used to set per-image attribute.
1606 This is VERY deep in the image caching structure.
1607 */
anthony92c93bd2012-03-19 14:02:47 +00001608 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001609 break;
1610 }
anthonyebb73a22012-03-22 14:25:52 +00001611 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001612 }
1613 case 'w':
1614 {
anthonyafa3dfc2012-03-03 11:31:30 +00001615 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001616 {
anthony72feaa62012-01-17 06:46:23 +00001617 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001618 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001619 */
anthony72feaa62012-01-17 06:46:23 +00001620 if (!IfSetOption)
1621 break;
anthony92c93bd2012-03-19 14:02:47 +00001622 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001623 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001624 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001625 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001626 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001627 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001628 if (_draw_info->weight <= 800)
1629 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001630 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001631 if (_draw_info->weight >= 100)
1632 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001633 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001634 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001635 break;
1636 }
anthonyafa3dfc2012-03-03 11:31:30 +00001637 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001638 {
anthony72feaa62012-01-17 06:46:23 +00001639 /* Used as a image chromaticity setting
1640 SyncImageSettings() used to set per-image attribute.
1641 */
anthony92c93bd2012-03-19 14:02:47 +00001642 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001643 break;
1644 }
anthonyebb73a22012-03-22 14:25:52 +00001645 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001646 }
1647 default:
anthonyebb73a22012-03-22 14:25:52 +00001648 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001649 }
anthony24aa8822012-03-11 00:56:06 +00001650
anthony92c93bd2012-03-19 14:02:47 +00001651#undef _image_info
1652#undef _exception
1653#undef _draw_info
1654#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001655#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001656#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001657#undef ArgBooleanNot
1658#undef ArgBooleanString
1659#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001660
anthony31f1bf72012-01-30 12:37:22 +00001661 return;
anthony805a2d42011-09-25 08:25:12 +00001662}
1663
1664/*
1665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1666% %
1667% %
1668% %
anthony43f425d2012-02-26 12:58:58 +00001669+ 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 +00001670% %
1671% %
1672% %
1673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1674%
anthony31f1bf72012-01-30 12:37:22 +00001675% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001676% the images in the CLI wand, with the settings that was previously saved in
1677% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001678%
1679% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001680% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001681%
anthonyd1447672012-01-19 05:33:53 +00001682% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001683%
anthony43f425d2012-02-26 12:58:58 +00001684% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001685% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001686%
1687% A description of each parameter follows:
1688%
anthony43f425d2012-02-26 12:58:58 +00001689% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001690%
anthonyfd706f92012-01-19 04:22:02 +00001691% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001692%
anthonyfd706f92012-01-19 04:22:02 +00001693% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001694%
anthony31f1bf72012-01-30 12:37:22 +00001695% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001696%
anthony31f1bf72012-01-30 12:37:22 +00001697% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001698%
anthonyafa3dfc2012-03-03 11:31:30 +00001699% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1700% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1701% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001702%
anthony24aa8822012-03-11 00:56:06 +00001703% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001704%
anthony43f425d2012-02-26 12:58:58 +00001705% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001706% argc,argv
1707% i=index in argv
1708%
anthony2052d272012-02-28 12:48:29 +00001709% option_info = GetCommandOptionInfo(argv[i]);
1710% count=option_info->type;
1711% option_type=option_info->flags;
1712%
1713% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001714% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001715% count>=1 ? argv[i+1] : (char *)NULL,
1716% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001717% i += count+1;
1718%
anthony805a2d42011-09-25 08:25:12 +00001719*/
anthony31f1bf72012-01-30 12:37:22 +00001720
1721/*
1722 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001723 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001724
1725 The image in the list may be modified in three different ways...
1726 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1727 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1728 * one image replace by a list of images (-separate and -crop only!)
1729
anthonyafa3dfc2012-03-03 11:31:30 +00001730 In each case the result replaces the single original image in the list, as
1731 well as the pointer to the modified image (last image added if replaced by a
1732 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001733
1734 As the image pointed to may be replaced, the first image in the list may
1735 also change. GetFirstImageInList() should be used by caller if they wish
1736 return the Image pointer to the first image in list.
1737*/
anthony43f425d2012-02-26 12:58:58 +00001738static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001739 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001740{
1741 Image *
1742 new_image;
1743
anthony805a2d42011-09-25 08:25:12 +00001744 GeometryInfo
1745 geometry_info;
1746
1747 RectangleInfo
1748 geometry;
1749
1750 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001751 flags;
1752
anthony92c93bd2012-03-19 14:02:47 +00001753 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001754 parse;
anthony92c93bd2012-03-19 14:02:47 +00001755
1756#define _image_info (cli_wand->wand.image_info)
1757#define _image (cli_wand->wand.images)
1758#define _exception (cli_wand->wand.exception)
1759#define _draw_info (cli_wand->draw_info)
1760#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001761#define IfNormalOp (*option=='-')
1762#define IfPlusOp (*option!='-')
1763#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1764#define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001765
anthony43f425d2012-02-26 12:58:58 +00001766 assert(cli_wand != (MagickCLI *) NULL);
1767 assert(cli_wand->signature == WandSignature);
1768 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001769 assert(_image != (Image *) NULL); /* an image must be present */
anthony43f425d2012-02-26 12:58:58 +00001770 if (cli_wand->wand.debug != MagickFalse)
1771 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001772
anthony92c93bd2012-03-19 14:02:47 +00001773 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001774
anthony805a2d42011-09-25 08:25:12 +00001775 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001776
anthony5330ae02012-03-20 14:17:01 +00001777 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001778
anthonyfd706f92012-01-19 04:22:02 +00001779 /* FUTURE: We may need somthing a little more optimized than this!
1780 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1781 */
anthonyafa3dfc2012-03-03 11:31:30 +00001782 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001783 {
1784 case 'a':
1785 {
anthonyafa3dfc2012-03-03 11:31:30 +00001786 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001787 {
anthony92c93bd2012-03-19 14:02:47 +00001788 if (IsGeometry(arg1) == MagickFalse)
1789 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001790 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001791 if ((flags & SigmaValue) == 0)
1792 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001793 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001794 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001795 break;
1796 }
anthonyafa3dfc2012-03-03 11:31:30 +00001797 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001798 {
anthonyfe1aa782012-03-24 13:43:04 +00001799 /* FUTURE: Roll into a resize special operator */
anthony92c93bd2012-03-19 14:02:47 +00001800 if (IsGeometry(arg1) == MagickFalse)
1801 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1802 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1803 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001804 _exception);
anthony805a2d42011-09-25 08:25:12 +00001805 break;
1806 }
anthonyafa3dfc2012-03-03 11:31:30 +00001807 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001808 {
anthony92c93bd2012-03-19 14:02:47 +00001809 if (IsGeometry(arg1) == MagickFalse)
1810 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001811 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001812 if ((flags & SigmaValue) == 0)
1813 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001814 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001815 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001816 break;
1817 }
anthonyafa3dfc2012-03-03 11:31:30 +00001818 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001819 {
anthony2a0ec8c2012-03-24 04:35:56 +00001820 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1821 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001822 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1823 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001824 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1825 _exception);
anthony805a2d42011-09-25 08:25:12 +00001826 break;
1827 }
anthonyafa3dfc2012-03-03 11:31:30 +00001828 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001829 {
1830 char
1831 *text,
1832 geometry[MaxTextExtent];
1833
anthony92c93bd2012-03-19 14:02:47 +00001834 if (IsGeometry(arg1) == MagickFalse)
1835 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001836 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001837 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001838 if ((flags & SigmaValue) == 0)
1839 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001840 text=InterpretImageProperties(_image_info,_image,arg2,
1841 _exception);
anthony805a2d42011-09-25 08:25:12 +00001842 if (text == (char *) NULL)
1843 break;
anthony92c93bd2012-03-19 14:02:47 +00001844 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001845 text=DestroyString(text);
1846 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1847 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001848 (void) CloneString(&_draw_info->geometry,geometry);
1849 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001850 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001851 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001852 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001853 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001854 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001855 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001856 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001857 (void) AnnotateImage(_image,_draw_info,_exception);
1858 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001859 break;
1860 }
anthonyafa3dfc2012-03-03 11:31:30 +00001861 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001862 {
anthony92c93bd2012-03-19 14:02:47 +00001863 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001864 break;
1865 }
anthonyafa3dfc2012-03-03 11:31:30 +00001866 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001867 {
anthony92c93bd2012-03-19 14:02:47 +00001868 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001869 break;
1870 }
anthonyafa3dfc2012-03-03 11:31:30 +00001871 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001872 {
anthony5330ae02012-03-20 14:17:01 +00001873 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001874 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001875 {
1876 case TopRightOrientation:
1877 {
anthony92c93bd2012-03-19 14:02:47 +00001878 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001879 break;
1880 }
1881 case BottomRightOrientation:
1882 {
anthony92c93bd2012-03-19 14:02:47 +00001883 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001884 break;
1885 }
1886 case BottomLeftOrientation:
1887 {
anthony92c93bd2012-03-19 14:02:47 +00001888 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001889 break;
1890 }
1891 case LeftTopOrientation:
1892 {
anthony92c93bd2012-03-19 14:02:47 +00001893 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001894 break;
1895 }
1896 case RightTopOrientation:
1897 {
anthony92c93bd2012-03-19 14:02:47 +00001898 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001899 break;
1900 }
1901 case RightBottomOrientation:
1902 {
anthony92c93bd2012-03-19 14:02:47 +00001903 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001904 break;
1905 }
1906 case LeftBottomOrientation:
1907 {
anthony92c93bd2012-03-19 14:02:47 +00001908 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001909 break;
1910 }
1911 default:
1912 break;
1913 }
1914 if (new_image != (Image *) NULL)
1915 new_image->orientation=TopLeftOrientation;
1916 break;
1917 }
anthonyebb73a22012-03-22 14:25:52 +00001918 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001919 }
1920 case 'b':
1921 {
anthonyafa3dfc2012-03-03 11:31:30 +00001922 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001923 {
anthony5330ae02012-03-20 14:17:01 +00001924 if (IsGeometry(arg1) == MagickFalse)
1925 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001926 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001927 break;
1928 }
anthonyafa3dfc2012-03-03 11:31:30 +00001929 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001930 {
anthony805a2d42011-09-25 08:25:12 +00001931 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001932 if (IfNormalOp) {
1933 if (IsGeometry(arg1) == MagickFalse)
1934 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001935 flags=ParseGeometry(arg1,&geometry_info);
anthony5330ae02012-03-20 14:17:01 +00001936 }
anthony92c93bd2012-03-19 14:02:47 +00001937 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001938 break;
1939 }
anthonyafa3dfc2012-03-03 11:31:30 +00001940 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001941 {
anthony5330ae02012-03-20 14:17:01 +00001942 if (IsGeometry(arg1) == MagickFalse)
1943 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001944 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001945 if ((flags & SigmaValue) == 0)
1946 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001947 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1948 _exception);
anthony805a2d42011-09-25 08:25:12 +00001949 break;
1950 }
anthonyafa3dfc2012-03-03 11:31:30 +00001951 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001952 {
anthony31f1bf72012-01-30 12:37:22 +00001953 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001954 compose;
1955
1956 const char*
anthony5f867ae2011-10-09 10:28:34 +00001957 value;
1958
anthony5330ae02012-03-20 14:17:01 +00001959 if (IsGeometry(arg1) == MagickFalse)
1960 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1961
anthony92c93bd2012-03-19 14:02:47 +00001962 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001963 if (value != (const char *) NULL)
1964 compose=(CompositeOperator) ParseCommandOption(
1965 MagickComposeOptions,MagickFalse,value);
1966 else
anthony92c93bd2012-03-19 14:02:47 +00001967 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001968
anthony92c93bd2012-03-19 14:02:47 +00001969 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001970 if ((flags & SigmaValue) == 0)
1971 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001972 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001973 break;
1974 }
anthonyafa3dfc2012-03-03 11:31:30 +00001975 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001976 {
1977 double
1978 brightness,
1979 contrast;
1980
1981 GeometryInfo
1982 geometry_info;
1983
1984 MagickStatusType
1985 flags;
1986
anthony5330ae02012-03-20 14:17:01 +00001987 if (IsGeometry(arg1) == MagickFalse)
1988 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001989 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001990 brightness=geometry_info.rho;
1991 contrast=0.0;
1992 if ((flags & SigmaValue) != 0)
1993 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001994 (void) BrightnessContrastImage(_image,brightness,contrast,
1995 _exception);
anthony805a2d42011-09-25 08:25:12 +00001996 break;
1997 }
anthonyebb73a22012-03-22 14:25:52 +00001998 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001999 }
2000 case 'c':
2001 {
anthonyafa3dfc2012-03-03 11:31:30 +00002002 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002003 {
2004 char
2005 *color_correction_collection;
2006
2007 /*
2008 Color correct with a color decision list.
2009 */
anthony92c93bd2012-03-19 14:02:47 +00002010 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002011 if (color_correction_collection == (char *) NULL)
2012 break;
anthony92c93bd2012-03-19 14:02:47 +00002013 (void) ColorDecisionListImage(_image,color_correction_collection,
2014 _exception);
anthony805a2d42011-09-25 08:25:12 +00002015 break;
2016 }
anthonyafa3dfc2012-03-03 11:31:30 +00002017 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002018 {
anthony5330ae02012-03-20 14:17:01 +00002019 if (IsGeometry(arg1) == MagickFalse)
2020 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002021 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002022 if ((flags & SigmaValue) == 0)
2023 geometry_info.sigma=1.0;
2024 if ((flags & XiValue) == 0)
2025 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002026 new_image=CharcoalImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002027 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002028 break;
2029 }
anthonyafa3dfc2012-03-03 11:31:30 +00002030 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002031 {
anthony5330ae02012-03-20 14:17:01 +00002032 if (IsGeometry(arg1) == MagickFalse)
2033 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002034 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
2035 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002036 break;
2037 }
anthonyafa3dfc2012-03-03 11:31:30 +00002038 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002039 {
anthony92c93bd2012-03-19 14:02:47 +00002040 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002041 break;
2042 }
anthonyafa3dfc2012-03-03 11:31:30 +00002043 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002044 {
anthonyafa3dfc2012-03-03 11:31:30 +00002045 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002046 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00002047 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002048 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002049 break;
2050 }
anthonyafa3dfc2012-03-03 11:31:30 +00002051 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002052 {
2053 CacheView
2054 *mask_view;
2055
2056 Image
2057 *mask_image;
2058
2059 register Quantum
2060 *restrict q;
2061
2062 register ssize_t
2063 x;
2064
2065 ssize_t
2066 y;
2067
anthonyafa3dfc2012-03-03 11:31:30 +00002068 if (IfPlusOp) {
2069 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002070 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002071 break;
2072 }
anthony92c93bd2012-03-19 14:02:47 +00002073 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002074 if (mask_image == (Image *) NULL)
2075 break;
anthony92c93bd2012-03-19 14:02:47 +00002076 if (SetImageStorageClass(mask_image,DirectClass,_exception)
anthonyfd706f92012-01-19 04:22:02 +00002077 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00002078 break;
anthony5330ae02012-03-20 14:17:01 +00002079 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002080 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00002081 mask_view=AcquireCacheView(mask_image);
2082 for (y=0; y < (ssize_t) mask_image->rows; y++)
2083 {
2084 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002085 _exception);
anthony805a2d42011-09-25 08:25:12 +00002086 if (q == (Quantum *) NULL)
2087 break;
2088 for (x=0; x < (ssize_t) mask_image->columns; x++)
2089 {
2090 if (mask_image->matte == MagickFalse)
2091 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2092 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2093 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2094 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2095 q+=GetPixelChannels(mask_image);
2096 }
anthony92c93bd2012-03-19 14:02:47 +00002097 if (SyncCacheViewAuthenticPixels(mask_view,_exception) == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002098 break;
2099 }
anthonyfd706f92012-01-19 04:22:02 +00002100 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002101 mask_view=DestroyCacheView(mask_view);
2102 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002103 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002104 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002105 break;
2106 }
anthonyafa3dfc2012-03-03 11:31:30 +00002107 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002108 {
anthony92c93bd2012-03-19 14:02:47 +00002109 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002110 break;
2111 }
anthonyafa3dfc2012-03-03 11:31:30 +00002112 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002113 {
anthony5330ae02012-03-20 14:17:01 +00002114 if (IsGeometry(arg1) == MagickFalse)
2115 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002116 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002117 break;
2118 }
anthonyafa3dfc2012-03-03 11:31:30 +00002119 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002120 {
2121 KernelInfo
2122 *kernel;
2123
anthonyfd706f92012-01-19 04:22:02 +00002124 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002125 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002126 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002127 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002128 kernel=DestroyKernelInfo(kernel);
2129 break;
2130 }
anthonyafa3dfc2012-03-03 11:31:30 +00002131 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002132 {
anthony5330ae02012-03-20 14:17:01 +00002133 /* Reduce the number of colors in the image.
2134 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002135 */
anthony92c93bd2012-03-19 14:02:47 +00002136 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2137 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002138 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002139 if ((_image->storage_class == DirectClass) ||
2140 _image->colors > _quantize_info->number_colors)
2141 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002142 else
anthony92c93bd2012-03-19 14:02:47 +00002143 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002144 break;
2145 }
anthonyafa3dfc2012-03-03 11:31:30 +00002146 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002147 {
anthony5330ae02012-03-20 14:17:01 +00002148 /* WARNING: this is both a image_info setting (already done)
2149 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002150
2151 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002152 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002153
anthonyd2cdc862011-10-07 14:07:17 +00002154 Note that +colorspace sets "undefined" or no effect on
2155 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002156 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002157 */
anthony92c93bd2012-03-19 14:02:47 +00002158 (void) TransformImageColorspace(_image,
2159 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2160 _exception);
anthony805a2d42011-09-25 08:25:12 +00002161 break;
2162 }
anthonyafa3dfc2012-03-03 11:31:30 +00002163 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002164 {
anthonydcf3a912012-03-22 14:33:17 +00002165 /* DEPRECIATED: The -/+level provides far more controlled form */
anthony92c93bd2012-03-19 14:02:47 +00002166 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002167 break;
2168 }
anthonyafa3dfc2012-03-03 11:31:30 +00002169 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002170 {
2171 double
2172 black_point,
2173 white_point;
2174
2175 MagickStatusType
2176 flags;
2177
anthonyebb73a22012-03-22 14:25:52 +00002178 if (IsGeometry(arg1) == MagickFalse)
2179 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002180 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002181 black_point=geometry_info.rho;
2182 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2183 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002184 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002185 black_point*=(double) _image->columns*_image->rows/100.0;
2186 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002187 }
anthony92c93bd2012-03-19 14:02:47 +00002188 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002189 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002190 (void) ContrastStretchImage(_image,black_point,white_point,
2191 _exception);
anthony805a2d42011-09-25 08:25:12 +00002192 break;
2193 }
anthonyafa3dfc2012-03-03 11:31:30 +00002194 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002195 {
2196 KernelInfo
2197 *kernel_info;
2198
anthonyfd706f92012-01-19 04:22:02 +00002199 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002200 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002201 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +00002202 /* kernel_info->bias=_image->bias; -- FUTURE: check this path! */
anthony92c93bd2012-03-19 14:02:47 +00002203 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002204 kernel_info=DestroyKernelInfo(kernel_info);
2205 break;
2206 }
anthonyafa3dfc2012-03-03 11:31:30 +00002207 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002208 {
anthony31f1bf72012-01-30 12:37:22 +00002209 /* WARNING: This can generate multiple images! */
anthonyebb73a22012-03-22 14:25:52 +00002210 if (IsGeometry(arg1) == MagickFalse)
2211 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002212 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002213 break;
2214 }
anthonyafa3dfc2012-03-03 11:31:30 +00002215 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002216 {
anthonyebb73a22012-03-22 14:25:52 +00002217 if (IsGeometry(arg1) == MagickFalse)
2218 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002219 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2220 _exception);
anthony805a2d42011-09-25 08:25:12 +00002221 break;
2222 }
anthonyebb73a22012-03-22 14:25:52 +00002223 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002224 }
2225 case 'd':
2226 {
anthonyafa3dfc2012-03-03 11:31:30 +00002227 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002228 {
2229 StringInfo
2230 *passkey;
2231
anthony92c93bd2012-03-19 14:02:47 +00002232 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002233 if (passkey == (StringInfo *) NULL)
2234 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2235
2236 (void) PasskeyDecipherImage(_image,passkey,_exception);
2237 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002238 break;
2239 }
anthonyafa3dfc2012-03-03 11:31:30 +00002240 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002241 {
anthony92c93bd2012-03-19 14:02:47 +00002242 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002243 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002244
anthonydcf510d2011-10-30 13:51:40 +00002245 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2246 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002247
anthonyfd706f92012-01-19 04:22:02 +00002248 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002249 */
anthony92c93bd2012-03-19 14:02:47 +00002250 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002251 break;
2252 }
anthonyafa3dfc2012-03-03 11:31:30 +00002253 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002254 {
2255 double
2256 threshold;
2257
anthonyebb73a22012-03-22 14:25:52 +00002258 if (IfNormalOp) {
2259 if (IsGeometry(arg1) == MagickFalse)
2260 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002261 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002262 }
anthonyafa3dfc2012-03-03 11:31:30 +00002263 else
2264 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002265 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002266 break;
2267 }
anthonyafa3dfc2012-03-03 11:31:30 +00002268 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002269 {
anthony92c93bd2012-03-19 14:02:47 +00002270 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002271 break;
2272 }
anthonyafa3dfc2012-03-03 11:31:30 +00002273 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002274 {
2275 char
2276 *args,
2277 token[MaxTextExtent];
2278
2279 const char
2280 *p;
2281
anthony805a2d42011-09-25 08:25:12 +00002282 double
2283 *arguments;
2284
2285 register ssize_t
2286 x;
2287
2288 size_t
2289 number_arguments;
2290
anthony2a0ec8c2012-03-24 04:35:56 +00002291 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2292 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002293 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2294 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002295 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002296 {
anthony80c37752012-01-16 01:03:11 +00002297 double
2298 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002299 /* Special Case - Argument is actually a resize geometry!
2300 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002301 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002302 Roll into a resize special operator */
anthonyebb73a22012-03-22 14:25:52 +00002303 if (IsGeometry(arg2) == MagickFalse)
2304 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2305 option,arg2);
2306 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002307 resize_args[0]=(double) geometry.width;
2308 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002309 new_image=DistortImage(_image,(DistortImageMethod) parse,
2310 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002311 break;
2312 }
anthonyfd706f92012-01-19 04:22:02 +00002313 /* handle percent arguments */
anthonyebb73a22012-03-22 14:25:52 +00002314 args=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00002315 if (args == (char *) NULL)
2316 break;
anthonyfd706f92012-01-19 04:22:02 +00002317 /* convert arguments into an array of doubles
2318 FUTURE: make this a separate function.
2319 Also make use of new 'sentinal' feature to avoid need for
2320 tokenization.
2321 */
anthony805a2d42011-09-25 08:25:12 +00002322 p=(char *) args;
2323 for (x=0; *p != '\0'; x++)
2324 {
2325 GetMagickToken(p,&p,token);
2326 if (*token == ',')
2327 GetMagickToken(p,&p,token);
2328 }
2329 number_arguments=(size_t) x;
2330 arguments=(double *) AcquireQuantumMemory(number_arguments,
2331 sizeof(*arguments));
2332 if (arguments == (double *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002333 CLIWandExceptionBreak(ResourceLimitFatalError,
2334 "MemoryAllocationFailed",option);
anthony805a2d42011-09-25 08:25:12 +00002335 (void) ResetMagickMemory(arguments,0,number_arguments*
anthonyebb73a22012-03-22 14:25:52 +00002336 sizeof(*arguments));
anthony805a2d42011-09-25 08:25:12 +00002337 p=(char *) args;
2338 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2339 {
2340 GetMagickToken(p,&p,token);
2341 if (*token == ',')
2342 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002343 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002344 }
2345 args=DestroyString(args);
anthony2a0ec8c2012-03-24 04:35:56 +00002346 new_image=DistortImage(_image,(DistortImageMethod) parse,
2347 number_arguments,arguments,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002348 arguments=(double *) RelinquishMagickMemory(arguments);
2349 break;
2350 }
anthonyafa3dfc2012-03-03 11:31:30 +00002351 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002352 {
anthony92c93bd2012-03-19 14:02:47 +00002353 (void) CloneString(&_draw_info->primitive,arg1);
2354 (void) DrawImage(_image,_draw_info,_exception);
2355 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002356 break;
2357 }
anthonyebb73a22012-03-22 14:25:52 +00002358 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002359 }
2360 case 'e':
2361 {
anthonyafa3dfc2012-03-03 11:31:30 +00002362 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002363 {
anthony2a0ec8c2012-03-24 04:35:56 +00002364 if (IsGeometry(arg1) == MagickFalse)
2365 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002366 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002367 if ((flags & SigmaValue) == 0)
2368 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002369 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2370 _exception);
anthony805a2d42011-09-25 08:25:12 +00002371 break;
2372 }
anthonyafa3dfc2012-03-03 11:31:30 +00002373 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002374 {
anthony2a0ec8c2012-03-24 04:35:56 +00002375 if (IsGeometry(arg1) == MagickFalse)
2376 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002377 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002378 if ((flags & SigmaValue) == 0)
2379 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002380 new_image=EmbossImage(_image,geometry_info.rho,
2381 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002382 break;
2383 }
anthonyafa3dfc2012-03-03 11:31:30 +00002384 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002385 {
2386 StringInfo
2387 *passkey;
2388
anthony92c93bd2012-03-19 14:02:47 +00002389 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002390 if (passkey != (StringInfo *) NULL)
2391 {
anthony92c93bd2012-03-19 14:02:47 +00002392 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002393 passkey=DestroyStringInfo(passkey);
2394 }
2395 break;
2396 }
anthonyafa3dfc2012-03-03 11:31:30 +00002397 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002398 {
anthony92c93bd2012-03-19 14:02:47 +00002399 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002400 break;
2401 }
anthonyafa3dfc2012-03-03 11:31:30 +00002402 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002403 {
anthony92c93bd2012-03-19 14:02:47 +00002404 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002405 break;
2406 }
anthonyafa3dfc2012-03-03 11:31:30 +00002407 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002408 {
2409 double
2410 constant;
2411
anthony2a0ec8c2012-03-24 04:35:56 +00002412 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2413 if ( parse < 0 )
2414 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2415 option,arg1);
2416 if (IsGeometry(arg2) == MagickFalse)
2417 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002418 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002419 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2420 _exception);
anthony805a2d42011-09-25 08:25:12 +00002421 break;
2422 }
anthonyafa3dfc2012-03-03 11:31:30 +00002423 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002424 {
anthony2a0ec8c2012-03-24 04:35:56 +00002425 if (IsGeometry(arg1) == MagickFalse)
2426 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002427 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002428 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002429 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002430 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002431 geometry.height=_image->rows;
2432 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002433 break;
2434 }
anthonyebb73a22012-03-22 14:25:52 +00002435 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002436 }
2437 case 'f':
2438 {
anthonyafa3dfc2012-03-03 11:31:30 +00002439 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002440 {
anthony31f1bf72012-01-30 12:37:22 +00002441 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002442 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002443 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002444 break;
2445 }
anthony92c93bd2012-03-19 14:02:47 +00002446 (void) SetImageArtifact(_image,"identify:features","true");
2447 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002448 break;
2449 }
anthonyafa3dfc2012-03-03 11:31:30 +00002450 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002451 {
anthony92c93bd2012-03-19 14:02:47 +00002452 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002453 break;
2454 }
anthonyafa3dfc2012-03-03 11:31:30 +00002455 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002456 {
anthony92c93bd2012-03-19 14:02:47 +00002457 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002458 break;
2459 }
anthonyafa3dfc2012-03-03 11:31:30 +00002460 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002461 {
2462 PixelInfo
2463 target;
2464
anthony2a0ec8c2012-03-24 04:35:56 +00002465 if (IsGeometry(arg1) == MagickFalse)
2466 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002467 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2468 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2469 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2470 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002471 break;
2472 }
anthonyafa3dfc2012-03-03 11:31:30 +00002473 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002474 {
2475 FrameInfo
2476 frame_info;
2477
anthony31f1bf72012-01-30 12:37:22 +00002478 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002479 compose;
2480
2481 const char*
2482 value;
2483
anthony92c93bd2012-03-19 14:02:47 +00002484 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002485 if (value != (const char *) NULL)
2486 compose=(CompositeOperator) ParseCommandOption(
2487 MagickComposeOptions,MagickFalse,value);
2488 else
anthony92c93bd2012-03-19 14:02:47 +00002489 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002490
anthony2a0ec8c2012-03-24 04:35:56 +00002491 if (IsGeometry(arg1) == MagickFalse)
2492 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002493 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002494 frame_info.width=geometry.width;
2495 frame_info.height=geometry.height;
2496 if ((flags & HeightValue) == 0)
2497 frame_info.height=geometry.width;
2498 frame_info.outer_bevel=geometry.x;
2499 frame_info.inner_bevel=geometry.y;
2500 frame_info.x=(ssize_t) frame_info.width;
2501 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002502 frame_info.width=_image->columns+2*frame_info.width;
2503 frame_info.height=_image->rows+2*frame_info.height;
2504 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002505 break;
2506 }
anthonyafa3dfc2012-03-03 11:31:30 +00002507 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002508 {
2509 char
2510 *arguments,
2511 token[MaxTextExtent];
2512
2513 const char
2514 *p;
2515
2516 double
2517 *parameters;
2518
anthony805a2d42011-09-25 08:25:12 +00002519 register ssize_t
2520 x;
2521
2522 size_t
2523 number_parameters;
2524
cristy947cb4c2011-10-20 18:41:46 +00002525 /*
2526 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002527 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002528 */
anthony2a0ec8c2012-03-24 04:35:56 +00002529 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2530 if ( parse < 0 )
2531 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2532 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002533 arguments=InterpretImageProperties(_image_info,_image,arg2,
2534 _exception);
anthony805a2d42011-09-25 08:25:12 +00002535 if (arguments == (char *) NULL)
anthony2a0ec8c2012-03-24 04:35:56 +00002536 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony805a2d42011-09-25 08:25:12 +00002537 p=(char *) arguments;
2538 for (x=0; *p != '\0'; x++)
2539 {
2540 GetMagickToken(p,&p,token);
2541 if (*token == ',')
2542 GetMagickToken(p,&p,token);
2543 }
2544 number_parameters=(size_t) x;
2545 parameters=(double *) AcquireQuantumMemory(number_parameters,
2546 sizeof(*parameters));
2547 if (parameters == (double *) NULL)
2548 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002549 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002550 (void) ResetMagickMemory(parameters,0,number_parameters*
2551 sizeof(*parameters));
2552 p=(char *) arguments;
anthony2a0ec8c2012-03-24 04:35:56 +00002553 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++) {
anthony805a2d42011-09-25 08:25:12 +00002554 GetMagickToken(p,&p,token);
2555 if (*token == ',')
2556 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002557 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002558 }
2559 arguments=DestroyString(arguments);
anthony2a0ec8c2012-03-24 04:35:56 +00002560 (void) FunctionImage(_image,(MagickFunction)parse,number_parameters,
2561 parameters,_exception);
anthony805a2d42011-09-25 08:25:12 +00002562 parameters=(double *) RelinquishMagickMemory(parameters);
2563 break;
2564 }
anthonyebb73a22012-03-22 14:25:52 +00002565 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002566 }
2567 case 'g':
2568 {
anthonyafa3dfc2012-03-03 11:31:30 +00002569 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002570 {
anthonyfe1aa782012-03-24 13:43:04 +00002571 if (IsGeometry(arg1) == MagickFalse)
2572 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafa3dfc2012-03-03 11:31:30 +00002573 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002574 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2575 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002576 else
anthony92c93bd2012-03-19 14:02:47 +00002577 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002578 break;
2579 }
anthonyafa3dfc2012-03-03 11:31:30 +00002580 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2581 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002582 {
anthonyfe1aa782012-03-24 13:43:04 +00002583 if (IsGeometry(arg1) == MagickFalse)
2584 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002585 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002586 if ((flags & SigmaValue) == 0)
2587 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002588 new_image=GaussianBlurImage(_image,geometry_info.rho,
2589 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002590 break;
2591 }
anthonyafa3dfc2012-03-03 11:31:30 +00002592 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002593 {
anthonyfd706f92012-01-19 04:22:02 +00002594 /*
anthony31f1bf72012-01-30 12:37:22 +00002595 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002596 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002597 FUTURE: Why if no 'offset' does this resize ALL images?
2598 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002599 */
anthonyafa3dfc2012-03-03 11:31:30 +00002600 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002601 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002602 if (_image->geometry != (char *) NULL)
2603 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002604 break;
2605 }
anthonyfe1aa782012-03-24 13:43:04 +00002606 if (IsGeometry(arg1) == MagickFalse)
2607 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002608 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002609 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002610 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002611 else
anthony92c93bd2012-03-19 14:02:47 +00002612 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002613 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002614 break;
2615 }
anthonyebb73a22012-03-22 14:25:52 +00002616 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002617 }
2618 case 'h':
2619 {
anthonyafa3dfc2012-03-03 11:31:30 +00002620 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002621 {
anthony92c93bd2012-03-19 14:02:47 +00002622 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002623 break;
2624 }
anthonyebb73a22012-03-22 14:25:52 +00002625 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002626 }
2627 case 'i':
2628 {
anthonyafa3dfc2012-03-03 11:31:30 +00002629 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002630 {
anthony31f1bf72012-01-30 12:37:22 +00002631 const char
2632 *format,
anthony805a2d42011-09-25 08:25:12 +00002633 *text;
2634
anthony92c93bd2012-03-19 14:02:47 +00002635 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002636 if (format == (char *) NULL)
2637 {
anthony92c93bd2012-03-19 14:02:47 +00002638 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2639 _exception);
anthony805a2d42011-09-25 08:25:12 +00002640 break;
2641 }
anthony92c93bd2012-03-19 14:02:47 +00002642 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002643 if (text == (char *) NULL)
2644 break;
2645 (void) fputs(text,stdout);
2646 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002647 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002648 break;
2649 }
anthonyafa3dfc2012-03-03 11:31:30 +00002650 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002651 {
anthonyfe1aa782012-03-24 13:43:04 +00002652 if (IsGeometry(arg1) == MagickFalse)
2653 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002654 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002655 new_image=ImplodeImage(_image,geometry_info.rho,
2656 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002657 break;
2658 }
anthonyafa3dfc2012-03-03 11:31:30 +00002659 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002660 {
anthonyfe1aa782012-03-24 13:43:04 +00002661 /* FUTURE: New to IMv7
2662 Roll into a resize special operator */
2663 if (IsGeometry(arg1) == MagickFalse)
2664 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002665 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2666 new_image=InterpolativeResizeImage(_image,geometry.width,
2667 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002668 break;
2669 }
anthonyebb73a22012-03-22 14:25:52 +00002670 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002671 }
2672 case 'l':
2673 {
anthonyafa3dfc2012-03-03 11:31:30 +00002674 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002675 {
anthonyfe1aa782012-03-24 13:43:04 +00002676 if (IsGeometry(arg1) == MagickFalse)
2677 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002678 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002679 if ((flags & PercentValue) != 0)
2680 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002681 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002682 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002683 _exception);
anthony805a2d42011-09-25 08:25:12 +00002684 break;
2685 }
anthonyafa3dfc2012-03-03 11:31:30 +00002686 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002687 {
2688 MagickRealType
2689 black_point,
2690 gamma,
2691 white_point;
2692
2693 MagickStatusType
2694 flags;
2695
anthonyfe1aa782012-03-24 13:43:04 +00002696 if (IsGeometry(arg1) == MagickFalse)
2697 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002698 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002699 black_point=geometry_info.rho;
2700 white_point=(MagickRealType) QuantumRange;
2701 if ((flags & SigmaValue) != 0)
2702 white_point=geometry_info.sigma;
2703 gamma=1.0;
2704 if ((flags & XiValue) != 0)
2705 gamma=geometry_info.xi;
2706 if ((flags & PercentValue) != 0)
2707 {
2708 black_point*=(MagickRealType) (QuantumRange/100.0);
2709 white_point*=(MagickRealType) (QuantumRange/100.0);
2710 }
2711 if ((flags & SigmaValue) == 0)
2712 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002713 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002714 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002715 else
anthony92c93bd2012-03-19 14:02:47 +00002716 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002717 break;
2718 }
anthonyafa3dfc2012-03-03 11:31:30 +00002719 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002720 {
2721 char
2722 token[MaxTextExtent];
2723
2724 const char
2725 *p;
2726
2727 PixelInfo
2728 black_point,
2729 white_point;
2730
anthonyfd706f92012-01-19 04:22:02 +00002731 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002732 GetMagickToken(p,&p,token); /* get black point color */
2733 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002734 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002735 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002736 else
cristy269c9412011-10-13 23:41:15 +00002737 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002738 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002739 if (isalpha((int) token[0]) || (token[0] == '#'))
2740 GetMagickToken(p,&p,token);
2741 if (*token == '\0')
2742 white_point=black_point; /* set everything to that color */
2743 else
2744 {
2745 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2746 GetMagickToken(p,&p,token); /* Get white point color. */
2747 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002748 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002749 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002750 else
cristy269c9412011-10-13 23:41:15 +00002751 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002752 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002753 }
anthony92c93bd2012-03-19 14:02:47 +00002754 (void) LevelImageColors(_image,&black_point,&white_point,
2755 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002756 break;
2757 }
anthonyafa3dfc2012-03-03 11:31:30 +00002758 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002759 {
2760 double
2761 black_point,
2762 white_point;
2763
2764 MagickStatusType
2765 flags;
2766
anthonyfe1aa782012-03-24 13:43:04 +00002767 if (IsGeometry(arg1) == MagickFalse)
2768 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002769 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002770 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002771 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002772 if ((flags & SigmaValue) != 0)
2773 white_point=geometry_info.sigma;
2774 if ((flags & PercentValue) != 0)
2775 {
anthony92c93bd2012-03-19 14:02:47 +00002776 black_point*=(double) _image->columns*_image->rows/100.0;
2777 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002778 }
2779 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002780 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002781 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002782 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002783 break;
2784 }
anthonyafa3dfc2012-03-03 11:31:30 +00002785 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002786 {
anthonyfe1aa782012-03-24 13:43:04 +00002787 /* FUTURE: Roll into a resize special operator */
2788 if (IsGeometry(arg1) == MagickFalse)
2789 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002790 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002791 if ((flags & XValue) == 0)
2792 geometry.x=1;
2793 if ((flags & YValue) == 0)
2794 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002795 new_image=LiquidRescaleImage(_image,geometry.width,
2796 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002797 break;
2798 }
anthonyafa3dfc2012-03-03 11:31:30 +00002799 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002800 {
anthony92c93bd2012-03-19 14:02:47 +00002801 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002802 break;
2803 }
anthonyebb73a22012-03-22 14:25:52 +00002804 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002805 }
2806 case 'm':
2807 {
anthonyafa3dfc2012-03-03 11:31:30 +00002808 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002809 {
2810 Image
2811 *remap_image;
2812
anthony31f1bf72012-01-30 12:37:22 +00002813 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002814 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002815 if (remap_image == (Image *) NULL)
2816 break;
anthony92c93bd2012-03-19 14:02:47 +00002817 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002818 remap_image=DestroyImage(remap_image);
2819 break;
2820 }
anthonyafa3dfc2012-03-03 11:31:30 +00002821 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002822 {
2823 Image
2824 *mask;
2825
anthonyafa3dfc2012-03-03 11:31:30 +00002826 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002827 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002828 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002829 break;
2830 }
anthony5330ae02012-03-20 14:17:01 +00002831 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002832 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002833 if (mask == (Image *) NULL)
2834 break;
anthony92c93bd2012-03-19 14:02:47 +00002835 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002836 mask=DestroyImage(mask);
2837 break;
2838 }
anthonyafa3dfc2012-03-03 11:31:30 +00002839 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002840 {
anthony31f1bf72012-01-30 12:37:22 +00002841 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002842 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2843 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002844 break;
2845 }
anthonya3ef4ed2012-03-17 06:52:53 +00002846 if (LocaleCompare("median",option+1) == 0)
2847 {
2848 /* DEPRECIATED - use -statistic Median */
anthony7bc87992012-03-25 02:32:51 +00002849 if (IsGeometry(arg1) == MagickFalse)
2850 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya3ef4ed2012-03-17 06:52:53 +00002851 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2852 break;
2853 }
anthonyafa3dfc2012-03-03 11:31:30 +00002854 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002855 {
anthony7bc87992012-03-25 02:32:51 +00002856 if (IsGeometry(arg1) == MagickFalse)
2857 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002858 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002859 if ((flags & SigmaValue) == 0)
2860 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002861 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2862 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002863 break;
2864 }
anthonyafa3dfc2012-03-03 11:31:30 +00002865 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002866 {
anthony7bc87992012-03-25 02:32:51 +00002867 if (IsGeometry(arg1) == MagickFalse)
2868 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002869 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002870 break;
2871 }
anthonyafa3dfc2012-03-03 11:31:30 +00002872 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002873 {
anthony92c93bd2012-03-19 14:02:47 +00002874 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002875 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002876 break;
2877 }
anthonyafa3dfc2012-03-03 11:31:30 +00002878 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002879 {
anthony92c93bd2012-03-19 14:02:47 +00002880 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002881 break;
2882 }
anthonyafa3dfc2012-03-03 11:31:30 +00002883 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002884 {
2885 char
2886 token[MaxTextExtent];
2887
2888 const char
2889 *p;
2890
2891 KernelInfo
2892 *kernel;
2893
anthony805a2d42011-09-25 08:25:12 +00002894 ssize_t
2895 iterations;
2896
anthonyfd706f92012-01-19 04:22:02 +00002897 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002898 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002899 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2900 if ( parse < 0 )
2901 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2902 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002903 iterations=1L;
2904 GetMagickToken(p,&p,token);
2905 if ((*p == ':') || (*p == ','))
2906 GetMagickToken(p,&p,token);
2907 if ((*p != '\0'))
2908 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002909 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002910 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002911 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2912 option,arg2);
2913 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2914 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002915 kernel=DestroyKernelInfo(kernel);
2916 break;
2917 }
anthonyafa3dfc2012-03-03 11:31:30 +00002918 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002919 {
anthony7bc87992012-03-25 02:32:51 +00002920 if (IsGeometry(arg1) == MagickFalse)
2921 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002922 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002923 if ((flags & SigmaValue) == 0)
2924 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002925 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002926 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002927 break;
2928 }
anthonyebb73a22012-03-22 14:25:52 +00002929 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002930 }
2931 case 'n':
2932 {
anthonyafa3dfc2012-03-03 11:31:30 +00002933 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002934 {
anthony92c93bd2012-03-19 14:02:47 +00002935 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002936 break;
2937 }
anthonyafa3dfc2012-03-03 11:31:30 +00002938 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002939 {
anthonyafa3dfc2012-03-03 11:31:30 +00002940 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002941 {
anthony7bc87992012-03-25 02:32:51 +00002942 if (IsGeometry(arg1) == MagickFalse)
2943 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002944 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002945 if ((flags & SigmaValue) == 0)
2946 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002947 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2948 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002949 }
2950 else
2951 {
anthony31f1bf72012-01-30 12:37:22 +00002952 double
2953 attenuate;
2954
2955 const char*
2956 value;
2957
anthony7bc87992012-03-25 02:32:51 +00002958 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2959 if ( parse < 0 )
2960 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2961 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002962 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002963 if (value != (const char *) NULL)
2964 attenuate=StringToDouble(value,(char **) NULL);
2965 else
2966 attenuate=1.0;
2967
anthony7bc87992012-03-25 02:32:51 +00002968 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2969 _exception);
anthony805a2d42011-09-25 08:25:12 +00002970 }
2971 break;
2972 }
anthonyafa3dfc2012-03-03 11:31:30 +00002973 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002974 {
anthony92c93bd2012-03-19 14:02:47 +00002975 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002976 break;
2977 }
anthonyebb73a22012-03-22 14:25:52 +00002978 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002979 }
2980 case 'o':
2981 {
anthonyafa3dfc2012-03-03 11:31:30 +00002982 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002983 {
2984 PixelInfo
2985 target;
2986
anthony92c93bd2012-03-19 14:02:47 +00002987 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2988 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2989 _exception);
anthony805a2d42011-09-25 08:25:12 +00002990 break;
2991 }
anthonyafa3dfc2012-03-03 11:31:30 +00002992 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002993 {
anthony92c93bd2012-03-19 14:02:47 +00002994 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002995 break;
2996 }
anthonyebb73a22012-03-22 14:25:52 +00002997 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002998 }
2999 case 'p':
3000 {
anthonyafa3dfc2012-03-03 11:31:30 +00003001 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003002 {
anthonyfd706f92012-01-19 04:22:02 +00003003 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003004 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
3005 _exception);
anthony805a2d42011-09-25 08:25:12 +00003006 break;
3007 }
anthonyafa3dfc2012-03-03 11:31:30 +00003008 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003009 {
cristye9e3d382011-12-14 01:50:13 +00003010 const char
3011 *caption;
3012
anthony805a2d42011-09-25 08:25:12 +00003013 double
3014 angle;
3015
anthony7bc87992012-03-25 02:32:51 +00003016 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00003017 RandomInfo
3018 *random_info;
anthony805a2d42011-09-25 08:25:12 +00003019
anthonyf42014d2012-03-25 09:53:06 +00003020 random_info=AcquireRandomInfo();
3021 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
3022 random_info=DestroyRandomInfo(random_info);
3023 }
anthony7bc87992012-03-25 02:32:51 +00003024 else {
anthonyf42014d2012-03-25 09:53:06 +00003025 if (IsGeometry(arg1) == MagickFalse)
3026 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3027 flags=ParseGeometry(arg1,&geometry_info);
3028 angle=geometry_info.rho;
3029 }
anthony92c93bd2012-03-19 14:02:47 +00003030 caption=GetImageProperty(_image,"caption",_exception);
3031 new_image=PolaroidImage(_image,_draw_info,caption,angle,
3032 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003033 break;
3034 }
anthonyafa3dfc2012-03-03 11:31:30 +00003035 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003036 {
anthony7bc87992012-03-25 02:32:51 +00003037 if (IsGeometry(arg1) == MagickFalse)
3038 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003039 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003040 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
3041 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00003042 break;
3043 }
anthonyafa3dfc2012-03-03 11:31:30 +00003044 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003045 {
anthony31f1bf72012-01-30 12:37:22 +00003046 /* FUTURE: should be a 'Genesis' option?
3047 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00003048 Why???
cristy947cb4c2011-10-20 18:41:46 +00003049 */
anthony7bc87992012-03-25 02:32:51 +00003050 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
3051 if ( parse < 0 )
3052 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
3053 option,arg1);
3054 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003055 break;
3056 }
anthonyafa3dfc2012-03-03 11:31:30 +00003057 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003058 {
3059 const char
3060 *name;
3061
3062 const StringInfo
3063 *profile;
3064
3065 Image
3066 *profile_image;
3067
3068 ImageInfo
3069 *profile_info;
3070
anthonyafa3dfc2012-03-03 11:31:30 +00003071 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003072 { /* Remove a profile from the _image. */
3073 (void) ProfileImage(_image,arg1,(const unsigned char *)
3074 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003075 break;
3076 }
anthony92c93bd2012-03-19 14:02:47 +00003077 /* Associate a profile with the _image. */
3078 profile_info=CloneImageInfo(_image_info);
3079 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003080 if (profile != (StringInfo *) NULL)
3081 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003082 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003083 profile_info=DestroyImageInfo(profile_info);
3084 if (profile_image == (Image *) NULL)
3085 {
3086 StringInfo
3087 *profile;
3088
anthony92c93bd2012-03-19 14:02:47 +00003089 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003090 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00003091 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00003092 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003093 if (profile != (StringInfo *) NULL)
3094 {
anthony92c93bd2012-03-19 14:02:47 +00003095 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003096 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003097 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003098 profile=DestroyStringInfo(profile);
3099 }
3100 profile_info=DestroyImageInfo(profile_info);
3101 break;
3102 }
3103 ResetImageProfileIterator(profile_image);
3104 name=GetNextImageProfile(profile_image);
3105 while (name != (const char *) NULL)
3106 {
3107 profile=GetImageProfile(profile_image,name);
3108 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003109 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3110 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003111 name=GetNextImageProfile(profile_image);
3112 }
3113 profile_image=DestroyImage(profile_image);
3114 break;
3115 }
anthonyebb73a22012-03-22 14:25:52 +00003116 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003117 }
anthony805a2d42011-09-25 08:25:12 +00003118 case 'r':
3119 {
anthonyafa3dfc2012-03-03 11:31:30 +00003120 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003121 {
anthonyf42014d2012-03-25 09:53:06 +00003122 if (IsGeometry(arg1) == MagickFalse)
3123 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003124 flags=ParseGeometry(arg1,&geometry_info);
cristyaa2c16c2012-03-25 22:21:35 +00003125 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003126 break;
3127 }
anthonyafa3dfc2012-03-03 11:31:30 +00003128 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003129 {
anthonyf42014d2012-03-25 09:53:06 +00003130 if (IsGeometry(arg1) == MagickFalse)
3131 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003132 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003133 if ((flags & SigmaValue) == 0)
3134 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00003135 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003136 break;
3137 }
anthonyafa3dfc2012-03-03 11:31:30 +00003138 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003139 {
anthonyf42014d2012-03-25 09:53:06 +00003140 if (IsGeometry(arg1) == MagickFalse)
3141 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003142 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003143 break;
3144 }
anthonyafa3dfc2012-03-03 11:31:30 +00003145 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003146 {
3147 Image
3148 *remap_image;
3149
anthony92c93bd2012-03-19 14:02:47 +00003150 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003151 if (remap_image == (Image *) NULL)
3152 break;
anthony92c93bd2012-03-19 14:02:47 +00003153 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003154 remap_image=DestroyImage(remap_image);
3155 break;
3156 }
anthonyafa3dfc2012-03-03 11:31:30 +00003157 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003158 {
anthonyafa3dfc2012-03-03 11:31:30 +00003159 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00003160 {
3161 if (IsGeometry(arg1) == MagickFalse)
3162 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3163 arg1);
3164 (void) ResetImagePage(_image,arg1);
3165 }
anthony31f1bf72012-01-30 12:37:22 +00003166 else
anthony92c93bd2012-03-19 14:02:47 +00003167 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003168 break;
3169 }
anthonyafa3dfc2012-03-03 11:31:30 +00003170 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003171 {
anthonyf46d4262012-03-26 03:30:34 +00003172 /* FUTURE: Roll into a resize special operation */
anthonyf42014d2012-03-25 09:53:06 +00003173 if (IsGeometry(arg1) == MagickFalse)
3174 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003175 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003176 if ((flags & SigmaValue) == 0)
3177 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003178 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003179 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003180 break;
3181 }
anthonyafa3dfc2012-03-03 11:31:30 +00003182 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003183 {
anthonyf42014d2012-03-25 09:53:06 +00003184 if (IsGeometry(arg1) == MagickFalse)
3185 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003186 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3187 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003188 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003189 break;
3190 }
anthonyafa3dfc2012-03-03 11:31:30 +00003191 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003192 {
anthonyf42014d2012-03-25 09:53:06 +00003193 if (IsGeometry(arg1) == MagickFalse)
3194 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003195 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3196 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003197 break;
3198 }
anthonyafa3dfc2012-03-03 11:31:30 +00003199 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003200 {
anthonyf42014d2012-03-25 09:53:06 +00003201 if (IsGeometry(arg1) == MagickFalse)
3202 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003203 if (strchr(arg1,'>') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003204 if (_image->columns <= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003205 break;
anthonyfd706f92012-01-19 04:22:02 +00003206 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003207 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003208 break;
anthonyfd706f92012-01-19 04:22:02 +00003209 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003210 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003211 break;
3212 }
anthonyebb73a22012-03-22 14:25:52 +00003213 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003214 }
3215 case 's':
3216 {
anthonyafa3dfc2012-03-03 11:31:30 +00003217 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003218 {
anthonyfe1aa782012-03-24 13:43:04 +00003219 /* FUTURE: Roll into a resize special operator */
anthonyf42014d2012-03-25 09:53:06 +00003220 if (IsGeometry(arg1) == MagickFalse)
3221 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003222 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3223 new_image=SampleImage(_image,geometry.width,geometry.height,
3224 _exception);
anthony805a2d42011-09-25 08:25:12 +00003225 break;
3226 }
anthonyafa3dfc2012-03-03 11:31:30 +00003227 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003228 {
anthonyfe1aa782012-03-24 13:43:04 +00003229 /* FUTURE: Roll into a resize special operator */
anthonyf42014d2012-03-25 09:53:06 +00003230 if (IsGeometry(arg1) == MagickFalse)
3231 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003232 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3233 new_image=ScaleImage(_image,geometry.width,geometry.height,
3234 _exception);
anthony805a2d42011-09-25 08:25:12 +00003235 break;
3236 }
anthonyf42014d2012-03-25 09:53:06 +00003237 if (LocaleCompare("segment",option+1) == 0)
3238 {
3239 if (IsGeometry(arg1) == MagickFalse)
3240 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3241 flags=ParseGeometry(arg1,&geometry_info);
3242 if ((flags & SigmaValue) == 0)
3243 geometry_info.sigma=1.0;
3244 (void) SegmentImage(_image,_image->colorspace,
3245 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3246 _exception);
3247 break;
3248 }
anthonyafa3dfc2012-03-03 11:31:30 +00003249 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003250 {
anthonyf42014d2012-03-25 09:53:06 +00003251 if (IsGeometry(arg1) == MagickFalse)
3252 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003253 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003254 if ((flags & PercentValue) != 0)
3255 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003256 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003257 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003258 break;
3259 }
anthonyafa3dfc2012-03-03 11:31:30 +00003260 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003261 {
anthony31f1bf72012-01-30 12:37:22 +00003262 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003263 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003264 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003265 break;
3266 }
anthonyafa3dfc2012-03-03 11:31:30 +00003267 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003268 {
anthonyf42014d2012-03-25 09:53:06 +00003269 if (IsGeometry(arg1) == MagickFalse)
3270 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3271 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3272 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003273 break;
3274 }
anthonyafa3dfc2012-03-03 11:31:30 +00003275 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003276 {
3277 char
3278 *value;
3279
anthonyf42014d2012-03-25 09:53:06 +00003280 if (IfPlusOp) {
anthonyfd706f92012-01-19 04:22:02 +00003281 if (LocaleNCompare(arg1,"registry:",9) == 0)
3282 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003283 else
anthony31f1bf72012-01-30 12:37:22 +00003284 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003285 {
anthony92c93bd2012-03-19 14:02:47 +00003286 (void) DeleteImageOption(_image_info,arg1+7);
3287 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003288 }
3289 else
anthony92c93bd2012-03-19 14:02:47 +00003290 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003291 break;
3292 }
anthonyf42014d2012-03-25 09:53:06 +00003293 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003294 if (value == (char *) NULL)
3295 break;
anthonyfd706f92012-01-19 04:22:02 +00003296 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003297 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003298 else
anthonyfd706f92012-01-19 04:22:02 +00003299 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003300 {
anthony92c93bd2012-03-19 14:02:47 +00003301 (void) SetImageOption(_image_info,arg1+7,value);
3302 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003303 }
3304 else
anthony92c93bd2012-03-19 14:02:47 +00003305 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003306 value=DestroyString(value);
3307 break;
3308 }
anthonyafa3dfc2012-03-03 11:31:30 +00003309 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003310 {
anthonyf42014d2012-03-25 09:53:06 +00003311 if (IsGeometry(arg1) == MagickFalse)
3312 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003313 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003314 if ((flags & SigmaValue) == 0)
3315 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003316 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3317 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003318 break;
3319 }
anthonyafa3dfc2012-03-03 11:31:30 +00003320 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003321 {
anthonyf42014d2012-03-25 09:53:06 +00003322 if (IsGeometry(arg1) == MagickFalse)
3323 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003324 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003325 if ((flags & SigmaValue) == 0)
3326 geometry_info.sigma=1.0;
3327 if ((flags & XiValue) == 0)
3328 geometry_info.xi=4.0;
3329 if ((flags & PsiValue) == 0)
3330 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003331 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3332 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3333 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003334 break;
3335 }
anthonyafa3dfc2012-03-03 11:31:30 +00003336 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003337 {
anthonyf42014d2012-03-25 09:53:06 +00003338 if (IsGeometry(arg1) == MagickFalse)
3339 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003340 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003341 if ((flags & SigmaValue) == 0)
3342 geometry_info.sigma=1.0;
3343 if ((flags & XiValue) == 0)
3344 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003345 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3346 _exception);
anthony805a2d42011-09-25 08:25:12 +00003347 break;
3348 }
anthonyafa3dfc2012-03-03 11:31:30 +00003349 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003350 {
anthonyf42014d2012-03-25 09:53:06 +00003351 if (IsGeometry(arg1) == MagickFalse)
3352 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003353 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3354 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003355 break;
3356 }
anthonyafa3dfc2012-03-03 11:31:30 +00003357 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003358 {
anthonyf42014d2012-03-25 09:53:06 +00003359 if (IsGeometry(arg1) == MagickFalse)
3360 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003361 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003362 if ((flags & SigmaValue) == 0)
3363 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003364 new_image=ShearImage(_image,geometry_info.rho,
3365 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003366 break;
3367 }
anthonyafa3dfc2012-03-03 11:31:30 +00003368 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003369 {
anthonyf42014d2012-03-25 09:53:06 +00003370 if (IsGeometry(arg1) == MagickFalse)
3371 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003372 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003373 if ((flags & SigmaValue) == 0)
3374 geometry_info.sigma=(double) QuantumRange/2.0;
3375 if ((flags & PercentValue) != 0)
3376 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3377 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003378 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003379 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003380 _exception);
anthony805a2d42011-09-25 08:25:12 +00003381 break;
3382 }
anthonyafa3dfc2012-03-03 11:31:30 +00003383 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003384 {
anthonyf42014d2012-03-25 09:53:06 +00003385 if (IsGeometry(arg1) == MagickFalse)
3386 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003387 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003388 if ((flags & SigmaValue) == 0)
3389 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003390 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003391 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003392 break;
3393 }
anthonyafa3dfc2012-03-03 11:31:30 +00003394 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003395 {
anthonyf42014d2012-03-25 09:53:06 +00003396 if (IsGeometry(arg1) == MagickFalse)
3397 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003398 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3399 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003400 break;
3401 }
anthonyafa3dfc2012-03-03 11:31:30 +00003402 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003403 {
anthony805a2d42011-09-25 08:25:12 +00003404 char
3405 *arguments;
3406
anthonyf42014d2012-03-25 09:53:06 +00003407 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3408 if ( parse < 0 )
3409 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3410 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003411 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003412 if (arguments == (char *) NULL)
anthonyf42014d2012-03-25 09:53:06 +00003413 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3414 new_image=SparseColorOption(_image,(SparseColorMethod)parse,
3415 arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003416 arguments=DestroyString(arguments);
3417 break;
3418 }
anthonyafa3dfc2012-03-03 11:31:30 +00003419 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003420 {
anthonyf42014d2012-03-25 09:53:06 +00003421 if (IsGeometry(arg1) == MagickFalse)
3422 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003423 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3424 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003425 break;
3426 }
anthonyafa3dfc2012-03-03 11:31:30 +00003427 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003428 {
anthonyf42014d2012-03-25 09:53:06 +00003429 if (IsGeometry(arg1) == MagickFalse)
3430 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003431 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003432 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3433 _exception);
anthony805a2d42011-09-25 08:25:12 +00003434 break;
3435 }
anthonyafa3dfc2012-03-03 11:31:30 +00003436 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003437 {
anthony7bc87992012-03-25 02:32:51 +00003438 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3439 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003440 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003441 option,arg1);
3442 if (IsGeometry(arg2) == MagickFalse)
3443 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00003444 (void) ParseGeometry(arg2,&geometry_info);
anthony7bc87992012-03-25 02:32:51 +00003445 new_image=StatisticImage(_image,(StatisticType)parse,
3446 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3447 _exception);
anthony805a2d42011-09-25 08:25:12 +00003448 break;
3449 }
anthonyafa3dfc2012-03-03 11:31:30 +00003450 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003451 {
anthony92c93bd2012-03-19 14:02:47 +00003452 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003453 break;
3454 }
anthonyafa3dfc2012-03-03 11:31:30 +00003455 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003456 {
anthonyf42014d2012-03-25 09:53:06 +00003457 if (IsGeometry(arg1) == MagickFalse)
3458 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003459 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003460 new_image=SwirlImage(_image,geometry_info.rho,
3461 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003462 break;
3463 }
anthonyebb73a22012-03-22 14:25:52 +00003464 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003465 }
3466 case 't':
3467 {
anthonyafa3dfc2012-03-03 11:31:30 +00003468 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003469 {
3470 double
3471 threshold;
3472
anthonyafa3dfc2012-03-03 11:31:30 +00003473 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003474 threshold=(double) QuantumRange/2;
3475 else
anthonyfd706f92012-01-19 04:22:02 +00003476 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003477 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003478 break;
3479 }
anthonyafa3dfc2012-03-03 11:31:30 +00003480 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003481 {
anthony92c93bd2012-03-19 14:02:47 +00003482 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3483 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3484 _exception);
anthony805a2d42011-09-25 08:25:12 +00003485 break;
3486 }
anthonyafa3dfc2012-03-03 11:31:30 +00003487 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003488 {
anthony92c93bd2012-03-19 14:02:47 +00003489 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003490 break;
3491 }
anthonyafa3dfc2012-03-03 11:31:30 +00003492 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003493 {
anthonya3ef4ed2012-03-17 06:52:53 +00003494 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony92c93bd2012-03-19 14:02:47 +00003495 new_image=AffineTransformImage(_image,&_draw_info->affine,
3496 _exception);
anthony805a2d42011-09-25 08:25:12 +00003497 break;
3498 }
anthonyafa3dfc2012-03-03 11:31:30 +00003499 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003500 {
3501 PixelInfo
3502 target;
3503
anthony92c93bd2012-03-19 14:02:47 +00003504 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3505 (void) TransparentPaintImage(_image,&target,(Quantum)
3506 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003507 break;
3508 }
anthonyafa3dfc2012-03-03 11:31:30 +00003509 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003510 {
anthony92c93bd2012-03-19 14:02:47 +00003511 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003512 break;
3513 }
anthonyafa3dfc2012-03-03 11:31:30 +00003514 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003515 {
anthony92c93bd2012-03-19 14:02:47 +00003516 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003517 break;
3518 }
anthonyafa3dfc2012-03-03 11:31:30 +00003519 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003520 {
anthony92c93bd2012-03-19 14:02:47 +00003521 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003522 break;
3523 }
anthonyafa3dfc2012-03-03 11:31:30 +00003524 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003525 {
anthonyab3a50c2011-10-27 11:48:57 +00003526 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003527 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003528 break;
3529 }
anthonyebb73a22012-03-22 14:25:52 +00003530 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003531 }
3532 case 'u':
3533 {
anthonyafa3dfc2012-03-03 11:31:30 +00003534 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003535 {
anthony31f1bf72012-01-30 12:37:22 +00003536 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthony24aa8822012-03-11 00:56:06 +00003537 /* FUTURE: This option is not documented!!!!! */
anthonyafa3dfc2012-03-03 11:31:30 +00003538 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003539 {
anthony92c93bd2012-03-19 14:02:47 +00003540 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003541 break;
3542 }
anthony92c93bd2012-03-19 14:02:47 +00003543 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3544 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003545 break;
3546 }
anthonyafa3dfc2012-03-03 11:31:30 +00003547 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003548 {
anthony92c93bd2012-03-19 14:02:47 +00003549 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003550 break;
3551 }
anthonyafa3dfc2012-03-03 11:31:30 +00003552 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003553 {
anthonyfd706f92012-01-19 04:22:02 +00003554 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003555 if ((flags & SigmaValue) == 0)
3556 geometry_info.sigma=1.0;
3557 if ((flags & XiValue) == 0)
3558 geometry_info.xi=1.0;
3559 if ((flags & PsiValue) == 0)
3560 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003561 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3562 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003563 break;
3564 }
anthonyebb73a22012-03-22 14:25:52 +00003565 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003566 }
3567 case 'v':
3568 {
anthonyafa3dfc2012-03-03 11:31:30 +00003569 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003570 {
anthonyafa3dfc2012-03-03 11:31:30 +00003571 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003572 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003573 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003574 */
anthony92c93bd2012-03-19 14:02:47 +00003575 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003576 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003577 break;
3578 }
anthonyafa3dfc2012-03-03 11:31:30 +00003579 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003580 {
anthonyfd706f92012-01-19 04:22:02 +00003581 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003582 if ((flags & SigmaValue) == 0)
3583 geometry_info.sigma=1.0;
3584 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003585 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003586 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003587 geometry_info.psi=0.1*_image->rows;
3588 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003589 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3590 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003591 break;
3592 }
anthonyebb73a22012-03-22 14:25:52 +00003593 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003594 }
3595 case 'w':
3596 {
anthonyafa3dfc2012-03-03 11:31:30 +00003597 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003598 {
anthonyfd706f92012-01-19 04:22:02 +00003599 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003600 if ((flags & SigmaValue) == 0)
3601 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003602 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3603 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003604 break;
3605 }
anthonyafa3dfc2012-03-03 11:31:30 +00003606 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003607 {
anthony92c93bd2012-03-19 14:02:47 +00003608 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003609 break;
3610 }
anthonyebb73a22012-03-22 14:25:52 +00003611 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003612 }
3613 default:
anthonyebb73a22012-03-22 14:25:52 +00003614 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003615 }
3616 /*
3617 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003618 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003619 */
3620 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003621 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003622
anthony31f1bf72012-01-30 12:37:22 +00003623 return;
anthony92c93bd2012-03-19 14:02:47 +00003624#undef _image_info
3625#undef _draw_info
3626#undef _quantize_info
3627#undef _image
3628#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003629#undef IfNormalOp
3630#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003631#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003632#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003633}
anthonyfd706f92012-01-19 04:22:02 +00003634
anthony43f425d2012-02-26 12:58:58 +00003635WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003636 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003637{
3638 size_t
anthony43f425d2012-02-26 12:58:58 +00003639 n,
anthony31f1bf72012-01-30 12:37:22 +00003640 i;
3641
anthony43f425d2012-02-26 12:58:58 +00003642 assert(cli_wand != (MagickCLI *) NULL);
3643 assert(cli_wand->signature == WandSignature);
3644 assert(cli_wand->wand.signature == WandSignature);
3645 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3646 if (cli_wand->wand.debug != MagickFalse)
3647 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003648
anthonyafa3dfc2012-03-03 11:31:30 +00003649#if !USE_WAND_METHODS
3650 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003651 i=0;
anthony43f425d2012-02-26 12:58:58 +00003652 n=GetImageListLength(cli_wand->wand.images);
3653 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003654 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003655 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003656 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003657 if ( cli_wand->wand.images->next == (Image *) NULL )
3658 break;
3659 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003660 }
anthony43f425d2012-02-26 12:58:58 +00003661 assert( i == n );
3662 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003663#else
3664 MagickResetIterator(&cli_wand->wand);
3665 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3666 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3667 MagickResetIterator(&cli_wand->wand);
3668#endif
anthony31f1bf72012-01-30 12:37:22 +00003669 return;
anthony805a2d42011-09-25 08:25:12 +00003670}
3671
3672/*
3673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3674% %
3675% %
3676% %
anthony43f425d2012-02-26 12:58:58 +00003677+ 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 +00003678% %
3679% %
3680% %
3681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3682%
anthony43f425d2012-02-26 12:58:58 +00003683% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003684% entire image list as a whole. The result is often a complete replacment
3685% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003686%
3687% The format of the MogrifyImage method is:
3688%
anthony43f425d2012-02-26 12:58:58 +00003689% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003690% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003691%
3692% A description of each parameter follows:
3693%
anthony43f425d2012-02-26 12:58:58 +00003694% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003695%
anthony36a8c2c2012-02-10 00:08:44 +00003696% o option: The option string for the operation
3697%
anthony31f1bf72012-01-30 12:37:22 +00003698% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003699%
anthonyfe1aa782012-03-24 13:43:04 +00003700% NOTE: only "limit" uses two arguments.
anthony8b10b462012-02-08 12:32:44 +00003701%
3702% Example usage...
3703%
anthonyafa3dfc2012-03-03 11:31:30 +00003704% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3705% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003706%
anthony24aa8822012-03-11 00:56:06 +00003707% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003708%
anthony43f425d2012-02-26 12:58:58 +00003709% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003710% argc,argv
3711% i=index in argv
3712%
anthony2052d272012-02-28 12:48:29 +00003713% option_info = GetCommandOptionInfo(argv[i]);
3714% count=option_info->type;
3715% option_type=option_info->flags;
3716%
3717% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003718% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003719% count>=1 ? argv[i+1] : (char *)NULL,
3720% count>=2 ? argv[i+2] : (char *)NULL );
3721% i += count+1;
3722%
anthony805a2d42011-09-25 08:25:12 +00003723*/
anthony43f425d2012-02-26 12:58:58 +00003724WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003725 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003726{
anthony2a0ec8c2012-03-24 04:35:56 +00003727 ssize_t
3728 parse;
3729
anthony31f1bf72012-01-30 12:37:22 +00003730 Image
3731 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003732
anthony92c93bd2012-03-19 14:02:47 +00003733#define _image_info (cli_wand->wand.image_info)
3734#define _images (cli_wand->wand.images)
3735#define _exception (cli_wand->wand.exception)
3736#define _draw_info (cli_wand->draw_info)
3737#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003738#define IfNormalOp (*option=='-')
3739#define IfPlusOp (*option!='-')
3740#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003741
anthony43f425d2012-02-26 12:58:58 +00003742 assert(cli_wand != (MagickCLI *) NULL);
3743 assert(cli_wand->signature == WandSignature);
3744 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003745 assert(_images != (Image *) NULL); /* _images must be present */
anthony43f425d2012-02-26 12:58:58 +00003746 if (cli_wand->wand.debug != MagickFalse)
3747 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003748
anthony92c93bd2012-03-19 14:02:47 +00003749 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003750
3751 new_images=NewImageList();
3752
anthonyafa3dfc2012-03-03 11:31:30 +00003753 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003754 {
3755 case 'a':
3756 {
anthonyafa3dfc2012-03-03 11:31:30 +00003757 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003758 {
anthony92c93bd2012-03-19 14:02:47 +00003759 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003760 break;
3761 }
anthonyafa3dfc2012-03-03 11:31:30 +00003762 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003763 {
anthony31f1bf72012-01-30 12:37:22 +00003764 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003765 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003766 break;
3767 }
anthonyebb73a22012-03-22 14:25:52 +00003768 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003769 }
3770 case 'c':
3771 {
cristy5f257b22012-03-07 00:27:29 +00003772 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003773 {
anthony92c93bd2012-03-19 14:02:47 +00003774 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003775 break;
3776 }
anthonyafa3dfc2012-03-03 11:31:30 +00003777 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003778 {
anthony805a2d42011-09-25 08:25:12 +00003779 Image
anthony31f1bf72012-01-30 12:37:22 +00003780 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003781
anthonyafa3dfc2012-03-03 11:31:30 +00003782 /* FUTURE - make this a compose option, and thus can be used
3783 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003784 _images.
cristy87c02f42012-02-24 00:19:10 +00003785 */
anthony92c93bd2012-03-19 14:02:47 +00003786 new_images=RemoveFirstImageFromList(&_images);
3787 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003788 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003789 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003790 break;
anthony92c93bd2012-03-19 14:02:47 +00003791 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003792 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003793 break;
3794 }
anthonyafa3dfc2012-03-03 11:31:30 +00003795 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003796 {
anthony92c93bd2012-03-19 14:02:47 +00003797 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003798 break;
3799 }
anthonyafa3dfc2012-03-03 11:31:30 +00003800 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003801 {
anthony43f425d2012-02-26 12:58:58 +00003802 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003803 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003804 break;
3805 }
anthonyafa3dfc2012-03-03 11:31:30 +00003806 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003807 {
3808 Image
3809 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003810 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003811
3812 RectangleInfo
3813 geometry;
3814
anthony31f1bf72012-01-30 12:37:22 +00003815 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003816 compose;
3817
3818 const char*
3819 value;
3820
anthony92c93bd2012-03-19 14:02:47 +00003821 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003822 if (value != (const char *) NULL)
3823 compose=(CompositeOperator) ParseCommandOption(
3824 MagickComposeOptions,MagickFalse,value);
3825 else
anthony31f1bf72012-01-30 12:37:22 +00003826 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003827
anthony92c93bd2012-03-19 14:02:47 +00003828 new_images=RemoveFirstImageFromList(&_images);
3829 source_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003830 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003831 if (source_image == (Image *) NULL)
3832 break;
anthonye8f56492012-02-12 12:39:02 +00003833
anthony31f1bf72012-01-30 12:37:22 +00003834 /* FUTURE - this should not be here! - should be part of -geometry */
3835 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003836 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003837
anthony31f1bf72012-01-30 12:37:22 +00003838 SetGeometry(source_image,&geometry);
3839 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3840 GravityAdjustGeometry(new_images->columns,new_images->rows,
3841 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003842
anthony92c93bd2012-03-19 14:02:47 +00003843 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003844 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003845 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003846 if ((compose == DisplaceCompositeOp) ||
3847 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003848 { /* Merge Y displacement into X displace/distort map. */
3849 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony92c93bd2012-03-19 14:02:47 +00003850 mask_image,0,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003851 mask_image=DestroyImage(mask_image);
3852 }
3853 else
3854 {
3855 /*
3856 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003857 */
anthony92c93bd2012-03-19 14:02:47 +00003858 (void) NegateImage(mask_image,MagickFalse,_exception);
3859 (void) SetImageMask(new_images,mask_image,_exception);
cristy1539afd2012-01-30 01:32:59 +00003860 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003861 }
3862 }
anthony31f1bf72012-01-30 12:37:22 +00003863 (void) CompositeImage(new_images,compose,source_image,geometry.x,
anthony92c93bd2012-03-19 14:02:47 +00003864 geometry.y,_exception);
3865 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003866 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003867 break;
3868 }
anthonyebb73a22012-03-22 14:25:52 +00003869 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003870 }
3871 case 'd':
3872 {
anthonyafa3dfc2012-03-03 11:31:30 +00003873 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003874 {
anthony31f1bf72012-01-30 12:37:22 +00003875 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003876 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003877 break;
3878 }
anthonyafa3dfc2012-03-03 11:31:30 +00003879 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003880 {
anthonyafa3dfc2012-03-03 11:31:30 +00003881 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003882 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003883 else
anthony92c93bd2012-03-19 14:02:47 +00003884 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003885 break;
3886 }
anthonyafa3dfc2012-03-03 11:31:30 +00003887 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003888 {
anthonyafa3dfc2012-03-03 11:31:30 +00003889 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003890 {
3891 const char
3892 *p;
3893
3894 size_t
3895 number_duplicates;
3896
anthonyebb73a22012-03-22 14:25:52 +00003897 if (IsGeometry(arg1) == MagickFalse)
3898 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3899 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003900 number_duplicates=(size_t) StringToLong(arg1);
3901 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003902 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003903 new_images=DuplicateImages(_images,number_duplicates,"-1",
3904 _exception);
anthony805a2d42011-09-25 08:25:12 +00003905 else
anthony92c93bd2012-03-19 14:02:47 +00003906 new_images=DuplicateImages(_images,number_duplicates,p,
3907 _exception);
anthony805a2d42011-09-25 08:25:12 +00003908 }
anthonyafa3dfc2012-03-03 11:31:30 +00003909 else
anthony92c93bd2012-03-19 14:02:47 +00003910 new_images=DuplicateImages(_images,1,"-1",_exception);
3911 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003912 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003913 break;
3914 }
anthonyebb73a22012-03-22 14:25:52 +00003915 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003916 }
3917 case 'e':
3918 {
anthonyafa3dfc2012-03-03 11:31:30 +00003919 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003920 {
anthony2a0ec8c2012-03-24 04:35:56 +00003921 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3922 if ( parse < 0 )
3923 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3924 option,arg1);
3925 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3926 _exception);
anthony805a2d42011-09-25 08:25:12 +00003927 break;
3928 }
anthonyebb73a22012-03-22 14:25:52 +00003929 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003930 }
3931 case 'f':
3932 {
anthonyafa3dfc2012-03-03 11:31:30 +00003933 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003934 {
anthony92c93bd2012-03-19 14:02:47 +00003935 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003936 break;
3937 }
anthonyafa3dfc2012-03-03 11:31:30 +00003938 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003939 {
anthony319dac62012-03-06 04:12:44 +00003940 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003941 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003942 break;
3943 }
anthonyafa3dfc2012-03-03 11:31:30 +00003944 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003945 {
anthony92c93bd2012-03-19 14:02:47 +00003946 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003947 break;
3948 }
anthonyebb73a22012-03-22 14:25:52 +00003949 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003950 }
3951 case 'h':
3952 {
anthonyafa3dfc2012-03-03 11:31:30 +00003953 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003954 {
anthony31f1bf72012-01-30 12:37:22 +00003955 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003956 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003957 */
anthony805a2d42011-09-25 08:25:12 +00003958 Image
anthony31f1bf72012-01-30 12:37:22 +00003959 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003960
anthony92c93bd2012-03-19 14:02:47 +00003961 new_images=RemoveFirstImageFromList(&_images);
3962 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003963 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003964 break;
anthony92c93bd2012-03-19 14:02:47 +00003965 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003966 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003967 break;
3968 }
anthonyebb73a22012-03-22 14:25:52 +00003969 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003970 }
3971 case 'i':
3972 {
anthonyafa3dfc2012-03-03 11:31:30 +00003973 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003974 {
3975 Image
anthony805a2d42011-09-25 08:25:12 +00003976 *magnitude_image,
3977 *phase_image;
3978
anthony92c93bd2012-03-19 14:02:47 +00003979 magnitude_image=RemoveFirstImageFromList(&_images);
3980 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003981 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003982 if (phase_image == (Image *) NULL)
3983 break;
3984 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003985 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003986 magnitude_image=DestroyImage(magnitude_image);
3987 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003988 break;
3989 }
anthonyafa3dfc2012-03-03 11:31:30 +00003990 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003991 {
3992 Image
anthony31f1bf72012-01-30 12:37:22 +00003993 *insert_image,
3994 *index_image;
3995
3996 ssize_t
3997 index;
anthony805a2d42011-09-25 08:25:12 +00003998
anthonyfe1aa782012-03-24 13:43:04 +00003999 if (IfNormalOp && IsGeometry(arg1) == MagickFalse)
4000 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004001 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004002 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004003 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004004 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004005 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004006 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004007 PrependImageToList(&_images,insert_image);
4008 else if (index == (ssize_t) GetImageListLength(_images))
4009 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004010 else
anthony43f425d2012-02-26 12:58:58 +00004011 {
anthony92c93bd2012-03-19 14:02:47 +00004012 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004013 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004014 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004015 InsertImageInList(&index_image,insert_image);
4016 }
anthony92c93bd2012-03-19 14:02:47 +00004017 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004018 break;
4019 }
anthonyebb73a22012-03-22 14:25:52 +00004020 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004021 }
4022 case 'l':
4023 {
anthonyafa3dfc2012-03-03 11:31:30 +00004024 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004025 {
anthonyfe1aa782012-03-24 13:43:04 +00004026 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4027 if ( parse < 0 )
4028 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4029 option,arg1);
4030 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004031 {
4032 case CoalesceLayer:
4033 {
anthony92c93bd2012-03-19 14:02:47 +00004034 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004035 break;
4036 }
4037 case CompareAnyLayer:
4038 case CompareClearLayer:
4039 case CompareOverlayLayer:
4040 default:
4041 {
anthonyfe1aa782012-03-24 13:43:04 +00004042 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
4043 _exception);
anthony805a2d42011-09-25 08:25:12 +00004044 break;
4045 }
4046 case MergeLayer:
4047 case FlattenLayer:
4048 case MosaicLayer:
4049 case TrimBoundsLayer:
4050 {
anthonyfe1aa782012-03-24 13:43:04 +00004051 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
4052 _exception);
anthony805a2d42011-09-25 08:25:12 +00004053 break;
4054 }
4055 case DisposeLayer:
4056 {
anthony92c93bd2012-03-19 14:02:47 +00004057 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004058 break;
4059 }
4060 case OptimizeImageLayer:
4061 {
anthony92c93bd2012-03-19 14:02:47 +00004062 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004063 break;
4064 }
4065 case OptimizePlusLayer:
4066 {
anthony92c93bd2012-03-19 14:02:47 +00004067 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004068 break;
4069 }
4070 case OptimizeTransLayer:
4071 {
anthony92c93bd2012-03-19 14:02:47 +00004072 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004073 break;
4074 }
4075 case RemoveDupsLayer:
4076 {
anthony92c93bd2012-03-19 14:02:47 +00004077 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004078 break;
4079 }
4080 case RemoveZeroLayer:
4081 {
anthony92c93bd2012-03-19 14:02:47 +00004082 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004083 break;
4084 }
4085 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004086 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004087 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004088 if (new_images == (Image *) NULL)
4089 break;
anthony92c93bd2012-03-19 14:02:47 +00004090 _images=DestroyImageList(_images);
4091 _images=OptimizeImageLayers(new_images,_exception);
4092 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004093 break;
4094 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004095 OptimizeImageTransparency(_images,_exception);
4096 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4097 _exception);
anthony805a2d42011-09-25 08:25:12 +00004098 break;
4099 }
4100 case CompositeLayer:
4101 {
anthony805a2d42011-09-25 08:25:12 +00004102 Image
4103 *source;
4104
4105 RectangleInfo
4106 geometry;
4107
anthony31f1bf72012-01-30 12:37:22 +00004108 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004109 compose;
4110
4111 const char*
4112 value;
4113
anthony92c93bd2012-03-19 14:02:47 +00004114 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004115 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004116 if (value != (const char *) NULL)
4117 compose=(CompositeOperator) ParseCommandOption(
4118 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004119
anthony31f1bf72012-01-30 12:37:22 +00004120 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004121 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004122 while (source != (Image *) NULL)
4123 {
4124 source=GetNextImageInList(source);
4125 if ((source != (Image *) NULL) &&
4126 (LocaleCompare(source->magick,"NULL") == 0))
4127 break;
4128 }
4129 if (source != (Image *) NULL)
4130 {
4131 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4132 (GetNextImageInList(source) == (Image *) NULL))
4133 source=(Image *) NULL;
4134 else
anthony31f1bf72012-01-30 12:37:22 +00004135 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004136 source=SplitImageList(source->previous);
4137 DeleteImageFromList(&source);
4138 }
4139 }
4140 if (source == (Image *) NULL)
4141 {
anthony92c93bd2012-03-19 14:02:47 +00004142 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004143 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004144 break;
4145 }
anthony31f1bf72012-01-30 12:37:22 +00004146 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004147 SetGeometry(_images,&geometry);
4148 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004149 geometry.width=source->page.width != 0 ?
4150 source->page.width : source->columns;
4151 geometry.height=source->page.height != 0 ?
4152 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004153 GravityAdjustGeometry(_images->page.width != 0 ?
4154 _images->page.width : _images->columns,
4155 _images->page.height != 0 ? _images->page.height :
4156 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004157
anthony31f1bf72012-01-30 12:37:22 +00004158 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004159 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4160 _exception);
anthony805a2d42011-09-25 08:25:12 +00004161 source=DestroyImageList(source);
4162 break;
4163 }
4164 }
anthony805a2d42011-09-25 08:25:12 +00004165 break;
4166 }
anthonyafa3dfc2012-03-03 11:31:30 +00004167 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00004168 {
4169 MagickSizeType
4170 limit;
4171
anthony72feaa62012-01-17 06:46:23 +00004172 limit=MagickResourceInfinity;
anthonyfe1aa782012-03-24 13:43:04 +00004173 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4174 if ( parse < 0 )
4175 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4176 option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004177 if (LocaleCompare("unlimited",arg2) != 0)
4178 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthonyfe1aa782012-03-24 13:43:04 +00004179 (void) SetMagickResourceLimit((ResourceType)parse,limit);
anthony72feaa62012-01-17 06:46:23 +00004180 break;
4181 }
anthonyebb73a22012-03-22 14:25:52 +00004182 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004183 }
4184 case 'm':
4185 {
anthonyafa3dfc2012-03-03 11:31:30 +00004186 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004187 {
anthony31f1bf72012-01-30 12:37:22 +00004188 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004189 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004190 break;
4191 }
anthonyafa3dfc2012-03-03 11:31:30 +00004192 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004193 {
4194 Image
4195 *morph_image;
4196
anthony7bc87992012-03-25 02:32:51 +00004197 if (IsGeometry(arg1) == MagickFalse)
4198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004199 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4200 _exception);
anthony805a2d42011-09-25 08:25:12 +00004201 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004202 break;
anthony92c93bd2012-03-19 14:02:47 +00004203 _images=DestroyImageList(_images);
4204 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004205 break;
4206 }
anthonyafa3dfc2012-03-03 11:31:30 +00004207 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004208 {
anthony319dac62012-03-06 04:12:44 +00004209 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00004210 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004211 break;
4212 }
anthonyebb73a22012-03-22 14:25:52 +00004213 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004214 }
4215 case 'p':
4216 {
anthonyafa3dfc2012-03-03 11:31:30 +00004217 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004218 {
4219 char
4220 *string;
4221
anthony92c93bd2012-03-19 14:02:47 +00004222 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004223 if (string == (char *) NULL)
4224 break;
4225 (void) FormatLocaleFile(stdout,"%s",string);
4226 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004227 break;
anthony805a2d42011-09-25 08:25:12 +00004228 }
anthonyafa3dfc2012-03-03 11:31:30 +00004229 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004230 {
4231 char
4232 **arguments;
4233
4234 int
4235 j,
4236 number_arguments;
4237
anthony31f1bf72012-01-30 12:37:22 +00004238 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004239 if (arguments == (char **) NULL)
4240 break;
anthony31f1bf72012-01-30 12:37:22 +00004241 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004242 {
4243 char
4244 breaker,
4245 quote,
4246 *token;
4247
4248 const char
4249 *arguments;
4250
4251 int
4252 next,
4253 status;
4254
4255 size_t
4256 length;
4257
4258 TokenInfo
4259 *token_info;
4260
4261 /*
anthony24aa8822012-03-11 00:56:06 +00004262 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004263 */
anthony31f1bf72012-01-30 12:37:22 +00004264 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004265 token=(char *) NULL;
4266 if (~length >= (MaxTextExtent-1))
4267 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4268 sizeof(*token));
4269 if (token == (char *) NULL)
4270 break;
4271 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004272 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004273 token_info=AcquireTokenInfo();
4274 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4275 "\"",'\0',&breaker,&next,&quote);
4276 token_info=DestroyTokenInfo(token_info);
4277 if (status == 0)
4278 {
4279 const char
4280 *argv;
4281
4282 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004283 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4284 _exception);
anthony805a2d42011-09-25 08:25:12 +00004285 }
4286 token=DestroyString(token);
4287 break;
4288 }
4289 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004290 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4291 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004292 for (j=0; j < number_arguments; j++)
4293 arguments[j]=DestroyString(arguments[j]);
4294 arguments=(char **) RelinquishMagickMemory(arguments);
4295 break;
4296 }
anthonyebb73a22012-03-22 14:25:52 +00004297 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004298 }
4299 case 'r':
4300 {
anthonyafa3dfc2012-03-03 11:31:30 +00004301 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004302 {
anthony92c93bd2012-03-19 14:02:47 +00004303 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004304 break;
4305 }
anthonyafa3dfc2012-03-03 11:31:30 +00004306 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004307 {
anthony92c93bd2012-03-19 14:02:47 +00004308 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004309 break;
4310 }
anthonyebb73a22012-03-22 14:25:52 +00004311 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004312 }
4313 case 's':
4314 {
anthonyafa3dfc2012-03-03 11:31:30 +00004315 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004316 {
4317 Image
4318 *smush_image;
4319
4320 ssize_t
4321 offset;
4322
anthonyf42014d2012-03-25 09:53:06 +00004323 if (IsGeometry(arg1) == MagickFalse)
4324 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004325 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004326 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004327 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004328 break;
anthony92c93bd2012-03-19 14:02:47 +00004329 _images=DestroyImageList(_images);
4330 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004331 break;
4332 }
anthonyafa3dfc2012-03-03 11:31:30 +00004333 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004334 {
4335 Image
4336 *p,
4337 *q,
4338 *swap;
4339
4340 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004341 index,
anthony805a2d42011-09-25 08:25:12 +00004342 swap_index;
4343
anthonyf42014d2012-03-25 09:53:06 +00004344 if (IsGeometry(arg1) == MagickFalse)
4345 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004346 index=-1;
4347 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004348 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004349 {
4350 GeometryInfo
4351 geometry_info;
4352
4353 MagickStatusType
4354 flags;
4355
4356 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004357 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004358 index=(ssize_t) geometry_info.rho;
4359 if ((flags & SigmaValue) != 0)
4360 swap_index=(ssize_t) geometry_info.sigma;
4361 }
anthony92c93bd2012-03-19 14:02:47 +00004362 p=GetImageFromList(_images,index);
4363 q=GetImageFromList(_images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004364 if ((p == (Image *) NULL) || (q == (Image *) NULL))
anthonyf42014d2012-03-25 09:53:06 +00004365 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004366 if (p == q)
anthonyf42014d2012-03-25 09:53:06 +00004367 break; /* same image - no-op - not an error */
anthony92c93bd2012-03-19 14:02:47 +00004368 swap=CloneImage(p,0,0,MagickTrue,_exception);
4369 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
anthony805a2d42011-09-25 08:25:12 +00004370 ReplaceImageInList(&q,swap);
anthony92c93bd2012-03-19 14:02:47 +00004371 _images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004372 break;
4373 }
anthonyebb73a22012-03-22 14:25:52 +00004374 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004375 }
4376 case 'w':
4377 {
anthonyafa3dfc2012-03-03 11:31:30 +00004378 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004379 {
4380 char
4381 key[MaxTextExtent];
4382
4383 Image
4384 *write_images;
4385
4386 ImageInfo
4387 *write_info;
4388
anthony31f1bf72012-01-30 12:37:22 +00004389 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004390 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004391 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004392 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004393 write_images=CloneImageList(_images,_exception);
4394 write_info=CloneImageInfo(_image_info);
4395 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004396 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004397 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004398 write_images=DestroyImageList(write_images);
4399 break;
4400 }
anthonyebb73a22012-03-22 14:25:52 +00004401 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004402 }
4403 default:
anthonyebb73a22012-03-22 14:25:52 +00004404 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004405 }
anthony31f1bf72012-01-30 12:37:22 +00004406 if (new_images == (Image *) NULL)
4407 return;
anthony805a2d42011-09-25 08:25:12 +00004408
anthony92c93bd2012-03-19 14:02:47 +00004409 if (_images != (Image *) NULL)
4410 _images=DestroyImageList(_images);
4411 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004412 return;
4413
anthony92c93bd2012-03-19 14:02:47 +00004414#undef _image_info
4415#undef _images
4416#undef _exception
4417#undef _draw_info
4418#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004419#undef IfNormalOp
4420#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004421#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004422}
anthony43f425d2012-02-26 12:58:58 +00004423
4424/*
4425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4426% %
4427% %
4428% %
4429+ C L I S p e c i a l O p e r a t i o n s %
4430% %
4431% %
4432% %
4433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4434%
4435% CLISpecialOption() Applies operations that may involve empty image lists
4436% and or stacks of image lists or image_info settings.
4437%
anthonyafa3dfc2012-03-03 11:31:30 +00004438% The classic operators of this type is -read, and image stack operators,
4439% which can be applied to empty image lists.
4440%
4441% Note: unlike other Operators, these may involve other special 'option'
4442% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004443%
4444% The format of the CLISpecialOption method is:
4445%
4446% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004447% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004448%
4449% A description of each parameter follows:
4450%
4451% o cli_wand: the main CLI Wand to use.
4452%
4453% o option: The special option (with any switch char) to process
4454%
anthony24aa8822012-03-11 00:56:06 +00004455% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004456%
anthony2052d272012-02-28 12:48:29 +00004457% Example Usage...
4458%
anthonyce8dcb32012-03-21 13:20:31 +00004459% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004460%
anthony24aa8822012-03-11 00:56:06 +00004461% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004462%
4463% cli_wand
4464% argc,argv
4465% i=index in argv
4466%
4467% option_info = GetCommandOptionInfo(argv[i]);
4468% count=option_info->type;
4469% option_type=option_info->flags;
4470%
4471% if ( (option_type & SpecialOptionFlag) != 0 )
4472% CLISpecialOperator(cli_wand,argv[i],
4473% count>=1 ? argv[i+1] : (char *)NULL);
4474% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004475%
4476*/
4477
anthony43f425d2012-02-26 12:58:58 +00004478WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004479 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004480{
anthony92c93bd2012-03-19 14:02:47 +00004481#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004482
4483 assert(cli_wand != (MagickCLI *) NULL);
4484 assert(cli_wand->signature == WandSignature);
4485 assert(cli_wand->wand.signature == WandSignature);
4486 if (cli_wand->wand.debug != MagickFalse)
4487 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4488
anthony24aa8822012-03-11 00:56:06 +00004489 if(cli_wand->wand.images != (Image *)NULL)
4490 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004491 _exception);
anthony24aa8822012-03-11 00:56:06 +00004492
anthonyce8dcb32012-03-21 13:20:31 +00004493 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
anthonyf42014d2012-03-25 09:53:06 +00004494 /* link image and setting stacks - option is itself saved on stack! */
anthonyce8dcb32012-03-21 13:20:31 +00004495 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4496 *option == '-' ? "true" : (char *) NULL);
4497 return;
4498 }
4499 if (LocaleCompare("(",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004500 /* stack 'push' images */
4501 Stack
4502 *node;
4503
4504 size_t
4505 size;
4506
anthony43f425d2012-02-26 12:58:58 +00004507 size=0;
4508 node=cli_wand->image_list_stack;
4509 for ( ; node != (Stack *)NULL; node=node->next)
4510 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004511 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004512 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004513 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4514 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004515 CLIWandExceptionReturn(ResourceLimitFatalError,
4516 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004517 node->data = (void *)cli_wand->wand.images;
4518 cli_wand->wand.images = NewImageList();
4519 node->next = cli_wand->image_list_stack;
4520 cli_wand->image_list_stack = node;
4521
4522 /* handle respect-parenthesis */
anthonyf42014d2012-03-25 09:53:06 +00004523 if (IsMagickTrue(GetImageOption(cli_wand->wand.image_info,
anthonyce8dcb32012-03-21 13:20:31 +00004524 "respect-parenthesis")) != MagickFalse )
anthonyf42014d2012-03-25 09:53:06 +00004525 option="{"; /* fall-thru so as to push image settings too */
anthony43f425d2012-02-26 12:58:58 +00004526 else
4527 return;
4528 }
anthonyce8dcb32012-03-21 13:20:31 +00004529 if (LocaleCompare("{",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004530 /* stack 'push' of image_info settings */
4531 Stack
4532 *node;
4533
4534 size_t
4535 size;
4536
4537 size=0;
4538 node=cli_wand->image_info_stack;
4539 for ( ; node != (Stack *)NULL; node=node->next)
4540 size++;
anthony92c93bd2012-03-19 14:02:47 +00004541 if ( size >= MAX_STACK_DEPTH )
anthony4d4f2c72012-03-22 03:22:03 +00004542 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004543 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004544 if (node == (Stack *) NULL)
4545 CLIWandExceptionReturn(ResourceLimitFatalError,
4546 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004547
4548 node->data = (void *)cli_wand->wand.image_info;
4549 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004550 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
anthony92c93bd2012-03-19 14:02:47 +00004551 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4552 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004553 cli_wand->wand.image_info = (ImageInfo *)node->data;
4554 node = (Stack *)RelinquishMagickMemory(node);
4555 return;
4556 }
anthony43f425d2012-02-26 12:58:58 +00004557
4558 node->next = cli_wand->image_info_stack;
4559 cli_wand->image_info_stack = node;
4560
4561 return;
4562 }
anthonyce8dcb32012-03-21 13:20:31 +00004563 if (LocaleCompare(")",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004564 /* pop images from stack */
4565 Stack
4566 *node;
4567
cristyaa2c16c2012-03-25 22:21:35 +00004568 node = (Stack *)cli_wand->image_list_stack;
anthony43f425d2012-02-26 12:58:58 +00004569 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004570 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004571 cli_wand->image_list_stack = node->next;
4572
4573 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4574 cli_wand->wand.images= (Image *)node->data;
4575 node = (Stack *)RelinquishMagickMemory(node);
4576
anthony4d4f2c72012-03-22 03:22:03 +00004577 /* handle respect-parenthesis - of the previous 'pushed' settings */
anthony43f425d2012-02-26 12:58:58 +00004578 node = cli_wand->image_info_stack;
4579 if ( node != (Stack *)NULL)
4580 {
anthonyce8dcb32012-03-21 13:20:31 +00004581 if (IsMagickTrue(GetImageOption((ImageInfo *)node->data,
4582 "respect-parenthesis")) != MagickFalse )
anthonyf42014d2012-03-25 09:53:06 +00004583 option="}"; /* fall-thru so as to pop image settings too */
anthony43f425d2012-02-26 12:58:58 +00004584 else
4585 return;
4586 }
4587 else
4588 return;
4589 }
anthonyce8dcb32012-03-21 13:20:31 +00004590 if (LocaleCompare("}",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004591 /* pop image_info settings from stack */
4592 Stack
4593 *node;
4594
cristyaa2c16c2012-03-25 22:21:35 +00004595 node = (Stack *)cli_wand->image_info_stack;
anthony43f425d2012-02-26 12:58:58 +00004596 if ( node == (Stack *)NULL)
anthony4d4f2c72012-03-22 03:22:03 +00004597 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
anthony43f425d2012-02-26 12:58:58 +00004598 cli_wand->image_info_stack = node->next;
4599
4600 (void) DestroyImageInfo(cli_wand->wand.image_info);
4601 cli_wand->wand.image_info = (ImageInfo *)node->data;
4602 node = (Stack *)RelinquishMagickMemory(node);
4603
4604 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4605 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4606 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4607
4608 return;
4609 }
anthonyce8dcb32012-03-21 13:20:31 +00004610 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004611 Image
4612 *new_images;
4613
4614 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004615 arg1="-1";
4616 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004617 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004618 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004619 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004620 new_images = (Image *)cli_wand->image_list_stack->data;
4621 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004622 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4623 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004624 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004625 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004626 AppendImageToList(&cli_wand->wand.images,new_images);
4627 return;
4628 }
anthony319dac62012-03-06 04:12:44 +00004629 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthonyce8dcb32012-03-21 13:20:31 +00004630 ( LocaleCompare("--",option) == 0 ) ) {
anthonyafa3dfc2012-03-03 11:31:30 +00004631#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004632 Image *
4633 new_images;
4634
anthony43f425d2012-02-26 12:58:58 +00004635 if (cli_wand->wand.image_info->ping != MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004636 new_images=PingImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004637 else
anthony92c93bd2012-03-19 14:02:47 +00004638 new_images=ReadImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004639 AppendImageToList(&cli_wand->wand.images, new_images);
4640#else
4641 /* read images using MagickWand method - no ping */
4642 /* This is not working! - it locks up in a CPU loop! */
4643 MagickSetLastIterator(&cli_wand->wand);
anthony24aa8822012-03-11 00:56:06 +00004644 MagickReadImage(&cli_wand->wand,arg1);
anthony43f425d2012-02-26 12:58:58 +00004645 MagickSetFirstIterator(&cli_wand->wand);
4646#endif
4647 return;
4648 }
anthonyafa3dfc2012-03-03 11:31:30 +00004649 /* No-op options */
4650 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004651 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004652 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004653 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004654 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004655 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004656 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004657 return;
anthonyce8dcb32012-03-21 13:20:31 +00004658 if (LocaleCompare("list",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004659 /* FUTURE: This should really be built into the MagickCore
4660 It does not actually require any wand or images at all!
4661 */
4662 ssize_t
4663 list;
4664
anthony24aa8822012-03-11 00:56:06 +00004665 list=ParseCommandOption(MagickListOptions,MagickFalse, arg1);
anthonyfe1aa782012-03-24 13:43:04 +00004666 if ( list < 0 ) {
4667 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4668 return;
4669 }
anthony43f425d2012-02-26 12:58:58 +00004670 switch (list)
4671 {
4672 case MagickCoderOptions:
4673 {
anthony92c93bd2012-03-19 14:02:47 +00004674 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004675 break;
4676 }
4677 case MagickColorOptions:
4678 {
anthony92c93bd2012-03-19 14:02:47 +00004679 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004680 break;
4681 }
4682 case MagickConfigureOptions:
4683 {
anthony92c93bd2012-03-19 14:02:47 +00004684 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004685 break;
4686 }
4687 case MagickDelegateOptions:
4688 {
anthony92c93bd2012-03-19 14:02:47 +00004689 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004690 break;
4691 }
4692 case MagickFontOptions:
4693 {
anthony92c93bd2012-03-19 14:02:47 +00004694 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004695 break;
4696 }
4697 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004698 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004699 break;
4700 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004701 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004702 break;
4703 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004704 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004705 break;
4706 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004707 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004708 break;
4709 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004710 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004711 break;
4712 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004713 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004714 break;
4715 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004716 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004717 break;
4718 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004719 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004720 break;
4721 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004722 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004723 break;
4724 default:
4725 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004726 _exception);
anthony43f425d2012-02-26 12:58:58 +00004727 break;
4728 }
4729 return;
4730 }
4731
4732#if 0
4733 // adjust stack handling
4734 // Other 'special' options this should handle
4735 // "region" "list" "version"
4736 // It does not do "exit" however as due to its side-effect requirements
4737#endif
4738#if 0
4739 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004740#endif
anthonyebb73a22012-03-22 14:25:52 +00004741 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004742
anthony92c93bd2012-03-19 14:02:47 +00004743#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004744}