blob: e7c9a7ba0323b592812adc44391065f4e42eb2b3 [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);
anthony92c93bd2012-03-19 14:02:47 +0000700 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
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);
974 _image_info->endian=(EndianType) arg1;
975 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000976 break;
977 }
anthonyafa3dfc2012-03-03 11:31:30 +0000978 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000979 {
anthony92c93bd2012-03-19 14:02:47 +0000980 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000981 break;
982 }
anthonyebb73a22012-03-22 14:25:52 +0000983 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000984 }
985 case 'f':
986 {
anthonyafa3dfc2012-03-03 11:31:30 +0000987 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000988 {
anthony92c93bd2012-03-19 14:02:47 +0000989 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000990 break;
991 }
anthonyafa3dfc2012-03-03 11:31:30 +0000992 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000993 {
anthony92c93bd2012-03-19 14:02:47 +0000994 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000995 The original fill color is preserved if a fill-pattern is given.
996 That way it does not effect other operations that directly using
997 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000998 */
anthony72feaa62012-01-17 06:46:23 +0000999 MagickBooleanType
1000 status;
anthony6dc09cd2011-10-12 08:56:49 +00001001
1002 ExceptionInfo
1003 *sans;
1004
anthonyfd706f92012-01-19 04:22:02 +00001005 PixelInfo
1006 color;
1007
anthony2a0ec8c2012-03-24 04:35:56 +00001008 arg1 = ArgOption("none"); /* +fill turns it off! */
1009 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001010 if (_draw_info->fill_pattern != (Image *) NULL)
1011 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +00001012
1013 /* is it a color or a image? -- ignore exceptions */
1014 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001015 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +00001016 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001017
anthony6dc09cd2011-10-12 08:56:49 +00001018 if (status == MagickFalse)
anthony2a0ec8c2012-03-24 04:35:56 +00001019 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001020 else
anthony92c93bd2012-03-19 14:02:47 +00001021 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +00001022 break;
1023 }
anthonyafa3dfc2012-03-03 11:31:30 +00001024 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001025 {
anthony72feaa62012-01-17 06:46:23 +00001026 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +00001027 arg1 = ArgOption("undefined");
1028 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
1029 if (parse < 0)
1030 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
1031 option,arg1);
1032 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001033 break;
1034 }
anthonyafa3dfc2012-03-03 11:31:30 +00001035 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001036 {
anthony92c93bd2012-03-19 14:02:47 +00001037 (void) CloneString(&_draw_info->font,ArgOption(NULL));
1038 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +00001039 break;
1040 }
anthonyafa3dfc2012-03-03 11:31:30 +00001041 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001042 {
anthonydcf510d2011-10-30 13:51:40 +00001043 /* FUTURE: why the ping test, you could set ping after this! */
1044 /*
anthony805a2d42011-09-25 08:25:12 +00001045 register const char
1046 *q;
1047
anthony24aa8822012-03-11 00:56:06 +00001048 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +00001049 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00001050 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +00001051 */
anthony92c93bd2012-03-19 14:02:47 +00001052 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001053 break;
1054 }
anthonyafa3dfc2012-03-03 11:31:30 +00001055 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001056 {
anthony72feaa62012-01-17 06:46:23 +00001057 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +00001058 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +00001059 SyncImageSettings() used to set per-image attribute.
1060
anthony2a0ec8c2012-03-24 04:35:56 +00001061 FUTURE: Can't find anything else using _image_info->fuzz directly!
1062 remove direct sttribute from image_info
anthony6613bf32011-10-15 07:24:44 +00001063 */
anthony2a0ec8c2012-03-24 04:35:56 +00001064 arg1=ArgOption("0");
1065 if (IsGeometry(arg1) == MagickFalse)
1066 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1067 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +00001068 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00001069 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001070 break;
1071 }
anthonyebb73a22012-03-22 14:25:52 +00001072 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001073 }
1074 case 'g':
1075 {
anthonyafa3dfc2012-03-03 11:31:30 +00001076 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001077 {
anthony72feaa62012-01-17 06:46:23 +00001078 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001079 arg1 = ArgOption("none");
1080 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
1081 if (parse < 0)
1082 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
1083 option,arg1);
1084 (void) SetImageOption(_image_info,option+1,arg1);
1085 _draw_info->gravity=(GravityType) parse;
anthony805a2d42011-09-25 08:25:12 +00001086 break;
1087 }
anthonyafa3dfc2012-03-03 11:31:30 +00001088 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001089 {
anthonydcf510d2011-10-30 13:51:40 +00001090 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +00001091 SyncImageSettings() used to set per-image attribute.
1092 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +00001093 */
anthonyf42014d2012-03-25 09:53:06 +00001094 arg1=ArgOption("0.0");
1095 if (IsGeometry(arg1) == MagickFalse)
anthonyfe1aa782012-03-24 13:43:04 +00001096 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001097 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001098 break;
1099 }
anthonyebb73a22012-03-22 14:25:52 +00001100 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001101 }
1102 case 'i':
1103 {
anthonyafa3dfc2012-03-03 11:31:30 +00001104 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001105 {
anthony72feaa62012-01-17 06:46:23 +00001106 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +00001107 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +00001108 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001109 */
anthonyfe1aa782012-03-24 13:43:04 +00001110 arg1 = ArgOption("indefined");
1111 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
1112 if (parse < 0)
1113 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
1114 option,arg1);
1115 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001116 break;
1117 }
anthonyafa3dfc2012-03-03 11:31:30 +00001118 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001119 {
anthony92c93bd2012-03-19 14:02:47 +00001120 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +00001121 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001122 */
anthonyfe1aa782012-03-24 13:43:04 +00001123 arg1 = ArgOption("undefined");
1124 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
1125 if (parse < 0)
1126 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
1127 option,arg1);
1128 _image_info->interlace=(InterlaceType) parse;
1129 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001130 break;
1131 }
anthonyafa3dfc2012-03-03 11:31:30 +00001132 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001133 {
anthonyfe1aa782012-03-24 13:43:04 +00001134 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1135 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001136 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1137 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001138 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001139 break;
1140 }
anthonyafa3dfc2012-03-03 11:31:30 +00001141 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001142 {
anthonyfd706f92012-01-19 04:22:02 +00001143 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001144 arg1 = ArgOption("undefined");
1145 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1146 if (parse < 0)
1147 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1148 option,arg1);
1149 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001150 break;
1151 }
anthonyafa3dfc2012-03-03 11:31:30 +00001152 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001153 {
anthonyfe1aa782012-03-24 13:43:04 +00001154 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1155 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001156 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1157 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001158 break;
1159 }
anthonyebb73a22012-03-22 14:25:52 +00001160 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001161 }
1162 case 'k':
1163 {
anthonyafa3dfc2012-03-03 11:31:30 +00001164 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001165 {
anthonyfe1aa782012-03-24 13:43:04 +00001166 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1167 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001168 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1169 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001170 break;
1171 }
anthonyebb73a22012-03-22 14:25:52 +00001172 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001173 }
1174 case 'l':
1175 {
anthonyafa3dfc2012-03-03 11:31:30 +00001176 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001177 {
anthony72feaa62012-01-17 06:46:23 +00001178 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001179 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001180 break;
1181 }
anthonyafa3dfc2012-03-03 11:31:30 +00001182 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001183 {
anthonyfe1aa782012-03-24 13:43:04 +00001184 if (IfSetOption) {
1185 if ((strchr(arg1,'%') == (char *) NULL))
1186 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001187 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001188 }
anthony805a2d42011-09-25 08:25:12 +00001189 break;
1190 }
anthonyafa3dfc2012-03-03 11:31:30 +00001191 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001192 {
anthony72feaa62012-01-17 06:46:23 +00001193 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001194 arg1=ArgOption("0");
1195 if (IsGeometry(arg1) == MagickFalse)
1196 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1197 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001198 break;
1199 }
anthonyebb73a22012-03-22 14:25:52 +00001200 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001201 }
1202 case 'm':
1203 {
anthonyafa3dfc2012-03-03 11:31:30 +00001204 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001205 {
anthony72feaa62012-01-17 06:46:23 +00001206 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001207 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001208 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001209 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001210 break;
1211 }
anthonyafa3dfc2012-03-03 11:31:30 +00001212 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001213 {
anthony92c93bd2012-03-19 14:02:47 +00001214 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001215 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001216 break;
1217 }
anthonyafa3dfc2012-03-03 11:31:30 +00001218 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001219 {
anthony24aa8822012-03-11 00:56:06 +00001220 /* Setting (used by some input coders!) -- why?
1221 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001222 */
anthony92c93bd2012-03-19 14:02:47 +00001223 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001224 break;
1225 }
anthonyebb73a22012-03-22 14:25:52 +00001226 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001227 }
1228 case 'o':
1229 {
anthonyafa3dfc2012-03-03 11:31:30 +00001230 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001231 {
anthony72feaa62012-01-17 06:46:23 +00001232 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001233 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001234 FUTURE: make set meta-data operator instead.
1235 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001236 */
anthony7bc87992012-03-25 02:32:51 +00001237 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1238 ArgOption("undefined"));
1239 if (parse < 0)
1240 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1241 option,arg1);
1242 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001243 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001244 break;
1245 }
anthonyebb73a22012-03-22 14:25:52 +00001246 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001247 }
1248 case 'p':
1249 {
anthonyafa3dfc2012-03-03 11:31:30 +00001250 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001251 {
anthony7bc87992012-03-25 02:32:51 +00001252 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001253 SyncImageSettings() used to set per-image attribute. ?????
1254 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001255 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001256 */
anthony805a2d42011-09-25 08:25:12 +00001257 char
1258 *canonical_page,
1259 page[MaxTextExtent];
1260
1261 const char
1262 *image_option;
1263
1264 MagickStatusType
1265 flags;
1266
1267 RectangleInfo
1268 geometry;
1269
anthonydcf510d2011-10-30 13:51:40 +00001270 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001271 {
anthony92c93bd2012-03-19 14:02:47 +00001272 (void) DeleteImageOption(_image_info,option+1);
1273 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001274 break;
1275 }
1276 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001277 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001278 if (image_option != (const char *) NULL)
1279 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001280 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001281 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1282 canonical_page=DestroyString(canonical_page);
1283 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1284 (unsigned long) geometry.width,(unsigned long) geometry.height);
1285 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1286 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1287 (unsigned long) geometry.width,(unsigned long) geometry.height,
1288 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001289 (void) SetImageOption(_image_info,option+1,page);
1290 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001291 break;
1292 }
anthonyafa3dfc2012-03-03 11:31:30 +00001293 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001294 {
anthony92c93bd2012-03-19 14:02:47 +00001295 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001296 break;
1297 }
anthonyafa3dfc2012-03-03 11:31:30 +00001298 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001299 {
anthonyf42014d2012-03-25 09:53:06 +00001300 if (IfSetOption) {
1301 if (IsGeometry(arg1) == MagickFalse)
1302 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1303 _image_info->pointsize =
1304 _draw_info->pointsize =
1305 StringToDouble(arg1,(char **) NULL);
1306 }
1307 else {
1308 _image_info->pointsize=0.0; /* unset pointsize */
1309 _draw_info->pointsize=12.0;
1310 }
anthony805a2d42011-09-25 08:25:12 +00001311 break;
1312 }
anthonyafa3dfc2012-03-03 11:31:30 +00001313 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001314 {
anthonyf42014d2012-03-25 09:53:06 +00001315 arg1=ArgOption("-1");
1316 if (IsGeometry(arg1) == MagickFalse)
1317 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1318 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001319 break;
1320 }
anthonydcf510d2011-10-30 13:51:40 +00001321 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001322 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001323 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001324 {
anthony92c93bd2012-03-19 14:02:47 +00001325 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001326 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001327 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001328 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001329 break;
1330 }
anthonydcf510d2011-10-30 13:51:40 +00001331 */
anthonyebb73a22012-03-22 14:25:52 +00001332 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001333 }
1334 case 'q':
1335 {
anthonyafa3dfc2012-03-03 11:31:30 +00001336 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001337 {
anthony7bc87992012-03-25 02:32:51 +00001338 if (IsGeometry(arg1) == MagickFalse)
1339 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001340 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1341 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001342 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001343 break;
1344 }
anthonyafa3dfc2012-03-03 11:31:30 +00001345 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001346 {
anthony92c93bd2012-03-19 14:02:47 +00001347 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001348 arg1=ArgOption("undefined");
1349 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1350 if (parse < 0)
1351 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1352 option,arg1);
1353 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001354 break;
1355 }
anthonyafa3dfc2012-03-03 11:31:30 +00001356 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001357 {
anthonyf42014d2012-03-25 09:53:06 +00001358 /* FUTURE: if two -quiet is performed you can not do +quiet!
1359 This needs to be checked over thoughly.
1360 */
anthony805a2d42011-09-25 08:25:12 +00001361 static WarningHandler
1362 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001363
anthonyafbaed72011-10-26 12:05:04 +00001364 WarningHandler
1365 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001366
anthonyafbaed72011-10-26 12:05:04 +00001367 if ( tmp != (WarningHandler) NULL)
1368 warning_handler = tmp; /* remember the old handler */
1369 if (!IfSetOption) /* set the old handler */
1370 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001371 break;
1372 }
anthonyebb73a22012-03-22 14:25:52 +00001373 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001374 }
1375 case 'r':
1376 {
anthonyafa3dfc2012-03-03 11:31:30 +00001377 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001378 {
anthonydcf510d2011-10-30 13:51:40 +00001379 /* Image chromaticity X,Y NB: Y=X if Y not defined
1380 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001381 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001382 */
anthonyf42014d2012-03-25 09:53:06 +00001383 arg1=ArgOption("0.0");
1384 if (IsGeometry(arg1) == MagickFalse)
anthonyfe1aa782012-03-24 13:43:04 +00001385 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001386 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001387 break;
1388 }
anthonyafa3dfc2012-03-03 11:31:30 +00001389 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001390 {
anthony92c93bd2012-03-19 14:02:47 +00001391 /* _draw_info only setting */
1392 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001393 break;
1394 }
anthonyebb73a22012-03-22 14:25:52 +00001395 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001396 }
1397 case 's':
1398 {
anthonyafa3dfc2012-03-03 11:31:30 +00001399 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001400 {
anthonyafbaed72011-10-26 12:05:04 +00001401 /* FUTURE: should be converted to jpeg:sampling_factor */
anthonyf42014d2012-03-25 09:53:06 +00001402 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1403 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001404 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001405 break;
1406 }
anthonyafa3dfc2012-03-03 11:31:30 +00001407 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001408 {
anthonyf42014d2012-03-25 09:53:06 +00001409 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001410 What ??? Why ????
1411 */
anthonyf42014d2012-03-25 09:53:06 +00001412 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1413 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001414 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1415 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001416 break;
1417 }
anthonyafa3dfc2012-03-03 11:31:30 +00001418 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001419 {
anthonyf42014d2012-03-25 09:53:06 +00001420 if (IsGeometry(arg1) == MagickFalse)
1421 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafbaed72011-10-26 12:05:04 +00001422 SeedPseudoRandomGenerator(
anthony24aa8822012-03-11 00:56:06 +00001423 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001424 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001425 break;
1426 }
anthonyafa3dfc2012-03-03 11:31:30 +00001427 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001428 {
anthony92c93bd2012-03-19 14:02:47 +00001429 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001430 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001431 */
anthony92c93bd2012-03-19 14:02:47 +00001432 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001433 break;
1434 }
anthonyafa3dfc2012-03-03 11:31:30 +00001435 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001436 {
anthonyf42014d2012-03-25 09:53:06 +00001437 arg1=ArgOption("undefined");
1438 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1439 if (parse < 0)
1440 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1441 option,arg1);
1442 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001443 break;
1444 }
anthonyafa3dfc2012-03-03 11:31:30 +00001445 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001446 {
anthonyafbaed72011-10-26 12:05:04 +00001447 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001448 UPDATE: ensure stroke color is not destroyed is a pattern
1449 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001450 */
anthony72feaa62012-01-17 06:46:23 +00001451 MagickBooleanType
1452 status;
anthonyafbaed72011-10-26 12:05:04 +00001453
1454 ExceptionInfo
1455 *sans;
1456
anthonyfd706f92012-01-19 04:22:02 +00001457 PixelInfo
1458 color;
1459
anthony2a0ec8c2012-03-24 04:35:56 +00001460 arg1 = ArgOption("none"); /* +fill turns it off! */
1461 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001462 if (_draw_info->stroke_pattern != (Image *) NULL)
1463 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001464
1465 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001466 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001467 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001468 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001469
anthonyafbaed72011-10-26 12:05:04 +00001470 if (status == MagickFalse)
anthony2a0ec8c2012-03-24 04:35:56 +00001471 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001472 else
anthony92c93bd2012-03-19 14:02:47 +00001473 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001474 break;
1475 }
anthonyafa3dfc2012-03-03 11:31:30 +00001476 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001477 {
anthonyf42014d2012-03-25 09:53:06 +00001478 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1479 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001480 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1481 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001482 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001483 break;
1484 }
anthonyafa3dfc2012-03-03 11:31:30 +00001485 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001486 {
anthonyf42014d2012-03-25 09:53:06 +00001487 arg1=ArgOption("undefined");
1488 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1489 if (parse < 0)
1490 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1491 option,arg1);
1492 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001493 break;
1494 }
anthonyafa3dfc2012-03-03 11:31:30 +00001495 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001496 {
anthonyf42014d2012-03-25 09:53:06 +00001497 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001498 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001499 break;
1500 }
anthonyebb73a22012-03-22 14:25:52 +00001501 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001502 }
1503 case 't':
1504 {
anthonyafa3dfc2012-03-03 11:31:30 +00001505 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001506 {
anthony72feaa62012-01-17 06:46:23 +00001507 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001508 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001509 break;
1510 }
anthonyafa3dfc2012-03-03 11:31:30 +00001511 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001512 {
anthony92c93bd2012-03-19 14:02:47 +00001513 /* FUTURE: move _image_info string to option splay-tree */
1514 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001515 break;
1516 }
anthonyafa3dfc2012-03-03 11:31:30 +00001517 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001518 {
anthony92c93bd2012-03-19 14:02:47 +00001519 _draw_info->fill_pattern=IfSetOption
1520 ?GetImageCache(_image_info,arg1,_exception)
1521 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001522 break;
1523 }
anthonyafa3dfc2012-03-03 11:31:30 +00001524 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001525 {
anthony72feaa62012-01-17 06:46:23 +00001526 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony92c93bd2012-03-19 14:02:47 +00001527 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001528 break;
1529 }
anthonyafa3dfc2012-03-03 11:31:30 +00001530 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001531 {
anthony92c93bd2012-03-19 14:02:47 +00001532 /* FUTURE: both _image_info attribute & ImageOption in use!
1533 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001534 SyncImageSettings() used to set per-image attribute.
1535
anthonyafbaed72011-10-26 12:05:04 +00001536 Note that +transparent-color, means fall-back to image
1537 attribute so ImageOption is deleted, not set to a default.
1538 */
anthony92c93bd2012-03-19 14:02:47 +00001539 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001540 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001541 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001542 break;
1543 }
anthonyafa3dfc2012-03-03 11:31:30 +00001544 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001545 {
anthony92c93bd2012-03-19 14:02:47 +00001546 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1547 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001548 break;
1549 }
anthonyafa3dfc2012-03-03 11:31:30 +00001550 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001551 {
anthony72feaa62012-01-17 06:46:23 +00001552 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001553 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1554 _image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
anthony72feaa62012-01-17 06:46:23 +00001555 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001556 break;
1557 }
anthonyebb73a22012-03-22 14:25:52 +00001558 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001559 }
1560 case 'u':
1561 {
anthonyafa3dfc2012-03-03 11:31:30 +00001562 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001563 {
anthony92c93bd2012-03-19 14:02:47 +00001564 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001565 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001566 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001567 break;
1568 }
anthonyafa3dfc2012-03-03 11:31:30 +00001569 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001570 {
anthony72feaa62012-01-17 06:46:23 +00001571 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001572 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001573 FUTURE: this probably should be part of the density setting
1574 */
anthony92c93bd2012-03-19 14:02:47 +00001575 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1576 _image_info->units=(ResolutionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001577 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001578 break;
1579 }
anthonyebb73a22012-03-22 14:25:52 +00001580 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001581 }
1582 case 'v':
1583 {
anthonyafa3dfc2012-03-03 11:31:30 +00001584 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001585 {
anthony24aa8822012-03-11 00:56:06 +00001586 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001587 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001588 */
anthony92c93bd2012-03-19 14:02:47 +00001589 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1590 _image_info->verbose= ArgBoolean;
1591 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001592 break;
1593 }
anthonyafa3dfc2012-03-03 11:31:30 +00001594 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001595 {
anthony92c93bd2012-03-19 14:02:47 +00001596 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001597 Only used by coder FPX
1598 */
anthony92c93bd2012-03-19 14:02:47 +00001599 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001600 break;
1601 }
anthonyafa3dfc2012-03-03 11:31:30 +00001602 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001603 {
anthonyfd706f92012-01-19 04:22:02 +00001604 /* SyncImageSettings() used to set per-image attribute.
1605 This is VERY deep in the image caching structure.
1606 */
anthony92c93bd2012-03-19 14:02:47 +00001607 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001608 break;
1609 }
anthonyebb73a22012-03-22 14:25:52 +00001610 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001611 }
1612 case 'w':
1613 {
anthonyafa3dfc2012-03-03 11:31:30 +00001614 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001615 {
anthony72feaa62012-01-17 06:46:23 +00001616 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001617 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001618 */
anthony72feaa62012-01-17 06:46:23 +00001619 if (!IfSetOption)
1620 break;
anthony92c93bd2012-03-19 14:02:47 +00001621 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001622 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001623 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001624 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001625 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001626 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001627 if (_draw_info->weight <= 800)
1628 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001629 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001630 if (_draw_info->weight >= 100)
1631 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001632 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001633 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001634 break;
1635 }
anthonyafa3dfc2012-03-03 11:31:30 +00001636 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001637 {
anthony72feaa62012-01-17 06:46:23 +00001638 /* Used as a image chromaticity setting
1639 SyncImageSettings() used to set per-image attribute.
1640 */
anthony92c93bd2012-03-19 14:02:47 +00001641 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001642 break;
1643 }
anthonyebb73a22012-03-22 14:25:52 +00001644 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001645 }
1646 default:
anthonyebb73a22012-03-22 14:25:52 +00001647 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001648 }
anthony24aa8822012-03-11 00:56:06 +00001649
anthony92c93bd2012-03-19 14:02:47 +00001650#undef _image_info
1651#undef _exception
1652#undef _draw_info
1653#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001654#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001655#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001656#undef ArgBooleanNot
1657#undef ArgBooleanString
1658#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001659
anthony31f1bf72012-01-30 12:37:22 +00001660 return;
anthony805a2d42011-09-25 08:25:12 +00001661}
1662
1663/*
1664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1665% %
1666% %
1667% %
anthony43f425d2012-02-26 12:58:58 +00001668+ 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 +00001669% %
1670% %
1671% %
1672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1673%
anthony31f1bf72012-01-30 12:37:22 +00001674% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001675% the images in the CLI wand, with the settings that was previously saved in
1676% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001677%
1678% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001679% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001680%
anthonyd1447672012-01-19 05:33:53 +00001681% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001682%
anthony43f425d2012-02-26 12:58:58 +00001683% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001684% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001685%
1686% A description of each parameter follows:
1687%
anthony43f425d2012-02-26 12:58:58 +00001688% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001689%
anthonyfd706f92012-01-19 04:22:02 +00001690% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001691%
anthonyfd706f92012-01-19 04:22:02 +00001692% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001693%
anthony31f1bf72012-01-30 12:37:22 +00001694% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001695%
anthony31f1bf72012-01-30 12:37:22 +00001696% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001697%
anthonyafa3dfc2012-03-03 11:31:30 +00001698% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1699% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1700% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001701%
anthony24aa8822012-03-11 00:56:06 +00001702% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001703%
anthony43f425d2012-02-26 12:58:58 +00001704% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001705% argc,argv
1706% i=index in argv
1707%
anthony2052d272012-02-28 12:48:29 +00001708% option_info = GetCommandOptionInfo(argv[i]);
1709% count=option_info->type;
1710% option_type=option_info->flags;
1711%
1712% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001713% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001714% count>=1 ? argv[i+1] : (char *)NULL,
1715% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001716% i += count+1;
1717%
anthony805a2d42011-09-25 08:25:12 +00001718*/
anthony31f1bf72012-01-30 12:37:22 +00001719
1720/*
1721 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001722 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001723
1724 The image in the list may be modified in three different ways...
1725 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1726 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1727 * one image replace by a list of images (-separate and -crop only!)
1728
anthonyafa3dfc2012-03-03 11:31:30 +00001729 In each case the result replaces the single original image in the list, as
1730 well as the pointer to the modified image (last image added if replaced by a
1731 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001732
1733 As the image pointed to may be replaced, the first image in the list may
1734 also change. GetFirstImageInList() should be used by caller if they wish
1735 return the Image pointer to the first image in list.
1736*/
anthony43f425d2012-02-26 12:58:58 +00001737static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001738 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001739{
1740 Image *
1741 new_image;
1742
anthony805a2d42011-09-25 08:25:12 +00001743 GeometryInfo
1744 geometry_info;
1745
1746 RectangleInfo
1747 geometry;
1748
1749 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001750 flags;
1751
anthony92c93bd2012-03-19 14:02:47 +00001752 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001753 parse;
anthony92c93bd2012-03-19 14:02:47 +00001754
1755#define _image_info (cli_wand->wand.image_info)
1756#define _image (cli_wand->wand.images)
1757#define _exception (cli_wand->wand.exception)
1758#define _draw_info (cli_wand->draw_info)
1759#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001760#define IfNormalOp (*option=='-')
1761#define IfPlusOp (*option!='-')
1762#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1763#define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001764
anthony43f425d2012-02-26 12:58:58 +00001765 assert(cli_wand != (MagickCLI *) NULL);
1766 assert(cli_wand->signature == WandSignature);
1767 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001768 assert(_image != (Image *) NULL); /* an image must be present */
anthony43f425d2012-02-26 12:58:58 +00001769 if (cli_wand->wand.debug != MagickFalse)
1770 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001771
anthony92c93bd2012-03-19 14:02:47 +00001772 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001773
anthony805a2d42011-09-25 08:25:12 +00001774 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001775
anthony5330ae02012-03-20 14:17:01 +00001776 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001777
anthonyfd706f92012-01-19 04:22:02 +00001778 /* FUTURE: We may need somthing a little more optimized than this!
1779 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1780 */
anthonyafa3dfc2012-03-03 11:31:30 +00001781 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001782 {
1783 case 'a':
1784 {
anthonyafa3dfc2012-03-03 11:31:30 +00001785 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001786 {
anthony92c93bd2012-03-19 14:02:47 +00001787 if (IsGeometry(arg1) == MagickFalse)
1788 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001789 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001790 if ((flags & SigmaValue) == 0)
1791 geometry_info.sigma=1.0;
1792 if ((flags & XiValue) == 0)
1793 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001794 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1795 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001796 break;
1797 }
anthonyafa3dfc2012-03-03 11:31:30 +00001798 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001799 {
anthonyfe1aa782012-03-24 13:43:04 +00001800 /* FUTURE: Roll into a resize special operator */
anthony92c93bd2012-03-19 14:02:47 +00001801 if (IsGeometry(arg1) == MagickFalse)
1802 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1803 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1804 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1805 _exception);
anthony805a2d42011-09-25 08:25:12 +00001806 break;
1807 }
anthonyafa3dfc2012-03-03 11:31:30 +00001808 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001809 {
anthony92c93bd2012-03-19 14:02:47 +00001810 if (IsGeometry(arg1) == MagickFalse)
1811 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001812 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001813 if ((flags & SigmaValue) == 0)
1814 geometry_info.sigma=1.0;
1815 if ((flags & XiValue) == 0)
1816 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001817 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1818 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001819 break;
1820 }
anthonyafa3dfc2012-03-03 11:31:30 +00001821 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001822 {
anthony2a0ec8c2012-03-24 04:35:56 +00001823 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1824 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001825 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1826 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001827 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1828 _exception);
anthony805a2d42011-09-25 08:25:12 +00001829 break;
1830 }
anthonyafa3dfc2012-03-03 11:31:30 +00001831 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001832 {
1833 char
1834 *text,
1835 geometry[MaxTextExtent];
1836
anthony92c93bd2012-03-19 14:02:47 +00001837 if (IsGeometry(arg1) == MagickFalse)
1838 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001839 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001840 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001841 if ((flags & SigmaValue) == 0)
1842 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001843 text=InterpretImageProperties(_image_info,_image,arg2,
1844 _exception);
anthony805a2d42011-09-25 08:25:12 +00001845 if (text == (char *) NULL)
1846 break;
anthony92c93bd2012-03-19 14:02:47 +00001847 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001848 text=DestroyString(text);
1849 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1850 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001851 (void) CloneString(&_draw_info->geometry,geometry);
1852 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001853 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001854 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001855 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001856 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001857 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001858 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001859 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001860 (void) AnnotateImage(_image,_draw_info,_exception);
1861 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001862 break;
1863 }
anthonyafa3dfc2012-03-03 11:31:30 +00001864 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001865 {
anthony92c93bd2012-03-19 14:02:47 +00001866 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001867 break;
1868 }
anthonyafa3dfc2012-03-03 11:31:30 +00001869 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001870 {
anthony92c93bd2012-03-19 14:02:47 +00001871 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001872 break;
1873 }
anthonyafa3dfc2012-03-03 11:31:30 +00001874 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001875 {
anthony5330ae02012-03-20 14:17:01 +00001876 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001877 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001878 {
1879 case TopRightOrientation:
1880 {
anthony92c93bd2012-03-19 14:02:47 +00001881 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001882 break;
1883 }
1884 case BottomRightOrientation:
1885 {
anthony92c93bd2012-03-19 14:02:47 +00001886 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001887 break;
1888 }
1889 case BottomLeftOrientation:
1890 {
anthony92c93bd2012-03-19 14:02:47 +00001891 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001892 break;
1893 }
1894 case LeftTopOrientation:
1895 {
anthony92c93bd2012-03-19 14:02:47 +00001896 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001897 break;
1898 }
1899 case RightTopOrientation:
1900 {
anthony92c93bd2012-03-19 14:02:47 +00001901 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001902 break;
1903 }
1904 case RightBottomOrientation:
1905 {
anthony92c93bd2012-03-19 14:02:47 +00001906 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001907 break;
1908 }
1909 case LeftBottomOrientation:
1910 {
anthony92c93bd2012-03-19 14:02:47 +00001911 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001912 break;
1913 }
1914 default:
1915 break;
1916 }
1917 if (new_image != (Image *) NULL)
1918 new_image->orientation=TopLeftOrientation;
1919 break;
1920 }
anthonyebb73a22012-03-22 14:25:52 +00001921 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001922 }
1923 case 'b':
1924 {
anthonyafa3dfc2012-03-03 11:31:30 +00001925 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001926 {
anthony5330ae02012-03-20 14:17:01 +00001927 if (IsGeometry(arg1) == MagickFalse)
1928 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001929 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001930 break;
1931 }
anthonyafa3dfc2012-03-03 11:31:30 +00001932 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001933 {
anthony805a2d42011-09-25 08:25:12 +00001934 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001935 if (IfNormalOp) {
1936 if (IsGeometry(arg1) == MagickFalse)
1937 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001938 flags=ParseGeometry(arg1,&geometry_info);
anthony5330ae02012-03-20 14:17:01 +00001939 }
anthony92c93bd2012-03-19 14:02:47 +00001940 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001941 break;
1942 }
anthonyafa3dfc2012-03-03 11:31:30 +00001943 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001944 {
anthony74b1cfc2011-10-06 12:44:16 +00001945 /* FUTURE: use of "bias" in a blur is non-sensible */
anthony5330ae02012-03-20 14:17:01 +00001946 if (IsGeometry(arg1) == MagickFalse)
1947 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001948 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001949 if ((flags & SigmaValue) == 0)
1950 geometry_info.sigma=1.0;
1951 if ((flags & XiValue) == 0)
1952 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001953 new_image=BlurImage(_image,geometry_info.rho,
1954 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001955 break;
1956 }
anthonyafa3dfc2012-03-03 11:31:30 +00001957 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001958 {
anthony31f1bf72012-01-30 12:37:22 +00001959 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001960 compose;
1961
1962 const char*
anthony5f867ae2011-10-09 10:28:34 +00001963 value;
1964
anthony5330ae02012-03-20 14:17:01 +00001965 if (IsGeometry(arg1) == MagickFalse)
1966 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1967
anthony92c93bd2012-03-19 14:02:47 +00001968 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001969 if (value != (const char *) NULL)
1970 compose=(CompositeOperator) ParseCommandOption(
1971 MagickComposeOptions,MagickFalse,value);
1972 else
anthony92c93bd2012-03-19 14:02:47 +00001973 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001974
anthony92c93bd2012-03-19 14:02:47 +00001975 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001976 if ((flags & SigmaValue) == 0)
1977 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001978 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001979 break;
1980 }
anthonyafa3dfc2012-03-03 11:31:30 +00001981 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001982 {
1983 double
1984 brightness,
1985 contrast;
1986
1987 GeometryInfo
1988 geometry_info;
1989
1990 MagickStatusType
1991 flags;
1992
anthony5330ae02012-03-20 14:17:01 +00001993 if (IsGeometry(arg1) == MagickFalse)
1994 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001995 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001996 brightness=geometry_info.rho;
1997 contrast=0.0;
1998 if ((flags & SigmaValue) != 0)
1999 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00002000 (void) BrightnessContrastImage(_image,brightness,contrast,
2001 _exception);
anthony805a2d42011-09-25 08:25:12 +00002002 break;
2003 }
anthonyebb73a22012-03-22 14:25:52 +00002004 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002005 }
2006 case 'c':
2007 {
anthonyafa3dfc2012-03-03 11:31:30 +00002008 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002009 {
2010 char
2011 *color_correction_collection;
2012
2013 /*
2014 Color correct with a color decision list.
2015 */
anthony92c93bd2012-03-19 14:02:47 +00002016 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002017 if (color_correction_collection == (char *) NULL)
2018 break;
anthony92c93bd2012-03-19 14:02:47 +00002019 (void) ColorDecisionListImage(_image,color_correction_collection,
2020 _exception);
anthony805a2d42011-09-25 08:25:12 +00002021 break;
2022 }
anthonyafa3dfc2012-03-03 11:31:30 +00002023 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002024 {
anthony5330ae02012-03-20 14:17:01 +00002025 if (IsGeometry(arg1) == MagickFalse)
2026 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002027 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002028 if ((flags & SigmaValue) == 0)
2029 geometry_info.sigma=1.0;
2030 if ((flags & XiValue) == 0)
2031 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002032 new_image=CharcoalImage(_image,geometry_info.rho,
2033 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002034 break;
2035 }
anthonyafa3dfc2012-03-03 11:31:30 +00002036 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002037 {
anthony5330ae02012-03-20 14:17:01 +00002038 if (IsGeometry(arg1) == MagickFalse)
2039 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002040 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
2041 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002042 break;
2043 }
anthonyafa3dfc2012-03-03 11:31:30 +00002044 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002045 {
anthony92c93bd2012-03-19 14:02:47 +00002046 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002047 break;
2048 }
anthonyafa3dfc2012-03-03 11:31:30 +00002049 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002050 {
anthonyafa3dfc2012-03-03 11:31:30 +00002051 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002052 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00002053 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002054 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002055 break;
2056 }
anthonyafa3dfc2012-03-03 11:31:30 +00002057 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002058 {
2059 CacheView
2060 *mask_view;
2061
2062 Image
2063 *mask_image;
2064
2065 register Quantum
2066 *restrict q;
2067
2068 register ssize_t
2069 x;
2070
2071 ssize_t
2072 y;
2073
anthonyafa3dfc2012-03-03 11:31:30 +00002074 if (IfPlusOp) {
2075 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002076 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002077 break;
2078 }
anthony92c93bd2012-03-19 14:02:47 +00002079 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002080 if (mask_image == (Image *) NULL)
2081 break;
anthony92c93bd2012-03-19 14:02:47 +00002082 if (SetImageStorageClass(mask_image,DirectClass,_exception)
anthonyfd706f92012-01-19 04:22:02 +00002083 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00002084 break;
anthony5330ae02012-03-20 14:17:01 +00002085 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002086 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00002087 mask_view=AcquireCacheView(mask_image);
2088 for (y=0; y < (ssize_t) mask_image->rows; y++)
2089 {
2090 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002091 _exception);
anthony805a2d42011-09-25 08:25:12 +00002092 if (q == (Quantum *) NULL)
2093 break;
2094 for (x=0; x < (ssize_t) mask_image->columns; x++)
2095 {
2096 if (mask_image->matte == MagickFalse)
2097 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2098 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2099 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2100 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2101 q+=GetPixelChannels(mask_image);
2102 }
anthony92c93bd2012-03-19 14:02:47 +00002103 if (SyncCacheViewAuthenticPixels(mask_view,_exception) == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002104 break;
2105 }
anthonyfd706f92012-01-19 04:22:02 +00002106 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002107 mask_view=DestroyCacheView(mask_view);
2108 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002109 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002110 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002111 break;
2112 }
anthonyafa3dfc2012-03-03 11:31:30 +00002113 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002114 {
anthony92c93bd2012-03-19 14:02:47 +00002115 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002116 break;
2117 }
anthonyafa3dfc2012-03-03 11:31:30 +00002118 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002119 {
anthony5330ae02012-03-20 14:17:01 +00002120 if (IsGeometry(arg1) == MagickFalse)
2121 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002122 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002123 break;
2124 }
anthonyafa3dfc2012-03-03 11:31:30 +00002125 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002126 {
2127 KernelInfo
2128 *kernel;
2129
anthonyfd706f92012-01-19 04:22:02 +00002130 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002131 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002132 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002133 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002134 kernel=DestroyKernelInfo(kernel);
2135 break;
2136 }
anthonyafa3dfc2012-03-03 11:31:30 +00002137 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002138 {
anthony5330ae02012-03-20 14:17:01 +00002139 /* Reduce the number of colors in the image.
2140 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002141 */
anthony92c93bd2012-03-19 14:02:47 +00002142 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2143 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002144 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002145 if ((_image->storage_class == DirectClass) ||
2146 _image->colors > _quantize_info->number_colors)
2147 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002148 else
anthony92c93bd2012-03-19 14:02:47 +00002149 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002150 break;
2151 }
anthonyafa3dfc2012-03-03 11:31:30 +00002152 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002153 {
anthony5330ae02012-03-20 14:17:01 +00002154 /* WARNING: this is both a image_info setting (already done)
2155 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002156
2157 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002158 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002159
anthonyd2cdc862011-10-07 14:07:17 +00002160 Note that +colorspace sets "undefined" or no effect on
2161 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002162 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002163 */
anthony92c93bd2012-03-19 14:02:47 +00002164 (void) TransformImageColorspace(_image,
2165 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2166 _exception);
anthony805a2d42011-09-25 08:25:12 +00002167 break;
2168 }
anthonyafa3dfc2012-03-03 11:31:30 +00002169 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002170 {
anthonydcf3a912012-03-22 14:33:17 +00002171 /* DEPRECIATED: The -/+level provides far more controlled form */
anthony92c93bd2012-03-19 14:02:47 +00002172 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002173 break;
2174 }
anthonyafa3dfc2012-03-03 11:31:30 +00002175 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002176 {
2177 double
2178 black_point,
2179 white_point;
2180
2181 MagickStatusType
2182 flags;
2183
anthonyebb73a22012-03-22 14:25:52 +00002184 if (IsGeometry(arg1) == MagickFalse)
2185 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002186 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002187 black_point=geometry_info.rho;
2188 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2189 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002190 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002191 black_point*=(double) _image->columns*_image->rows/100.0;
2192 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002193 }
anthony92c93bd2012-03-19 14:02:47 +00002194 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002195 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002196 (void) ContrastStretchImage(_image,black_point,white_point,
2197 _exception);
anthony805a2d42011-09-25 08:25:12 +00002198 break;
2199 }
anthonyafa3dfc2012-03-03 11:31:30 +00002200 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002201 {
2202 KernelInfo
2203 *kernel_info;
2204
anthonyfd706f92012-01-19 04:22:02 +00002205 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002206 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002207 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002208 kernel_info->bias=_image->bias;
2209 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002210 kernel_info=DestroyKernelInfo(kernel_info);
2211 break;
2212 }
anthonyafa3dfc2012-03-03 11:31:30 +00002213 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002214 {
anthony31f1bf72012-01-30 12:37:22 +00002215 /* WARNING: This can generate multiple images! */
anthonyebb73a22012-03-22 14:25:52 +00002216 if (IsGeometry(arg1) == MagickFalse)
2217 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002218 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002219 break;
2220 }
anthonyafa3dfc2012-03-03 11:31:30 +00002221 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002222 {
anthonyebb73a22012-03-22 14:25:52 +00002223 if (IsGeometry(arg1) == MagickFalse)
2224 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002225 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2226 _exception);
anthony805a2d42011-09-25 08:25:12 +00002227 break;
2228 }
anthonyebb73a22012-03-22 14:25:52 +00002229 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002230 }
2231 case 'd':
2232 {
anthonyafa3dfc2012-03-03 11:31:30 +00002233 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002234 {
2235 StringInfo
2236 *passkey;
2237
anthony92c93bd2012-03-19 14:02:47 +00002238 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002239 if (passkey == (StringInfo *) NULL)
2240 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2241
2242 (void) PasskeyDecipherImage(_image,passkey,_exception);
2243 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002244 break;
2245 }
anthonyafa3dfc2012-03-03 11:31:30 +00002246 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002247 {
anthony92c93bd2012-03-19 14:02:47 +00002248 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002249 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002250
anthonydcf510d2011-10-30 13:51:40 +00002251 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2252 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002253
anthonyfd706f92012-01-19 04:22:02 +00002254 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002255 */
anthony92c93bd2012-03-19 14:02:47 +00002256 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002257 break;
2258 }
anthonyafa3dfc2012-03-03 11:31:30 +00002259 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002260 {
2261 double
2262 threshold;
2263
anthonyebb73a22012-03-22 14:25:52 +00002264 if (IfNormalOp) {
2265 if (IsGeometry(arg1) == MagickFalse)
2266 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002267 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002268 }
anthonyafa3dfc2012-03-03 11:31:30 +00002269 else
2270 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002271 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002272 break;
2273 }
anthonyafa3dfc2012-03-03 11:31:30 +00002274 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002275 {
anthony92c93bd2012-03-19 14:02:47 +00002276 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002277 break;
2278 }
anthonyafa3dfc2012-03-03 11:31:30 +00002279 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002280 {
2281 char
2282 *args,
2283 token[MaxTextExtent];
2284
2285 const char
2286 *p;
2287
anthony805a2d42011-09-25 08:25:12 +00002288 double
2289 *arguments;
2290
2291 register ssize_t
2292 x;
2293
2294 size_t
2295 number_arguments;
2296
anthony2a0ec8c2012-03-24 04:35:56 +00002297 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2298 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002299 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2300 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002301 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002302 {
anthony80c37752012-01-16 01:03:11 +00002303 double
2304 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002305 /* Special Case - Argument is actually a resize geometry!
2306 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002307 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002308 Roll into a resize special operator */
anthonyebb73a22012-03-22 14:25:52 +00002309 if (IsGeometry(arg2) == MagickFalse)
2310 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2311 option,arg2);
2312 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002313 resize_args[0]=(double) geometry.width;
2314 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002315 new_image=DistortImage(_image,(DistortImageMethod) parse,
2316 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002317 break;
2318 }
anthonyfd706f92012-01-19 04:22:02 +00002319 /* handle percent arguments */
anthonyebb73a22012-03-22 14:25:52 +00002320 args=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00002321 if (args == (char *) NULL)
2322 break;
anthonyfd706f92012-01-19 04:22:02 +00002323 /* convert arguments into an array of doubles
2324 FUTURE: make this a separate function.
2325 Also make use of new 'sentinal' feature to avoid need for
2326 tokenization.
2327 */
anthony805a2d42011-09-25 08:25:12 +00002328 p=(char *) args;
2329 for (x=0; *p != '\0'; x++)
2330 {
2331 GetMagickToken(p,&p,token);
2332 if (*token == ',')
2333 GetMagickToken(p,&p,token);
2334 }
2335 number_arguments=(size_t) x;
2336 arguments=(double *) AcquireQuantumMemory(number_arguments,
2337 sizeof(*arguments));
2338 if (arguments == (double *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002339 CLIWandExceptionBreak(ResourceLimitFatalError,
2340 "MemoryAllocationFailed",option);
anthony805a2d42011-09-25 08:25:12 +00002341 (void) ResetMagickMemory(arguments,0,number_arguments*
anthonyebb73a22012-03-22 14:25:52 +00002342 sizeof(*arguments));
anthony805a2d42011-09-25 08:25:12 +00002343 p=(char *) args;
2344 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2345 {
2346 GetMagickToken(p,&p,token);
2347 if (*token == ',')
2348 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002349 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002350 }
2351 args=DestroyString(args);
anthony2a0ec8c2012-03-24 04:35:56 +00002352 new_image=DistortImage(_image,(DistortImageMethod) parse,
2353 number_arguments,arguments,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002354 arguments=(double *) RelinquishMagickMemory(arguments);
2355 break;
2356 }
anthonyafa3dfc2012-03-03 11:31:30 +00002357 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002358 {
anthony92c93bd2012-03-19 14:02:47 +00002359 (void) CloneString(&_draw_info->primitive,arg1);
2360 (void) DrawImage(_image,_draw_info,_exception);
2361 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002362 break;
2363 }
anthonyebb73a22012-03-22 14:25:52 +00002364 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002365 }
2366 case 'e':
2367 {
anthonyafa3dfc2012-03-03 11:31:30 +00002368 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002369 {
anthony2a0ec8c2012-03-24 04:35:56 +00002370 if (IsGeometry(arg1) == MagickFalse)
2371 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002372 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002373 if ((flags & SigmaValue) == 0)
2374 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002375 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2376 _exception);
anthony805a2d42011-09-25 08:25:12 +00002377 break;
2378 }
anthonyafa3dfc2012-03-03 11:31:30 +00002379 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002380 {
anthony2a0ec8c2012-03-24 04:35:56 +00002381 if (IsGeometry(arg1) == MagickFalse)
2382 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002383 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002384 if ((flags & SigmaValue) == 0)
2385 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002386 new_image=EmbossImage(_image,geometry_info.rho,
2387 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002388 break;
2389 }
anthonyafa3dfc2012-03-03 11:31:30 +00002390 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002391 {
2392 StringInfo
2393 *passkey;
2394
anthony92c93bd2012-03-19 14:02:47 +00002395 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002396 if (passkey != (StringInfo *) NULL)
2397 {
anthony92c93bd2012-03-19 14:02:47 +00002398 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002399 passkey=DestroyStringInfo(passkey);
2400 }
2401 break;
2402 }
anthonyafa3dfc2012-03-03 11:31:30 +00002403 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002404 {
anthony92c93bd2012-03-19 14:02:47 +00002405 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002406 break;
2407 }
anthonyafa3dfc2012-03-03 11:31:30 +00002408 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002409 {
anthony92c93bd2012-03-19 14:02:47 +00002410 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002411 break;
2412 }
anthonyafa3dfc2012-03-03 11:31:30 +00002413 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002414 {
2415 double
2416 constant;
2417
anthony2a0ec8c2012-03-24 04:35:56 +00002418 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2419 if ( parse < 0 )
2420 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2421 option,arg1);
2422 if (IsGeometry(arg2) == MagickFalse)
2423 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002424 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002425 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2426 _exception);
anthony805a2d42011-09-25 08:25:12 +00002427 break;
2428 }
anthonyafa3dfc2012-03-03 11:31:30 +00002429 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002430 {
anthony2a0ec8c2012-03-24 04:35:56 +00002431 if (IsGeometry(arg1) == MagickFalse)
2432 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002433 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002434 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002435 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002436 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002437 geometry.height=_image->rows;
2438 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002439 break;
2440 }
anthonyebb73a22012-03-22 14:25:52 +00002441 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002442 }
2443 case 'f':
2444 {
anthonyafa3dfc2012-03-03 11:31:30 +00002445 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002446 {
anthony31f1bf72012-01-30 12:37:22 +00002447 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002448 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002449 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002450 break;
2451 }
anthony92c93bd2012-03-19 14:02:47 +00002452 (void) SetImageArtifact(_image,"identify:features","true");
2453 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002454 break;
2455 }
anthonyafa3dfc2012-03-03 11:31:30 +00002456 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002457 {
anthony92c93bd2012-03-19 14:02:47 +00002458 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002459 break;
2460 }
anthonyafa3dfc2012-03-03 11:31:30 +00002461 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002462 {
anthony92c93bd2012-03-19 14:02:47 +00002463 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002464 break;
2465 }
anthonyafa3dfc2012-03-03 11:31:30 +00002466 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002467 {
2468 PixelInfo
2469 target;
2470
anthony2a0ec8c2012-03-24 04:35:56 +00002471 if (IsGeometry(arg1) == MagickFalse)
2472 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002473 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2474 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2475 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2476 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002477 break;
2478 }
anthonyafa3dfc2012-03-03 11:31:30 +00002479 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002480 {
2481 FrameInfo
2482 frame_info;
2483
anthony31f1bf72012-01-30 12:37:22 +00002484 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002485 compose;
2486
2487 const char*
2488 value;
2489
anthony92c93bd2012-03-19 14:02:47 +00002490 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002491 if (value != (const char *) NULL)
2492 compose=(CompositeOperator) ParseCommandOption(
2493 MagickComposeOptions,MagickFalse,value);
2494 else
anthony92c93bd2012-03-19 14:02:47 +00002495 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002496
anthony2a0ec8c2012-03-24 04:35:56 +00002497 if (IsGeometry(arg1) == MagickFalse)
2498 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002499 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002500 frame_info.width=geometry.width;
2501 frame_info.height=geometry.height;
2502 if ((flags & HeightValue) == 0)
2503 frame_info.height=geometry.width;
2504 frame_info.outer_bevel=geometry.x;
2505 frame_info.inner_bevel=geometry.y;
2506 frame_info.x=(ssize_t) frame_info.width;
2507 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002508 frame_info.width=_image->columns+2*frame_info.width;
2509 frame_info.height=_image->rows+2*frame_info.height;
2510 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002511 break;
2512 }
anthonyafa3dfc2012-03-03 11:31:30 +00002513 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002514 {
2515 char
2516 *arguments,
2517 token[MaxTextExtent];
2518
2519 const char
2520 *p;
2521
2522 double
2523 *parameters;
2524
anthony805a2d42011-09-25 08:25:12 +00002525 register ssize_t
2526 x;
2527
2528 size_t
2529 number_parameters;
2530
cristy947cb4c2011-10-20 18:41:46 +00002531 /*
2532 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002533 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002534 */
anthony2a0ec8c2012-03-24 04:35:56 +00002535 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2536 if ( parse < 0 )
2537 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2538 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002539 arguments=InterpretImageProperties(_image_info,_image,arg2,
2540 _exception);
anthony805a2d42011-09-25 08:25:12 +00002541 if (arguments == (char *) NULL)
anthony2a0ec8c2012-03-24 04:35:56 +00002542 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony805a2d42011-09-25 08:25:12 +00002543 p=(char *) arguments;
2544 for (x=0; *p != '\0'; x++)
2545 {
2546 GetMagickToken(p,&p,token);
2547 if (*token == ',')
2548 GetMagickToken(p,&p,token);
2549 }
2550 number_parameters=(size_t) x;
2551 parameters=(double *) AcquireQuantumMemory(number_parameters,
2552 sizeof(*parameters));
2553 if (parameters == (double *) NULL)
2554 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002555 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002556 (void) ResetMagickMemory(parameters,0,number_parameters*
2557 sizeof(*parameters));
2558 p=(char *) arguments;
anthony2a0ec8c2012-03-24 04:35:56 +00002559 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++) {
anthony805a2d42011-09-25 08:25:12 +00002560 GetMagickToken(p,&p,token);
2561 if (*token == ',')
2562 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002563 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002564 }
2565 arguments=DestroyString(arguments);
anthony2a0ec8c2012-03-24 04:35:56 +00002566 (void) FunctionImage(_image,(MagickFunction)parse,number_parameters,
2567 parameters,_exception);
anthony805a2d42011-09-25 08:25:12 +00002568 parameters=(double *) RelinquishMagickMemory(parameters);
2569 break;
2570 }
anthonyebb73a22012-03-22 14:25:52 +00002571 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002572 }
2573 case 'g':
2574 {
anthonyafa3dfc2012-03-03 11:31:30 +00002575 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002576 {
anthonyfe1aa782012-03-24 13:43:04 +00002577 if (IsGeometry(arg1) == MagickFalse)
2578 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafa3dfc2012-03-03 11:31:30 +00002579 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002580 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2581 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002582 else
anthony92c93bd2012-03-19 14:02:47 +00002583 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002584 break;
2585 }
anthonyafa3dfc2012-03-03 11:31:30 +00002586 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2587 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002588 {
anthonyfe1aa782012-03-24 13:43:04 +00002589 if (IsGeometry(arg1) == MagickFalse)
2590 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002591 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002592 if ((flags & SigmaValue) == 0)
2593 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002594 new_image=GaussianBlurImage(_image,geometry_info.rho,
2595 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002596 break;
2597 }
anthonyafa3dfc2012-03-03 11:31:30 +00002598 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002599 {
anthonyfd706f92012-01-19 04:22:02 +00002600 /*
anthony31f1bf72012-01-30 12:37:22 +00002601 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002602 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002603 FUTURE: Why if no 'offset' does this resize ALL images?
2604 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002605 */
anthonyafa3dfc2012-03-03 11:31:30 +00002606 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002607 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002608 if (_image->geometry != (char *) NULL)
2609 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002610 break;
2611 }
anthonyfe1aa782012-03-24 13:43:04 +00002612 if (IsGeometry(arg1) == MagickFalse)
2613 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002614 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002615 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002616 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002617 else
anthony92c93bd2012-03-19 14:02:47 +00002618 new_image=ResizeImage(_image,geometry.width,geometry.height,
2619 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00002620 break;
2621 }
anthonyebb73a22012-03-22 14:25:52 +00002622 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002623 }
2624 case 'h':
2625 {
anthonyafa3dfc2012-03-03 11:31:30 +00002626 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002627 {
anthony92c93bd2012-03-19 14:02:47 +00002628 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002629 break;
2630 }
anthonyebb73a22012-03-22 14:25:52 +00002631 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002632 }
2633 case 'i':
2634 {
anthonyafa3dfc2012-03-03 11:31:30 +00002635 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002636 {
anthony31f1bf72012-01-30 12:37:22 +00002637 const char
2638 *format,
anthony805a2d42011-09-25 08:25:12 +00002639 *text;
2640
anthony92c93bd2012-03-19 14:02:47 +00002641 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002642 if (format == (char *) NULL)
2643 {
anthony92c93bd2012-03-19 14:02:47 +00002644 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2645 _exception);
anthony805a2d42011-09-25 08:25:12 +00002646 break;
2647 }
anthony92c93bd2012-03-19 14:02:47 +00002648 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002649 if (text == (char *) NULL)
2650 break;
2651 (void) fputs(text,stdout);
2652 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002653 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002654 break;
2655 }
anthonyafa3dfc2012-03-03 11:31:30 +00002656 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002657 {
anthonyfe1aa782012-03-24 13:43:04 +00002658 if (IsGeometry(arg1) == MagickFalse)
2659 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002660 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002661 new_image=ImplodeImage(_image,geometry_info.rho,
2662 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002663 break;
2664 }
anthonyafa3dfc2012-03-03 11:31:30 +00002665 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002666 {
anthonyfe1aa782012-03-24 13:43:04 +00002667 /* FUTURE: New to IMv7
2668 Roll into a resize special operator */
2669 if (IsGeometry(arg1) == MagickFalse)
2670 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002671 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2672 new_image=InterpolativeResizeImage(_image,geometry.width,
2673 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002674 break;
2675 }
anthonyebb73a22012-03-22 14:25:52 +00002676 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002677 }
2678 case 'l':
2679 {
anthonyafa3dfc2012-03-03 11:31:30 +00002680 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002681 {
anthonyfe1aa782012-03-24 13:43:04 +00002682 if (IsGeometry(arg1) == MagickFalse)
2683 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002684 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002685 if ((flags & PercentValue) != 0)
2686 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002687 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002688 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002689 _exception);
anthony805a2d42011-09-25 08:25:12 +00002690 break;
2691 }
anthonyafa3dfc2012-03-03 11:31:30 +00002692 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002693 {
2694 MagickRealType
2695 black_point,
2696 gamma,
2697 white_point;
2698
2699 MagickStatusType
2700 flags;
2701
anthonyfe1aa782012-03-24 13:43:04 +00002702 if (IsGeometry(arg1) == MagickFalse)
2703 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002704 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002705 black_point=geometry_info.rho;
2706 white_point=(MagickRealType) QuantumRange;
2707 if ((flags & SigmaValue) != 0)
2708 white_point=geometry_info.sigma;
2709 gamma=1.0;
2710 if ((flags & XiValue) != 0)
2711 gamma=geometry_info.xi;
2712 if ((flags & PercentValue) != 0)
2713 {
2714 black_point*=(MagickRealType) (QuantumRange/100.0);
2715 white_point*=(MagickRealType) (QuantumRange/100.0);
2716 }
2717 if ((flags & SigmaValue) == 0)
2718 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002719 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002720 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002721 else
anthony92c93bd2012-03-19 14:02:47 +00002722 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002723 break;
2724 }
anthonyafa3dfc2012-03-03 11:31:30 +00002725 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002726 {
2727 char
2728 token[MaxTextExtent];
2729
2730 const char
2731 *p;
2732
2733 PixelInfo
2734 black_point,
2735 white_point;
2736
anthonyfd706f92012-01-19 04:22:02 +00002737 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002738 GetMagickToken(p,&p,token); /* get black point color */
2739 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002740 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002741 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002742 else
cristy269c9412011-10-13 23:41:15 +00002743 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002744 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002745 if (isalpha((int) token[0]) || (token[0] == '#'))
2746 GetMagickToken(p,&p,token);
2747 if (*token == '\0')
2748 white_point=black_point; /* set everything to that color */
2749 else
2750 {
2751 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2752 GetMagickToken(p,&p,token); /* Get white point color. */
2753 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002754 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002755 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002756 else
cristy269c9412011-10-13 23:41:15 +00002757 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002758 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002759 }
anthony92c93bd2012-03-19 14:02:47 +00002760 (void) LevelImageColors(_image,&black_point,&white_point,
2761 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002762 break;
2763 }
anthonyafa3dfc2012-03-03 11:31:30 +00002764 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002765 {
2766 double
2767 black_point,
2768 white_point;
2769
2770 MagickStatusType
2771 flags;
2772
anthonyfe1aa782012-03-24 13:43:04 +00002773 if (IsGeometry(arg1) == MagickFalse)
2774 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002775 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002776 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002777 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002778 if ((flags & SigmaValue) != 0)
2779 white_point=geometry_info.sigma;
2780 if ((flags & PercentValue) != 0)
2781 {
anthony92c93bd2012-03-19 14:02:47 +00002782 black_point*=(double) _image->columns*_image->rows/100.0;
2783 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002784 }
2785 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002786 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002787 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002788 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002789 break;
2790 }
anthonyafa3dfc2012-03-03 11:31:30 +00002791 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002792 {
anthonyfe1aa782012-03-24 13:43:04 +00002793 /* FUTURE: Roll into a resize special operator */
2794 if (IsGeometry(arg1) == MagickFalse)
2795 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002796 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002797 if ((flags & XValue) == 0)
2798 geometry.x=1;
2799 if ((flags & YValue) == 0)
2800 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002801 new_image=LiquidRescaleImage(_image,geometry.width,
2802 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002803 break;
2804 }
anthonyafa3dfc2012-03-03 11:31:30 +00002805 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002806 {
anthony92c93bd2012-03-19 14:02:47 +00002807 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002808 break;
2809 }
anthonyebb73a22012-03-22 14:25:52 +00002810 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002811 }
2812 case 'm':
2813 {
anthonyafa3dfc2012-03-03 11:31:30 +00002814 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002815 {
2816 Image
2817 *remap_image;
2818
anthony31f1bf72012-01-30 12:37:22 +00002819 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002820 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002821 if (remap_image == (Image *) NULL)
2822 break;
anthony92c93bd2012-03-19 14:02:47 +00002823 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002824 remap_image=DestroyImage(remap_image);
2825 break;
2826 }
anthonyafa3dfc2012-03-03 11:31:30 +00002827 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002828 {
2829 Image
2830 *mask;
2831
anthonyafa3dfc2012-03-03 11:31:30 +00002832 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002833 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002834 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002835 break;
2836 }
anthony5330ae02012-03-20 14:17:01 +00002837 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002838 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002839 if (mask == (Image *) NULL)
2840 break;
anthony92c93bd2012-03-19 14:02:47 +00002841 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002842 mask=DestroyImage(mask);
2843 break;
2844 }
anthonyafa3dfc2012-03-03 11:31:30 +00002845 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002846 {
anthony31f1bf72012-01-30 12:37:22 +00002847 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002848 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2849 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002850 break;
2851 }
anthonya3ef4ed2012-03-17 06:52:53 +00002852 if (LocaleCompare("median",option+1) == 0)
2853 {
2854 /* DEPRECIATED - use -statistic Median */
anthony7bc87992012-03-25 02:32:51 +00002855 if (IsGeometry(arg1) == MagickFalse)
2856 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya3ef4ed2012-03-17 06:52:53 +00002857 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2858 break;
2859 }
anthonyafa3dfc2012-03-03 11:31:30 +00002860 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002861 {
anthony7bc87992012-03-25 02:32:51 +00002862 if (IsGeometry(arg1) == MagickFalse)
2863 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002864 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002865 if ((flags & SigmaValue) == 0)
2866 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002867 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2868 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002869 break;
2870 }
anthonyafa3dfc2012-03-03 11:31:30 +00002871 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002872 {
anthony7bc87992012-03-25 02:32:51 +00002873 if (IsGeometry(arg1) == MagickFalse)
2874 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002875 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002876 break;
2877 }
anthonyafa3dfc2012-03-03 11:31:30 +00002878 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002879 {
anthony92c93bd2012-03-19 14:02:47 +00002880 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002881 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002882 break;
2883 }
anthonyafa3dfc2012-03-03 11:31:30 +00002884 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002885 {
anthony92c93bd2012-03-19 14:02:47 +00002886 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002887 break;
2888 }
anthonyafa3dfc2012-03-03 11:31:30 +00002889 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002890 {
2891 char
2892 token[MaxTextExtent];
2893
2894 const char
2895 *p;
2896
2897 KernelInfo
2898 *kernel;
2899
anthony805a2d42011-09-25 08:25:12 +00002900 ssize_t
2901 iterations;
2902
anthonyfd706f92012-01-19 04:22:02 +00002903 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002904 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002905 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2906 if ( parse < 0 )
2907 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2908 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002909 iterations=1L;
2910 GetMagickToken(p,&p,token);
2911 if ((*p == ':') || (*p == ','))
2912 GetMagickToken(p,&p,token);
2913 if ((*p != '\0'))
2914 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002915 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002916 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002917 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2918 option,arg2);
2919 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2920 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002921 kernel=DestroyKernelInfo(kernel);
2922 break;
2923 }
anthonyafa3dfc2012-03-03 11:31:30 +00002924 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002925 {
anthony7bc87992012-03-25 02:32:51 +00002926 if (IsGeometry(arg1) == MagickFalse)
2927 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002928 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002929 if ((flags & SigmaValue) == 0)
2930 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002931 new_image=MotionBlurImage(_image,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002932 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
anthony92c93bd2012-03-19 14:02:47 +00002933 _exception);
anthony805a2d42011-09-25 08:25:12 +00002934 break;
2935 }
anthonyebb73a22012-03-22 14:25:52 +00002936 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002937 }
2938 case 'n':
2939 {
anthonyafa3dfc2012-03-03 11:31:30 +00002940 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002941 {
anthony92c93bd2012-03-19 14:02:47 +00002942 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002943 break;
2944 }
anthonyafa3dfc2012-03-03 11:31:30 +00002945 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002946 {
anthonyafa3dfc2012-03-03 11:31:30 +00002947 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002948 {
anthony7bc87992012-03-25 02:32:51 +00002949 if (IsGeometry(arg1) == MagickFalse)
2950 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002951 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002952 if ((flags & SigmaValue) == 0)
2953 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002954 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2955 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002956 }
2957 else
2958 {
anthony31f1bf72012-01-30 12:37:22 +00002959 double
2960 attenuate;
2961
2962 const char*
2963 value;
2964
anthony7bc87992012-03-25 02:32:51 +00002965 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2966 if ( parse < 0 )
2967 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2968 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002969 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002970 if (value != (const char *) NULL)
2971 attenuate=StringToDouble(value,(char **) NULL);
2972 else
2973 attenuate=1.0;
2974
anthony7bc87992012-03-25 02:32:51 +00002975 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2976 _exception);
anthony805a2d42011-09-25 08:25:12 +00002977 }
2978 break;
2979 }
anthonyafa3dfc2012-03-03 11:31:30 +00002980 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002981 {
anthony92c93bd2012-03-19 14:02:47 +00002982 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002983 break;
2984 }
anthonyebb73a22012-03-22 14:25:52 +00002985 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002986 }
2987 case 'o':
2988 {
anthonyafa3dfc2012-03-03 11:31:30 +00002989 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002990 {
2991 PixelInfo
2992 target;
2993
anthony92c93bd2012-03-19 14:02:47 +00002994 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2995 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2996 _exception);
anthony805a2d42011-09-25 08:25:12 +00002997 break;
2998 }
anthonyafa3dfc2012-03-03 11:31:30 +00002999 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003000 {
anthony92c93bd2012-03-19 14:02:47 +00003001 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003002 break;
3003 }
anthonyebb73a22012-03-22 14:25:52 +00003004 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003005 }
3006 case 'p':
3007 {
anthonyafa3dfc2012-03-03 11:31:30 +00003008 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003009 {
anthonyfd706f92012-01-19 04:22:02 +00003010 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003011 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
3012 _exception);
anthony805a2d42011-09-25 08:25:12 +00003013 break;
3014 }
anthonyafa3dfc2012-03-03 11:31:30 +00003015 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003016 {
cristye9e3d382011-12-14 01:50:13 +00003017 const char
3018 *caption;
3019
anthony805a2d42011-09-25 08:25:12 +00003020 double
3021 angle;
3022
anthony7bc87992012-03-25 02:32:51 +00003023 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00003024 RandomInfo
3025 *random_info;
anthony805a2d42011-09-25 08:25:12 +00003026
anthonyf42014d2012-03-25 09:53:06 +00003027 random_info=AcquireRandomInfo();
3028 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
3029 random_info=DestroyRandomInfo(random_info);
3030 }
anthony7bc87992012-03-25 02:32:51 +00003031 else {
anthonyf42014d2012-03-25 09:53:06 +00003032 if (IsGeometry(arg1) == MagickFalse)
3033 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3034 flags=ParseGeometry(arg1,&geometry_info);
3035 angle=geometry_info.rho;
3036 }
anthony92c93bd2012-03-19 14:02:47 +00003037 caption=GetImageProperty(_image,"caption",_exception);
3038 new_image=PolaroidImage(_image,_draw_info,caption,angle,
3039 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003040 break;
3041 }
anthonyafa3dfc2012-03-03 11:31:30 +00003042 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003043 {
anthony7bc87992012-03-25 02:32:51 +00003044 if (IsGeometry(arg1) == MagickFalse)
3045 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003046 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003047 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
3048 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00003049 break;
3050 }
anthonyafa3dfc2012-03-03 11:31:30 +00003051 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003052 {
anthony31f1bf72012-01-30 12:37:22 +00003053 /* FUTURE: should be a 'Genesis' option?
3054 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00003055 Why???
cristy947cb4c2011-10-20 18:41:46 +00003056 */
anthony7bc87992012-03-25 02:32:51 +00003057 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
3058 if ( parse < 0 )
3059 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
3060 option,arg1);
3061 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003062 break;
3063 }
anthonyafa3dfc2012-03-03 11:31:30 +00003064 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003065 {
3066 const char
3067 *name;
3068
3069 const StringInfo
3070 *profile;
3071
3072 Image
3073 *profile_image;
3074
3075 ImageInfo
3076 *profile_info;
3077
anthonyafa3dfc2012-03-03 11:31:30 +00003078 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003079 { /* Remove a profile from the _image. */
3080 (void) ProfileImage(_image,arg1,(const unsigned char *)
3081 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003082 break;
3083 }
anthony92c93bd2012-03-19 14:02:47 +00003084 /* Associate a profile with the _image. */
3085 profile_info=CloneImageInfo(_image_info);
3086 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003087 if (profile != (StringInfo *) NULL)
3088 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003089 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003090 profile_info=DestroyImageInfo(profile_info);
3091 if (profile_image == (Image *) NULL)
3092 {
3093 StringInfo
3094 *profile;
3095
anthony92c93bd2012-03-19 14:02:47 +00003096 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003097 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00003098 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00003099 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003100 if (profile != (StringInfo *) NULL)
3101 {
anthony92c93bd2012-03-19 14:02:47 +00003102 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003103 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003104 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003105 profile=DestroyStringInfo(profile);
3106 }
3107 profile_info=DestroyImageInfo(profile_info);
3108 break;
3109 }
3110 ResetImageProfileIterator(profile_image);
3111 name=GetNextImageProfile(profile_image);
3112 while (name != (const char *) NULL)
3113 {
3114 profile=GetImageProfile(profile_image,name);
3115 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003116 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3117 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003118 name=GetNextImageProfile(profile_image);
3119 }
3120 profile_image=DestroyImage(profile_image);
3121 break;
3122 }
anthonyebb73a22012-03-22 14:25:52 +00003123 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003124 }
anthony805a2d42011-09-25 08:25:12 +00003125 case 'r':
3126 {
anthonyafa3dfc2012-03-03 11:31:30 +00003127 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003128 {
anthonyf42014d2012-03-25 09:53:06 +00003129 if (IsGeometry(arg1) == MagickFalse)
3130 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003131 flags=ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003132 new_image=RadialBlurImage(_image,geometry_info.rho,
3133 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003134 break;
3135 }
anthonyafa3dfc2012-03-03 11:31:30 +00003136 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003137 {
anthonyf42014d2012-03-25 09:53:06 +00003138 if (IsGeometry(arg1) == MagickFalse)
3139 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003140 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003141 if ((flags & SigmaValue) == 0)
3142 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00003143 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003144 break;
3145 }
anthonyafa3dfc2012-03-03 11:31:30 +00003146 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003147 {
anthonyf42014d2012-03-25 09:53:06 +00003148 if (IsGeometry(arg1) == MagickFalse)
3149 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003150 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003151 break;
3152 }
anthonyafa3dfc2012-03-03 11:31:30 +00003153 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003154 {
3155 Image
3156 *remap_image;
3157
anthony92c93bd2012-03-19 14:02:47 +00003158 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003159 if (remap_image == (Image *) NULL)
3160 break;
anthony92c93bd2012-03-19 14:02:47 +00003161 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003162 remap_image=DestroyImage(remap_image);
3163 break;
3164 }
anthonyafa3dfc2012-03-03 11:31:30 +00003165 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003166 {
anthonyafa3dfc2012-03-03 11:31:30 +00003167 if (IfNormalOp)
anthonyf42014d2012-03-25 09:53:06 +00003168 if (IsGeometry(arg1) == MagickFalse)
3169 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003170 (void) ResetImagePage(_image,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003171 else
anthony92c93bd2012-03-19 14:02:47 +00003172 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003173 break;
3174 }
anthonyafa3dfc2012-03-03 11:31:30 +00003175 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003176 {
anthonyf42014d2012-03-25 09:53:06 +00003177 /* FUTURE: remove blur arguemnt - no longer used
3178 Roll into a resize special operation */
3179 if (IsGeometry(arg1) == MagickFalse)
3180 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003181 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003182 if ((flags & SigmaValue) == 0)
3183 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003184 new_image=ResampleImage(_image,geometry_info.rho,
3185 geometry_info.sigma,_image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003186 break;
3187 }
anthonyafa3dfc2012-03-03 11:31:30 +00003188 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003189 {
anthonyafbaed72011-10-26 12:05:04 +00003190 /* FUTURE: remove blur argument - no longer used */
anthonyf42014d2012-03-25 09:53:06 +00003191 if (IsGeometry(arg1) == MagickFalse)
3192 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003193 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3194 new_image=ResizeImage(_image,geometry.width,geometry.height,
3195 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003196 break;
3197 }
anthonyafa3dfc2012-03-03 11:31:30 +00003198 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003199 {
anthonyf42014d2012-03-25 09:53:06 +00003200 if (IsGeometry(arg1) == MagickFalse)
3201 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003202 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3203 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003204 break;
3205 }
anthonyafa3dfc2012-03-03 11:31:30 +00003206 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003207 {
anthonyf42014d2012-03-25 09:53:06 +00003208 if (IsGeometry(arg1) == MagickFalse)
3209 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003210 if (strchr(arg1,'>') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003211 if (_image->columns <= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003212 break;
anthonyfd706f92012-01-19 04:22:02 +00003213 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003214 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003215 break;
anthonyfd706f92012-01-19 04:22:02 +00003216 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003217 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003218 break;
3219 }
anthonyebb73a22012-03-22 14:25:52 +00003220 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003221 }
3222 case 's':
3223 {
anthonyafa3dfc2012-03-03 11:31:30 +00003224 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003225 {
anthonyfe1aa782012-03-24 13:43:04 +00003226 /* FUTURE: Roll into a resize special operator */
anthonyf42014d2012-03-25 09:53:06 +00003227 if (IsGeometry(arg1) == MagickFalse)
3228 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003229 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3230 new_image=SampleImage(_image,geometry.width,geometry.height,
3231 _exception);
anthony805a2d42011-09-25 08:25:12 +00003232 break;
3233 }
anthonyafa3dfc2012-03-03 11:31:30 +00003234 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003235 {
anthonyfe1aa782012-03-24 13:43:04 +00003236 /* FUTURE: Roll into a resize special operator */
anthonyf42014d2012-03-25 09:53:06 +00003237 if (IsGeometry(arg1) == MagickFalse)
3238 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003239 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3240 new_image=ScaleImage(_image,geometry.width,geometry.height,
3241 _exception);
anthony805a2d42011-09-25 08:25:12 +00003242 break;
3243 }
anthonyf42014d2012-03-25 09:53:06 +00003244 if (LocaleCompare("segment",option+1) == 0)
3245 {
3246 if (IsGeometry(arg1) == MagickFalse)
3247 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3248 flags=ParseGeometry(arg1,&geometry_info);
3249 if ((flags & SigmaValue) == 0)
3250 geometry_info.sigma=1.0;
3251 (void) SegmentImage(_image,_image->colorspace,
3252 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3253 _exception);
3254 break;
3255 }
anthonyafa3dfc2012-03-03 11:31:30 +00003256 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003257 {
anthonyf42014d2012-03-25 09:53:06 +00003258 if (IsGeometry(arg1) == MagickFalse)
3259 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003260 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003261 if ((flags & PercentValue) != 0)
3262 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003263 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3264 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003265 break;
3266 }
anthonyafa3dfc2012-03-03 11:31:30 +00003267 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003268 {
anthony31f1bf72012-01-30 12:37:22 +00003269 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003270 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003271 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003272 break;
3273 }
anthonyafa3dfc2012-03-03 11:31:30 +00003274 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003275 {
anthonyf42014d2012-03-25 09:53:06 +00003276 if (IsGeometry(arg1) == MagickFalse)
3277 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3278 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3279 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003280 break;
3281 }
anthonyafa3dfc2012-03-03 11:31:30 +00003282 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003283 {
3284 char
3285 *value;
3286
anthonyf42014d2012-03-25 09:53:06 +00003287 if (IfPlusOp) {
anthonyfd706f92012-01-19 04:22:02 +00003288 if (LocaleNCompare(arg1,"registry:",9) == 0)
3289 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003290 else
anthony31f1bf72012-01-30 12:37:22 +00003291 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003292 {
anthony92c93bd2012-03-19 14:02:47 +00003293 (void) DeleteImageOption(_image_info,arg1+7);
3294 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003295 }
3296 else
anthony92c93bd2012-03-19 14:02:47 +00003297 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003298 break;
3299 }
anthonyf42014d2012-03-25 09:53:06 +00003300 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003301 if (value == (char *) NULL)
3302 break;
anthonyfd706f92012-01-19 04:22:02 +00003303 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003304 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003305 else
anthonyfd706f92012-01-19 04:22:02 +00003306 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003307 {
anthony92c93bd2012-03-19 14:02:47 +00003308 (void) SetImageOption(_image_info,arg1+7,value);
3309 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003310 }
3311 else
anthony92c93bd2012-03-19 14:02:47 +00003312 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003313 value=DestroyString(value);
3314 break;
3315 }
anthonyafa3dfc2012-03-03 11:31:30 +00003316 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003317 {
anthonyf42014d2012-03-25 09:53:06 +00003318 if (IsGeometry(arg1) == MagickFalse)
3319 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003320 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003321 if ((flags & SigmaValue) == 0)
3322 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003323 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3324 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003325 break;
3326 }
anthonyafa3dfc2012-03-03 11:31:30 +00003327 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003328 {
anthonyf42014d2012-03-25 09:53:06 +00003329 if (IsGeometry(arg1) == MagickFalse)
3330 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003331 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003332 if ((flags & SigmaValue) == 0)
3333 geometry_info.sigma=1.0;
3334 if ((flags & XiValue) == 0)
3335 geometry_info.xi=4.0;
3336 if ((flags & PsiValue) == 0)
3337 geometry_info.psi=4.0;
anthony92c93bd2012-03-19 14:02:47 +00003338 new_image=ShadowImage(_image,geometry_info.rho,
3339 geometry_info.sigma,_image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003340 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
anthony92c93bd2012-03-19 14:02:47 +00003341 _exception);
anthony805a2d42011-09-25 08:25:12 +00003342 break;
3343 }
anthonyafa3dfc2012-03-03 11:31:30 +00003344 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003345 {
anthonyf42014d2012-03-25 09:53:06 +00003346 if (IsGeometry(arg1) == MagickFalse)
3347 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003348 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003349 if ((flags & SigmaValue) == 0)
3350 geometry_info.sigma=1.0;
3351 if ((flags & XiValue) == 0)
3352 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00003353 new_image=SharpenImage(_image,geometry_info.rho,
3354 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003355 break;
3356 }
anthonyafa3dfc2012-03-03 11:31:30 +00003357 if (LocaleCompare("shave",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);
anthony92c93bd2012-03-19 14:02:47 +00003361 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3362 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003363 break;
3364 }
anthonyafa3dfc2012-03-03 11:31:30 +00003365 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003366 {
anthonyf42014d2012-03-25 09:53:06 +00003367 if (IsGeometry(arg1) == MagickFalse)
3368 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003369 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003370 if ((flags & SigmaValue) == 0)
3371 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003372 new_image=ShearImage(_image,geometry_info.rho,
3373 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003374 break;
3375 }
anthonyafa3dfc2012-03-03 11:31:30 +00003376 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003377 {
anthonyf42014d2012-03-25 09:53:06 +00003378 if (IsGeometry(arg1) == MagickFalse)
3379 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003380 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003381 if ((flags & SigmaValue) == 0)
3382 geometry_info.sigma=(double) QuantumRange/2.0;
3383 if ((flags & PercentValue) != 0)
3384 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3385 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003386 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003387 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003388 _exception);
anthony805a2d42011-09-25 08:25:12 +00003389 break;
3390 }
anthonyafa3dfc2012-03-03 11:31:30 +00003391 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003392 {
anthonyf42014d2012-03-25 09:53:06 +00003393 if (IsGeometry(arg1) == MagickFalse)
3394 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003395 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003396 if ((flags & SigmaValue) == 0)
3397 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003398 new_image=SketchImage(_image,geometry_info.rho,
3399 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003400 break;
3401 }
anthonyafa3dfc2012-03-03 11:31:30 +00003402 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003403 {
anthonyf42014d2012-03-25 09:53:06 +00003404 if (IsGeometry(arg1) == MagickFalse)
3405 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003406 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3407 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003408 break;
3409 }
anthonyafa3dfc2012-03-03 11:31:30 +00003410 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003411 {
anthony805a2d42011-09-25 08:25:12 +00003412 char
3413 *arguments;
3414
anthonyf42014d2012-03-25 09:53:06 +00003415 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3416 if ( parse < 0 )
3417 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3418 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003419 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003420 if (arguments == (char *) NULL)
anthonyf42014d2012-03-25 09:53:06 +00003421 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3422 new_image=SparseColorOption(_image,(SparseColorMethod)parse,
3423 arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003424 arguments=DestroyString(arguments);
3425 break;
3426 }
anthonyafa3dfc2012-03-03 11:31:30 +00003427 if (LocaleCompare("splice",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);
anthony92c93bd2012-03-19 14:02:47 +00003431 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3432 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003433 break;
3434 }
anthonyafa3dfc2012-03-03 11:31:30 +00003435 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003436 {
anthonyf42014d2012-03-25 09:53:06 +00003437 if (IsGeometry(arg1) == MagickFalse)
3438 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003439 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003440 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3441 _exception);
anthony805a2d42011-09-25 08:25:12 +00003442 break;
3443 }
anthonyafa3dfc2012-03-03 11:31:30 +00003444 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003445 {
anthony7bc87992012-03-25 02:32:51 +00003446 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3447 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003448 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003449 option,arg1);
3450 if (IsGeometry(arg2) == MagickFalse)
3451 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00003452 (void) ParseGeometry(arg2,&geometry_info);
anthony7bc87992012-03-25 02:32:51 +00003453 new_image=StatisticImage(_image,(StatisticType)parse,
3454 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3455 _exception);
anthony805a2d42011-09-25 08:25:12 +00003456 break;
3457 }
anthonyafa3dfc2012-03-03 11:31:30 +00003458 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003459 {
anthony92c93bd2012-03-19 14:02:47 +00003460 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003461 break;
3462 }
anthonyafa3dfc2012-03-03 11:31:30 +00003463 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003464 {
anthonyf42014d2012-03-25 09:53:06 +00003465 if (IsGeometry(arg1) == MagickFalse)
3466 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003467 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003468 new_image=SwirlImage(_image,geometry_info.rho,
3469 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003470 break;
3471 }
anthonyebb73a22012-03-22 14:25:52 +00003472 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003473 }
3474 case 't':
3475 {
anthonyafa3dfc2012-03-03 11:31:30 +00003476 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003477 {
3478 double
3479 threshold;
3480
anthonyafa3dfc2012-03-03 11:31:30 +00003481 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003482 threshold=(double) QuantumRange/2;
3483 else
anthonyfd706f92012-01-19 04:22:02 +00003484 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003485 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003486 break;
3487 }
anthonyafa3dfc2012-03-03 11:31:30 +00003488 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003489 {
anthony92c93bd2012-03-19 14:02:47 +00003490 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3491 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3492 _exception);
anthony805a2d42011-09-25 08:25:12 +00003493 break;
3494 }
anthonyafa3dfc2012-03-03 11:31:30 +00003495 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003496 {
anthony92c93bd2012-03-19 14:02:47 +00003497 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003498 break;
3499 }
anthonyafa3dfc2012-03-03 11:31:30 +00003500 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003501 {
anthonya3ef4ed2012-03-17 06:52:53 +00003502 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony92c93bd2012-03-19 14:02:47 +00003503 new_image=AffineTransformImage(_image,&_draw_info->affine,
3504 _exception);
anthony805a2d42011-09-25 08:25:12 +00003505 break;
3506 }
anthonyafa3dfc2012-03-03 11:31:30 +00003507 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003508 {
3509 PixelInfo
3510 target;
3511
anthony92c93bd2012-03-19 14:02:47 +00003512 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3513 (void) TransparentPaintImage(_image,&target,(Quantum)
3514 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003515 break;
3516 }
anthonyafa3dfc2012-03-03 11:31:30 +00003517 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003518 {
anthony92c93bd2012-03-19 14:02:47 +00003519 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003520 break;
3521 }
anthonyafa3dfc2012-03-03 11:31:30 +00003522 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003523 {
anthony92c93bd2012-03-19 14:02:47 +00003524 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003525 break;
3526 }
anthonyafa3dfc2012-03-03 11:31:30 +00003527 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003528 {
anthony92c93bd2012-03-19 14:02:47 +00003529 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003530 break;
3531 }
anthonyafa3dfc2012-03-03 11:31:30 +00003532 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003533 {
anthonyab3a50c2011-10-27 11:48:57 +00003534 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003535 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003536 break;
3537 }
anthonyebb73a22012-03-22 14:25:52 +00003538 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003539 }
3540 case 'u':
3541 {
anthonyafa3dfc2012-03-03 11:31:30 +00003542 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003543 {
anthony31f1bf72012-01-30 12:37:22 +00003544 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthony24aa8822012-03-11 00:56:06 +00003545 /* FUTURE: This option is not documented!!!!! */
anthonyafa3dfc2012-03-03 11:31:30 +00003546 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003547 {
anthony92c93bd2012-03-19 14:02:47 +00003548 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003549 break;
3550 }
anthony92c93bd2012-03-19 14:02:47 +00003551 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3552 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003553 break;
3554 }
anthonyafa3dfc2012-03-03 11:31:30 +00003555 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003556 {
anthony92c93bd2012-03-19 14:02:47 +00003557 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003558 break;
3559 }
anthonyafa3dfc2012-03-03 11:31:30 +00003560 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003561 {
anthonyfd706f92012-01-19 04:22:02 +00003562 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003563 if ((flags & SigmaValue) == 0)
3564 geometry_info.sigma=1.0;
3565 if ((flags & XiValue) == 0)
3566 geometry_info.xi=1.0;
3567 if ((flags & PsiValue) == 0)
3568 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003569 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3570 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003571 break;
3572 }
anthonyebb73a22012-03-22 14:25:52 +00003573 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003574 }
3575 case 'v':
3576 {
anthonyafa3dfc2012-03-03 11:31:30 +00003577 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003578 {
anthonyafa3dfc2012-03-03 11:31:30 +00003579 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003580 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003581 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003582 */
anthony92c93bd2012-03-19 14:02:47 +00003583 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003584 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003585 break;
3586 }
anthonyafa3dfc2012-03-03 11:31:30 +00003587 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003588 {
anthonyfd706f92012-01-19 04:22:02 +00003589 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003590 if ((flags & SigmaValue) == 0)
3591 geometry_info.sigma=1.0;
3592 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003593 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003594 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003595 geometry_info.psi=0.1*_image->rows;
3596 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3597 _image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3598 (ssize_t) ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003599 break;
3600 }
anthonyebb73a22012-03-22 14:25:52 +00003601 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003602 }
3603 case 'w':
3604 {
anthonyafa3dfc2012-03-03 11:31:30 +00003605 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003606 {
anthonyfd706f92012-01-19 04:22:02 +00003607 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003608 if ((flags & SigmaValue) == 0)
3609 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003610 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3611 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003612 break;
3613 }
anthonyafa3dfc2012-03-03 11:31:30 +00003614 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003615 {
anthony92c93bd2012-03-19 14:02:47 +00003616 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003617 break;
3618 }
anthonyebb73a22012-03-22 14:25:52 +00003619 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003620 }
3621 default:
anthonyebb73a22012-03-22 14:25:52 +00003622 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003623 }
3624 /*
3625 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003626 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003627 */
3628 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003629 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003630
anthony31f1bf72012-01-30 12:37:22 +00003631 return;
anthony92c93bd2012-03-19 14:02:47 +00003632#undef _image_info
3633#undef _draw_info
3634#undef _quantize_info
3635#undef _image
3636#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003637#undef IfNormalOp
3638#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003639#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003640#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003641}
anthonyfd706f92012-01-19 04:22:02 +00003642
anthony43f425d2012-02-26 12:58:58 +00003643WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003644 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003645{
3646 size_t
anthony43f425d2012-02-26 12:58:58 +00003647 n,
anthony31f1bf72012-01-30 12:37:22 +00003648 i;
3649
anthony43f425d2012-02-26 12:58:58 +00003650 assert(cli_wand != (MagickCLI *) NULL);
3651 assert(cli_wand->signature == WandSignature);
3652 assert(cli_wand->wand.signature == WandSignature);
3653 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3654 if (cli_wand->wand.debug != MagickFalse)
3655 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003656
anthonyafa3dfc2012-03-03 11:31:30 +00003657#if !USE_WAND_METHODS
3658 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003659 i=0;
anthony43f425d2012-02-26 12:58:58 +00003660 n=GetImageListLength(cli_wand->wand.images);
3661 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003662 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003663 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003664 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003665 if ( cli_wand->wand.images->next == (Image *) NULL )
3666 break;
3667 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003668 }
anthony43f425d2012-02-26 12:58:58 +00003669 assert( i == n );
3670 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003671#else
3672 MagickResetIterator(&cli_wand->wand);
3673 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3674 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3675 MagickResetIterator(&cli_wand->wand);
3676#endif
anthony31f1bf72012-01-30 12:37:22 +00003677 return;
anthony805a2d42011-09-25 08:25:12 +00003678}
3679
3680/*
3681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3682% %
3683% %
3684% %
anthony43f425d2012-02-26 12:58:58 +00003685+ 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 +00003686% %
3687% %
3688% %
3689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3690%
anthony43f425d2012-02-26 12:58:58 +00003691% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003692% entire image list as a whole. The result is often a complete replacment
3693% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003694%
3695% The format of the MogrifyImage method is:
3696%
anthony43f425d2012-02-26 12:58:58 +00003697% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003698% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003699%
3700% A description of each parameter follows:
3701%
anthony43f425d2012-02-26 12:58:58 +00003702% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003703%
anthony36a8c2c2012-02-10 00:08:44 +00003704% o option: The option string for the operation
3705%
anthony31f1bf72012-01-30 12:37:22 +00003706% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003707%
anthonyfe1aa782012-03-24 13:43:04 +00003708% NOTE: only "limit" uses two arguments.
anthony8b10b462012-02-08 12:32:44 +00003709%
3710% Example usage...
3711%
anthonyafa3dfc2012-03-03 11:31:30 +00003712% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3713% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003714%
anthony24aa8822012-03-11 00:56:06 +00003715% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003716%
anthony43f425d2012-02-26 12:58:58 +00003717% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003718% argc,argv
3719% i=index in argv
3720%
anthony2052d272012-02-28 12:48:29 +00003721% option_info = GetCommandOptionInfo(argv[i]);
3722% count=option_info->type;
3723% option_type=option_info->flags;
3724%
3725% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003726% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003727% count>=1 ? argv[i+1] : (char *)NULL,
3728% count>=2 ? argv[i+2] : (char *)NULL );
3729% i += count+1;
3730%
anthony805a2d42011-09-25 08:25:12 +00003731*/
anthony43f425d2012-02-26 12:58:58 +00003732WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003733 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003734{
anthony2a0ec8c2012-03-24 04:35:56 +00003735 ssize_t
3736 parse;
3737
anthony31f1bf72012-01-30 12:37:22 +00003738 Image
3739 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003740
anthony92c93bd2012-03-19 14:02:47 +00003741#define _image_info (cli_wand->wand.image_info)
3742#define _images (cli_wand->wand.images)
3743#define _exception (cli_wand->wand.exception)
3744#define _draw_info (cli_wand->draw_info)
3745#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003746#define IfNormalOp (*option=='-')
3747#define IfPlusOp (*option!='-')
3748#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003749
anthony43f425d2012-02-26 12:58:58 +00003750 assert(cli_wand != (MagickCLI *) NULL);
3751 assert(cli_wand->signature == WandSignature);
3752 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003753 assert(_images != (Image *) NULL); /* _images must be present */
anthony43f425d2012-02-26 12:58:58 +00003754 if (cli_wand->wand.debug != MagickFalse)
3755 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003756
anthony92c93bd2012-03-19 14:02:47 +00003757 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003758
3759 new_images=NewImageList();
3760
anthonyafa3dfc2012-03-03 11:31:30 +00003761 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003762 {
3763 case 'a':
3764 {
anthonyafa3dfc2012-03-03 11:31:30 +00003765 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003766 {
anthony92c93bd2012-03-19 14:02:47 +00003767 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003768 break;
3769 }
anthonyafa3dfc2012-03-03 11:31:30 +00003770 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003771 {
anthony31f1bf72012-01-30 12:37:22 +00003772 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003773 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003774 break;
3775 }
anthonyebb73a22012-03-22 14:25:52 +00003776 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003777 }
3778 case 'c':
3779 {
cristy5f257b22012-03-07 00:27:29 +00003780 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003781 {
anthony92c93bd2012-03-19 14:02:47 +00003782 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003783 break;
3784 }
anthonyafa3dfc2012-03-03 11:31:30 +00003785 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003786 {
anthony805a2d42011-09-25 08:25:12 +00003787 Image
anthony31f1bf72012-01-30 12:37:22 +00003788 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003789
anthonyafa3dfc2012-03-03 11:31:30 +00003790 /* FUTURE - make this a compose option, and thus can be used
3791 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003792 _images.
cristy87c02f42012-02-24 00:19:10 +00003793 */
anthony92c93bd2012-03-19 14:02:47 +00003794 new_images=RemoveFirstImageFromList(&_images);
3795 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003796 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003797 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003798 break;
anthony92c93bd2012-03-19 14:02:47 +00003799 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003800 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003801 break;
3802 }
anthonyafa3dfc2012-03-03 11:31:30 +00003803 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003804 {
anthony92c93bd2012-03-19 14:02:47 +00003805 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003806 break;
3807 }
anthonyafa3dfc2012-03-03 11:31:30 +00003808 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003809 {
anthony43f425d2012-02-26 12:58:58 +00003810 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003811 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003812 break;
3813 }
anthonyafa3dfc2012-03-03 11:31:30 +00003814 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003815 {
3816 Image
3817 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003818 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003819
3820 RectangleInfo
3821 geometry;
3822
anthony31f1bf72012-01-30 12:37:22 +00003823 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003824 compose;
3825
3826 const char*
3827 value;
3828
anthony92c93bd2012-03-19 14:02:47 +00003829 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003830 if (value != (const char *) NULL)
3831 compose=(CompositeOperator) ParseCommandOption(
3832 MagickComposeOptions,MagickFalse,value);
3833 else
anthony31f1bf72012-01-30 12:37:22 +00003834 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003835
anthony92c93bd2012-03-19 14:02:47 +00003836 new_images=RemoveFirstImageFromList(&_images);
3837 source_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003838 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003839 if (source_image == (Image *) NULL)
3840 break;
anthonye8f56492012-02-12 12:39:02 +00003841
anthony31f1bf72012-01-30 12:37:22 +00003842 /* FUTURE - this should not be here! - should be part of -geometry */
3843 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003844 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003845
anthony31f1bf72012-01-30 12:37:22 +00003846 SetGeometry(source_image,&geometry);
3847 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3848 GravityAdjustGeometry(new_images->columns,new_images->rows,
3849 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003850
anthony92c93bd2012-03-19 14:02:47 +00003851 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003852 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003853 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003854 if ((compose == DisplaceCompositeOp) ||
3855 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003856 { /* Merge Y displacement into X displace/distort map. */
3857 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony92c93bd2012-03-19 14:02:47 +00003858 mask_image,0,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003859 mask_image=DestroyImage(mask_image);
3860 }
3861 else
3862 {
3863 /*
3864 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003865 */
anthony92c93bd2012-03-19 14:02:47 +00003866 (void) NegateImage(mask_image,MagickFalse,_exception);
3867 (void) SetImageMask(new_images,mask_image,_exception);
cristy1539afd2012-01-30 01:32:59 +00003868 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003869 }
3870 }
anthony31f1bf72012-01-30 12:37:22 +00003871 (void) CompositeImage(new_images,compose,source_image,geometry.x,
anthony92c93bd2012-03-19 14:02:47 +00003872 geometry.y,_exception);
3873 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003874 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003875 break;
3876 }
anthonyebb73a22012-03-22 14:25:52 +00003877 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003878 }
3879 case 'd':
3880 {
anthonyafa3dfc2012-03-03 11:31:30 +00003881 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003882 {
anthony31f1bf72012-01-30 12:37:22 +00003883 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003884 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003885 break;
3886 }
anthonyafa3dfc2012-03-03 11:31:30 +00003887 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003888 {
anthonyafa3dfc2012-03-03 11:31:30 +00003889 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003890 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003891 else
anthony92c93bd2012-03-19 14:02:47 +00003892 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003893 break;
3894 }
anthonyafa3dfc2012-03-03 11:31:30 +00003895 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003896 {
anthonyafa3dfc2012-03-03 11:31:30 +00003897 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003898 {
3899 const char
3900 *p;
3901
3902 size_t
3903 number_duplicates;
3904
anthonyebb73a22012-03-22 14:25:52 +00003905 if (IsGeometry(arg1) == MagickFalse)
3906 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3907 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003908 number_duplicates=(size_t) StringToLong(arg1);
3909 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003910 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003911 new_images=DuplicateImages(_images,number_duplicates,"-1",
3912 _exception);
anthony805a2d42011-09-25 08:25:12 +00003913 else
anthony92c93bd2012-03-19 14:02:47 +00003914 new_images=DuplicateImages(_images,number_duplicates,p,
3915 _exception);
anthony805a2d42011-09-25 08:25:12 +00003916 }
anthonyafa3dfc2012-03-03 11:31:30 +00003917 else
anthony92c93bd2012-03-19 14:02:47 +00003918 new_images=DuplicateImages(_images,1,"-1",_exception);
3919 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003920 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003921 break;
3922 }
anthonyebb73a22012-03-22 14:25:52 +00003923 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003924 }
3925 case 'e':
3926 {
anthonyafa3dfc2012-03-03 11:31:30 +00003927 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003928 {
anthony2a0ec8c2012-03-24 04:35:56 +00003929 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3930 if ( parse < 0 )
3931 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3932 option,arg1);
3933 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3934 _exception);
anthony805a2d42011-09-25 08:25:12 +00003935 break;
3936 }
anthonyebb73a22012-03-22 14:25:52 +00003937 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003938 }
3939 case 'f':
3940 {
anthonyafa3dfc2012-03-03 11:31:30 +00003941 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003942 {
anthony92c93bd2012-03-19 14:02:47 +00003943 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003944 break;
3945 }
anthonyafa3dfc2012-03-03 11:31:30 +00003946 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003947 {
anthony319dac62012-03-06 04:12:44 +00003948 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003949 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003950 break;
3951 }
anthonyafa3dfc2012-03-03 11:31:30 +00003952 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003953 {
anthony92c93bd2012-03-19 14:02:47 +00003954 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003955 break;
3956 }
anthonyebb73a22012-03-22 14:25:52 +00003957 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003958 }
3959 case 'h':
3960 {
anthonyafa3dfc2012-03-03 11:31:30 +00003961 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003962 {
anthony31f1bf72012-01-30 12:37:22 +00003963 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003964 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003965 */
anthony805a2d42011-09-25 08:25:12 +00003966 Image
anthony31f1bf72012-01-30 12:37:22 +00003967 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003968
anthony92c93bd2012-03-19 14:02:47 +00003969 new_images=RemoveFirstImageFromList(&_images);
3970 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003971 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003972 break;
anthony92c93bd2012-03-19 14:02:47 +00003973 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003974 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003975 break;
3976 }
anthonyebb73a22012-03-22 14:25:52 +00003977 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003978 }
3979 case 'i':
3980 {
anthonyafa3dfc2012-03-03 11:31:30 +00003981 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003982 {
3983 Image
anthony805a2d42011-09-25 08:25:12 +00003984 *magnitude_image,
3985 *phase_image;
3986
anthony92c93bd2012-03-19 14:02:47 +00003987 magnitude_image=RemoveFirstImageFromList(&_images);
3988 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003989 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003990 if (phase_image == (Image *) NULL)
3991 break;
3992 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003993 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003994 magnitude_image=DestroyImage(magnitude_image);
3995 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003996 break;
3997 }
anthonyafa3dfc2012-03-03 11:31:30 +00003998 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003999 {
4000 Image
anthony31f1bf72012-01-30 12:37:22 +00004001 *insert_image,
4002 *index_image;
4003
4004 ssize_t
4005 index;
anthony805a2d42011-09-25 08:25:12 +00004006
anthonyfe1aa782012-03-24 13:43:04 +00004007 if (IfNormalOp && IsGeometry(arg1) == MagickFalse)
4008 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004009 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004010 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004011 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004012 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004013 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004014 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004015 PrependImageToList(&_images,insert_image);
4016 else if (index == (ssize_t) GetImageListLength(_images))
4017 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004018 else
anthony43f425d2012-02-26 12:58:58 +00004019 {
anthony92c93bd2012-03-19 14:02:47 +00004020 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004021 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004022 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004023 InsertImageInList(&index_image,insert_image);
4024 }
anthony92c93bd2012-03-19 14:02:47 +00004025 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004026 break;
4027 }
anthonyebb73a22012-03-22 14:25:52 +00004028 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004029 }
4030 case 'l':
4031 {
anthonyafa3dfc2012-03-03 11:31:30 +00004032 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004033 {
anthonyfe1aa782012-03-24 13:43:04 +00004034 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4035 if ( parse < 0 )
4036 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4037 option,arg1);
4038 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004039 {
4040 case CoalesceLayer:
4041 {
anthony92c93bd2012-03-19 14:02:47 +00004042 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004043 break;
4044 }
4045 case CompareAnyLayer:
4046 case CompareClearLayer:
4047 case CompareOverlayLayer:
4048 default:
4049 {
anthonyfe1aa782012-03-24 13:43:04 +00004050 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
4051 _exception);
anthony805a2d42011-09-25 08:25:12 +00004052 break;
4053 }
4054 case MergeLayer:
4055 case FlattenLayer:
4056 case MosaicLayer:
4057 case TrimBoundsLayer:
4058 {
anthonyfe1aa782012-03-24 13:43:04 +00004059 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
4060 _exception);
anthony805a2d42011-09-25 08:25:12 +00004061 break;
4062 }
4063 case DisposeLayer:
4064 {
anthony92c93bd2012-03-19 14:02:47 +00004065 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004066 break;
4067 }
4068 case OptimizeImageLayer:
4069 {
anthony92c93bd2012-03-19 14:02:47 +00004070 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004071 break;
4072 }
4073 case OptimizePlusLayer:
4074 {
anthony92c93bd2012-03-19 14:02:47 +00004075 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004076 break;
4077 }
4078 case OptimizeTransLayer:
4079 {
anthony92c93bd2012-03-19 14:02:47 +00004080 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004081 break;
4082 }
4083 case RemoveDupsLayer:
4084 {
anthony92c93bd2012-03-19 14:02:47 +00004085 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004086 break;
4087 }
4088 case RemoveZeroLayer:
4089 {
anthony92c93bd2012-03-19 14:02:47 +00004090 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004091 break;
4092 }
4093 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004094 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004095 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004096 if (new_images == (Image *) NULL)
4097 break;
anthony92c93bd2012-03-19 14:02:47 +00004098 _images=DestroyImageList(_images);
4099 _images=OptimizeImageLayers(new_images,_exception);
4100 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004101 break;
4102 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004103 OptimizeImageTransparency(_images,_exception);
4104 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4105 _exception);
anthony805a2d42011-09-25 08:25:12 +00004106 break;
4107 }
4108 case CompositeLayer:
4109 {
anthony805a2d42011-09-25 08:25:12 +00004110 Image
4111 *source;
4112
4113 RectangleInfo
4114 geometry;
4115
anthony31f1bf72012-01-30 12:37:22 +00004116 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004117 compose;
4118
4119 const char*
4120 value;
4121
anthony92c93bd2012-03-19 14:02:47 +00004122 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004123 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004124 if (value != (const char *) NULL)
4125 compose=(CompositeOperator) ParseCommandOption(
4126 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004127
anthony31f1bf72012-01-30 12:37:22 +00004128 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004129 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004130 while (source != (Image *) NULL)
4131 {
4132 source=GetNextImageInList(source);
4133 if ((source != (Image *) NULL) &&
4134 (LocaleCompare(source->magick,"NULL") == 0))
4135 break;
4136 }
4137 if (source != (Image *) NULL)
4138 {
4139 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4140 (GetNextImageInList(source) == (Image *) NULL))
4141 source=(Image *) NULL;
4142 else
anthony31f1bf72012-01-30 12:37:22 +00004143 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004144 source=SplitImageList(source->previous);
4145 DeleteImageFromList(&source);
4146 }
4147 }
4148 if (source == (Image *) NULL)
4149 {
anthony92c93bd2012-03-19 14:02:47 +00004150 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004151 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004152 break;
4153 }
anthony31f1bf72012-01-30 12:37:22 +00004154 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004155 SetGeometry(_images,&geometry);
4156 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004157 geometry.width=source->page.width != 0 ?
4158 source->page.width : source->columns;
4159 geometry.height=source->page.height != 0 ?
4160 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004161 GravityAdjustGeometry(_images->page.width != 0 ?
4162 _images->page.width : _images->columns,
4163 _images->page.height != 0 ? _images->page.height :
4164 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004165
anthony31f1bf72012-01-30 12:37:22 +00004166 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004167 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4168 _exception);
anthony805a2d42011-09-25 08:25:12 +00004169 source=DestroyImageList(source);
4170 break;
4171 }
4172 }
anthony805a2d42011-09-25 08:25:12 +00004173 break;
4174 }
anthonyafa3dfc2012-03-03 11:31:30 +00004175 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00004176 {
4177 MagickSizeType
4178 limit;
4179
anthony72feaa62012-01-17 06:46:23 +00004180 limit=MagickResourceInfinity;
anthonyfe1aa782012-03-24 13:43:04 +00004181 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4182 if ( parse < 0 )
4183 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4184 option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004185 if (LocaleCompare("unlimited",arg2) != 0)
4186 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthonyfe1aa782012-03-24 13:43:04 +00004187 (void) SetMagickResourceLimit((ResourceType)parse,limit);
anthony72feaa62012-01-17 06:46:23 +00004188 break;
4189 }
anthonyebb73a22012-03-22 14:25:52 +00004190 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004191 }
4192 case 'm':
4193 {
anthonyafa3dfc2012-03-03 11:31:30 +00004194 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004195 {
anthony31f1bf72012-01-30 12:37:22 +00004196 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004197 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004198 break;
4199 }
anthonyafa3dfc2012-03-03 11:31:30 +00004200 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004201 {
4202 Image
4203 *morph_image;
4204
anthony7bc87992012-03-25 02:32:51 +00004205 if (IsGeometry(arg1) == MagickFalse)
4206 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004207 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4208 _exception);
anthony805a2d42011-09-25 08:25:12 +00004209 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004210 break;
anthony92c93bd2012-03-19 14:02:47 +00004211 _images=DestroyImageList(_images);
4212 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004213 break;
4214 }
anthonyafa3dfc2012-03-03 11:31:30 +00004215 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004216 {
anthony319dac62012-03-06 04:12:44 +00004217 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00004218 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004219 break;
4220 }
anthonyebb73a22012-03-22 14:25:52 +00004221 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004222 }
4223 case 'p':
4224 {
anthonyafa3dfc2012-03-03 11:31:30 +00004225 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004226 {
4227 char
4228 *string;
4229
anthony92c93bd2012-03-19 14:02:47 +00004230 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004231 if (string == (char *) NULL)
4232 break;
4233 (void) FormatLocaleFile(stdout,"%s",string);
4234 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004235 break;
anthony805a2d42011-09-25 08:25:12 +00004236 }
anthonyafa3dfc2012-03-03 11:31:30 +00004237 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004238 {
4239 char
4240 **arguments;
4241
4242 int
4243 j,
4244 number_arguments;
4245
anthony31f1bf72012-01-30 12:37:22 +00004246 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004247 if (arguments == (char **) NULL)
4248 break;
anthony31f1bf72012-01-30 12:37:22 +00004249 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004250 {
4251 char
4252 breaker,
4253 quote,
4254 *token;
4255
4256 const char
4257 *arguments;
4258
4259 int
4260 next,
4261 status;
4262
4263 size_t
4264 length;
4265
4266 TokenInfo
4267 *token_info;
4268
4269 /*
anthony24aa8822012-03-11 00:56:06 +00004270 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004271 */
anthony31f1bf72012-01-30 12:37:22 +00004272 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004273 token=(char *) NULL;
4274 if (~length >= (MaxTextExtent-1))
4275 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4276 sizeof(*token));
4277 if (token == (char *) NULL)
4278 break;
4279 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004280 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004281 token_info=AcquireTokenInfo();
4282 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4283 "\"",'\0',&breaker,&next,&quote);
4284 token_info=DestroyTokenInfo(token_info);
4285 if (status == 0)
4286 {
4287 const char
4288 *argv;
4289
4290 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004291 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4292 _exception);
anthony805a2d42011-09-25 08:25:12 +00004293 }
4294 token=DestroyString(token);
4295 break;
4296 }
4297 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004298 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4299 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004300 for (j=0; j < number_arguments; j++)
4301 arguments[j]=DestroyString(arguments[j]);
4302 arguments=(char **) RelinquishMagickMemory(arguments);
4303 break;
4304 }
anthonyebb73a22012-03-22 14:25:52 +00004305 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004306 }
4307 case 'r':
4308 {
anthonyafa3dfc2012-03-03 11:31:30 +00004309 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004310 {
anthony92c93bd2012-03-19 14:02:47 +00004311 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004312 break;
4313 }
anthonyafa3dfc2012-03-03 11:31:30 +00004314 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004315 {
anthony92c93bd2012-03-19 14:02:47 +00004316 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004317 break;
4318 }
anthonyebb73a22012-03-22 14:25:52 +00004319 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004320 }
4321 case 's':
4322 {
anthonyafa3dfc2012-03-03 11:31:30 +00004323 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004324 {
4325 Image
4326 *smush_image;
4327
4328 ssize_t
4329 offset;
4330
anthonyf42014d2012-03-25 09:53:06 +00004331 if (IsGeometry(arg1) == MagickFalse)
4332 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004333 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004334 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004335 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004336 break;
anthony92c93bd2012-03-19 14:02:47 +00004337 _images=DestroyImageList(_images);
4338 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004339 break;
4340 }
anthonyafa3dfc2012-03-03 11:31:30 +00004341 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004342 {
4343 Image
4344 *p,
4345 *q,
4346 *swap;
4347
4348 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004349 index,
anthony805a2d42011-09-25 08:25:12 +00004350 swap_index;
4351
anthonyf42014d2012-03-25 09:53:06 +00004352 if (IsGeometry(arg1) == MagickFalse)
4353 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004354 index=-1;
4355 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004356 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004357 {
4358 GeometryInfo
4359 geometry_info;
4360
4361 MagickStatusType
4362 flags;
4363
4364 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004365 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004366 index=(ssize_t) geometry_info.rho;
4367 if ((flags & SigmaValue) != 0)
4368 swap_index=(ssize_t) geometry_info.sigma;
4369 }
anthony92c93bd2012-03-19 14:02:47 +00004370 p=GetImageFromList(_images,index);
4371 q=GetImageFromList(_images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004372 if ((p == (Image *) NULL) || (q == (Image *) NULL))
anthonyf42014d2012-03-25 09:53:06 +00004373 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004374 if (p == q)
anthonyf42014d2012-03-25 09:53:06 +00004375 break; /* same image - no-op - not an error */
anthony92c93bd2012-03-19 14:02:47 +00004376 swap=CloneImage(p,0,0,MagickTrue,_exception);
4377 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
anthony805a2d42011-09-25 08:25:12 +00004378 ReplaceImageInList(&q,swap);
anthony92c93bd2012-03-19 14:02:47 +00004379 _images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004380 break;
4381 }
anthonyebb73a22012-03-22 14:25:52 +00004382 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004383 }
4384 case 'w':
4385 {
anthonyafa3dfc2012-03-03 11:31:30 +00004386 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004387 {
4388 char
4389 key[MaxTextExtent];
4390
4391 Image
4392 *write_images;
4393
4394 ImageInfo
4395 *write_info;
4396
anthony31f1bf72012-01-30 12:37:22 +00004397 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004398 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004399 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004400 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004401 write_images=CloneImageList(_images,_exception);
4402 write_info=CloneImageInfo(_image_info);
4403 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004404 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004405 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004406 write_images=DestroyImageList(write_images);
4407 break;
4408 }
anthonyebb73a22012-03-22 14:25:52 +00004409 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004410 }
4411 default:
anthonyebb73a22012-03-22 14:25:52 +00004412 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004413 }
anthony31f1bf72012-01-30 12:37:22 +00004414 if (new_images == (Image *) NULL)
4415 return;
anthony805a2d42011-09-25 08:25:12 +00004416
anthony92c93bd2012-03-19 14:02:47 +00004417 if (_images != (Image *) NULL)
4418 _images=DestroyImageList(_images);
4419 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004420 return;
4421
anthony92c93bd2012-03-19 14:02:47 +00004422#undef _image_info
4423#undef _images
4424#undef _exception
4425#undef _draw_info
4426#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004427#undef IfNormalOp
4428#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004429#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004430}
anthony43f425d2012-02-26 12:58:58 +00004431
4432/*
4433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4434% %
4435% %
4436% %
4437+ C L I S p e c i a l O p e r a t i o n s %
4438% %
4439% %
4440% %
4441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4442%
4443% CLISpecialOption() Applies operations that may involve empty image lists
4444% and or stacks of image lists or image_info settings.
4445%
anthonyafa3dfc2012-03-03 11:31:30 +00004446% The classic operators of this type is -read, and image stack operators,
4447% which can be applied to empty image lists.
4448%
4449% Note: unlike other Operators, these may involve other special 'option'
4450% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004451%
4452% The format of the CLISpecialOption method is:
4453%
4454% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004455% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004456%
4457% A description of each parameter follows:
4458%
4459% o cli_wand: the main CLI Wand to use.
4460%
4461% o option: The special option (with any switch char) to process
4462%
anthony24aa8822012-03-11 00:56:06 +00004463% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004464%
anthony2052d272012-02-28 12:48:29 +00004465% Example Usage...
4466%
anthonyce8dcb32012-03-21 13:20:31 +00004467% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004468%
anthony24aa8822012-03-11 00:56:06 +00004469% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004470%
4471% cli_wand
4472% argc,argv
4473% i=index in argv
4474%
4475% option_info = GetCommandOptionInfo(argv[i]);
4476% count=option_info->type;
4477% option_type=option_info->flags;
4478%
4479% if ( (option_type & SpecialOptionFlag) != 0 )
4480% CLISpecialOperator(cli_wand,argv[i],
4481% count>=1 ? argv[i+1] : (char *)NULL);
4482% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004483%
4484*/
4485
anthony43f425d2012-02-26 12:58:58 +00004486WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004487 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004488{
anthony92c93bd2012-03-19 14:02:47 +00004489#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004490
4491 assert(cli_wand != (MagickCLI *) NULL);
4492 assert(cli_wand->signature == WandSignature);
4493 assert(cli_wand->wand.signature == WandSignature);
4494 if (cli_wand->wand.debug != MagickFalse)
4495 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4496
anthony24aa8822012-03-11 00:56:06 +00004497 if(cli_wand->wand.images != (Image *)NULL)
4498 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004499 _exception);
anthony24aa8822012-03-11 00:56:06 +00004500
anthonyce8dcb32012-03-21 13:20:31 +00004501 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
anthonyf42014d2012-03-25 09:53:06 +00004502 /* link image and setting stacks - option is itself saved on stack! */
anthonyce8dcb32012-03-21 13:20:31 +00004503 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4504 *option == '-' ? "true" : (char *) NULL);
4505 return;
4506 }
4507 if (LocaleCompare("(",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004508 /* stack 'push' images */
4509 Stack
4510 *node;
4511
4512 size_t
4513 size;
4514
anthony43f425d2012-02-26 12:58:58 +00004515 size=0;
4516 node=cli_wand->image_list_stack;
4517 for ( ; node != (Stack *)NULL; node=node->next)
4518 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004519 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004520 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004521 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4522 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004523 CLIWandExceptionReturn(ResourceLimitFatalError,
4524 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004525 node->data = (void *)cli_wand->wand.images;
4526 cli_wand->wand.images = NewImageList();
4527 node->next = cli_wand->image_list_stack;
4528 cli_wand->image_list_stack = node;
4529
4530 /* handle respect-parenthesis */
anthonyf42014d2012-03-25 09:53:06 +00004531 if (IsMagickTrue(GetImageOption(cli_wand->wand.image_info,
anthonyce8dcb32012-03-21 13:20:31 +00004532 "respect-parenthesis")) != MagickFalse )
anthonyf42014d2012-03-25 09:53:06 +00004533 option="{"; /* fall-thru so as to push image settings too */
anthony43f425d2012-02-26 12:58:58 +00004534 else
4535 return;
4536 }
anthonyce8dcb32012-03-21 13:20:31 +00004537 if (LocaleCompare("{",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004538 /* stack 'push' of image_info settings */
4539 Stack
4540 *node;
4541
4542 size_t
4543 size;
4544
4545 size=0;
4546 node=cli_wand->image_info_stack;
4547 for ( ; node != (Stack *)NULL; node=node->next)
4548 size++;
anthony92c93bd2012-03-19 14:02:47 +00004549 if ( size >= MAX_STACK_DEPTH )
anthony4d4f2c72012-03-22 03:22:03 +00004550 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004551 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004552 if (node == (Stack *) NULL)
4553 CLIWandExceptionReturn(ResourceLimitFatalError,
4554 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004555
4556 node->data = (void *)cli_wand->wand.image_info;
4557 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004558 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
anthony92c93bd2012-03-19 14:02:47 +00004559 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4560 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004561 cli_wand->wand.image_info = (ImageInfo *)node->data;
4562 node = (Stack *)RelinquishMagickMemory(node);
4563 return;
4564 }
anthony43f425d2012-02-26 12:58:58 +00004565
4566 node->next = cli_wand->image_info_stack;
4567 cli_wand->image_info_stack = node;
4568
4569 return;
4570 }
anthonyce8dcb32012-03-21 13:20:31 +00004571 if (LocaleCompare(")",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004572 /* pop images from stack */
4573 Stack
4574 *node;
4575
anthony43f425d2012-02-26 12:58:58 +00004576 node = (void *)cli_wand->image_list_stack;
4577 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004578 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004579 cli_wand->image_list_stack = node->next;
4580
4581 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4582 cli_wand->wand.images= (Image *)node->data;
4583 node = (Stack *)RelinquishMagickMemory(node);
4584
anthony4d4f2c72012-03-22 03:22:03 +00004585 /* handle respect-parenthesis - of the previous 'pushed' settings */
anthony43f425d2012-02-26 12:58:58 +00004586 node = cli_wand->image_info_stack;
4587 if ( node != (Stack *)NULL)
4588 {
anthonyce8dcb32012-03-21 13:20:31 +00004589 if (IsMagickTrue(GetImageOption((ImageInfo *)node->data,
4590 "respect-parenthesis")) != MagickFalse )
anthonyf42014d2012-03-25 09:53:06 +00004591 option="}"; /* fall-thru so as to pop image settings too */
anthony43f425d2012-02-26 12:58:58 +00004592 else
4593 return;
4594 }
4595 else
4596 return;
4597 }
anthonyce8dcb32012-03-21 13:20:31 +00004598 if (LocaleCompare("}",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004599 /* pop image_info settings from stack */
4600 Stack
4601 *node;
4602
4603 node = (void *)cli_wand->image_info_stack;
4604 if ( node == (Stack *)NULL)
anthony4d4f2c72012-03-22 03:22:03 +00004605 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
anthony43f425d2012-02-26 12:58:58 +00004606 cli_wand->image_info_stack = node->next;
4607
4608 (void) DestroyImageInfo(cli_wand->wand.image_info);
4609 cli_wand->wand.image_info = (ImageInfo *)node->data;
4610 node = (Stack *)RelinquishMagickMemory(node);
4611
4612 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4613 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4614 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4615
4616 return;
4617 }
anthonyce8dcb32012-03-21 13:20:31 +00004618 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004619 Image
4620 *new_images;
4621
4622 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004623 arg1="-1";
4624 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004625 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004626 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004627 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004628 new_images = (Image *)cli_wand->image_list_stack->data;
4629 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004630 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4631 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004632 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004633 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004634 AppendImageToList(&cli_wand->wand.images,new_images);
4635 return;
4636 }
anthony319dac62012-03-06 04:12:44 +00004637 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthonyce8dcb32012-03-21 13:20:31 +00004638 ( LocaleCompare("--",option) == 0 ) ) {
anthonyafa3dfc2012-03-03 11:31:30 +00004639#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004640 Image *
4641 new_images;
4642
anthony43f425d2012-02-26 12:58:58 +00004643 if (cli_wand->wand.image_info->ping != MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004644 new_images=PingImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004645 else
anthony92c93bd2012-03-19 14:02:47 +00004646 new_images=ReadImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004647 AppendImageToList(&cli_wand->wand.images, new_images);
4648#else
4649 /* read images using MagickWand method - no ping */
4650 /* This is not working! - it locks up in a CPU loop! */
4651 MagickSetLastIterator(&cli_wand->wand);
anthony24aa8822012-03-11 00:56:06 +00004652 MagickReadImage(&cli_wand->wand,arg1);
anthony43f425d2012-02-26 12:58:58 +00004653 MagickSetFirstIterator(&cli_wand->wand);
4654#endif
4655 return;
4656 }
anthonyafa3dfc2012-03-03 11:31:30 +00004657 /* No-op options */
4658 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004659 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004660 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004661 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004662 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004663 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004664 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004665 return;
anthonyce8dcb32012-03-21 13:20:31 +00004666 if (LocaleCompare("list",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004667 /* FUTURE: This should really be built into the MagickCore
4668 It does not actually require any wand or images at all!
4669 */
4670 ssize_t
4671 list;
4672
anthony24aa8822012-03-11 00:56:06 +00004673 list=ParseCommandOption(MagickListOptions,MagickFalse, arg1);
anthonyfe1aa782012-03-24 13:43:04 +00004674 if ( list < 0 ) {
4675 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4676 return;
4677 }
anthony43f425d2012-02-26 12:58:58 +00004678 switch (list)
4679 {
4680 case MagickCoderOptions:
4681 {
anthony92c93bd2012-03-19 14:02:47 +00004682 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004683 break;
4684 }
4685 case MagickColorOptions:
4686 {
anthony92c93bd2012-03-19 14:02:47 +00004687 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004688 break;
4689 }
4690 case MagickConfigureOptions:
4691 {
anthony92c93bd2012-03-19 14:02:47 +00004692 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004693 break;
4694 }
4695 case MagickDelegateOptions:
4696 {
anthony92c93bd2012-03-19 14:02:47 +00004697 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004698 break;
4699 }
4700 case MagickFontOptions:
4701 {
anthony92c93bd2012-03-19 14:02:47 +00004702 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004703 break;
4704 }
4705 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004706 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004707 break;
4708 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004709 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004710 break;
4711 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004712 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004713 break;
4714 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004715 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004716 break;
4717 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004718 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004719 break;
4720 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004721 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004722 break;
4723 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004724 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004725 break;
4726 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004727 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004728 break;
4729 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004730 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004731 break;
4732 default:
4733 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004734 _exception);
anthony43f425d2012-02-26 12:58:58 +00004735 break;
4736 }
4737 return;
4738 }
4739
4740#if 0
4741 // adjust stack handling
4742 // Other 'special' options this should handle
4743 // "region" "list" "version"
4744 // It does not do "exit" however as due to its side-effect requirements
4745#endif
4746#if 0
4747 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004748#endif
anthonyebb73a22012-03-22 14:25:52 +00004749 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004750
anthony92c93bd2012-03-19 14:02:47 +00004751#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004752}