blob: 1226b9991d2fa58f2d450581bf8148ea2a1b3912 [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)
cristy0d0de742012-03-25 19:32:48 +00003168 {
3169 if (IsGeometry(arg1) == MagickFalse)
3170 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3171 arg1);
3172 (void) ResetImagePage(_image,arg1);
3173 }
anthony31f1bf72012-01-30 12:37:22 +00003174 else
anthony92c93bd2012-03-19 14:02:47 +00003175 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003176 break;
3177 }
anthonyafa3dfc2012-03-03 11:31:30 +00003178 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003179 {
anthonyf42014d2012-03-25 09:53:06 +00003180 /* FUTURE: remove blur arguemnt - no longer used
3181 Roll into a resize special operation */
3182 if (IsGeometry(arg1) == MagickFalse)
3183 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003184 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003185 if ((flags & SigmaValue) == 0)
3186 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003187 new_image=ResampleImage(_image,geometry_info.rho,
3188 geometry_info.sigma,_image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003189 break;
3190 }
anthonyafa3dfc2012-03-03 11:31:30 +00003191 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003192 {
anthonyafbaed72011-10-26 12:05:04 +00003193 /* FUTURE: remove blur argument - no longer used */
anthonyf42014d2012-03-25 09:53:06 +00003194 if (IsGeometry(arg1) == MagickFalse)
3195 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003196 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3197 new_image=ResizeImage(_image,geometry.width,geometry.height,
3198 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003199 break;
3200 }
anthonyafa3dfc2012-03-03 11:31:30 +00003201 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003202 {
anthonyf42014d2012-03-25 09:53:06 +00003203 if (IsGeometry(arg1) == MagickFalse)
3204 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003205 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3206 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003207 break;
3208 }
anthonyafa3dfc2012-03-03 11:31:30 +00003209 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003210 {
anthonyf42014d2012-03-25 09:53:06 +00003211 if (IsGeometry(arg1) == MagickFalse)
3212 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
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 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003217 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003218 break;
anthonyfd706f92012-01-19 04:22:02 +00003219 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003220 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003221 break;
3222 }
anthonyebb73a22012-03-22 14:25:52 +00003223 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003224 }
3225 case 's':
3226 {
anthonyafa3dfc2012-03-03 11:31:30 +00003227 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003228 {
anthonyfe1aa782012-03-24 13:43:04 +00003229 /* FUTURE: Roll into a resize special operator */
anthonyf42014d2012-03-25 09:53:06 +00003230 if (IsGeometry(arg1) == MagickFalse)
3231 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003232 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3233 new_image=SampleImage(_image,geometry.width,geometry.height,
3234 _exception);
anthony805a2d42011-09-25 08:25:12 +00003235 break;
3236 }
anthonyafa3dfc2012-03-03 11:31:30 +00003237 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003238 {
anthonyfe1aa782012-03-24 13:43:04 +00003239 /* FUTURE: Roll into a resize special operator */
anthonyf42014d2012-03-25 09:53:06 +00003240 if (IsGeometry(arg1) == MagickFalse)
3241 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003242 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3243 new_image=ScaleImage(_image,geometry.width,geometry.height,
3244 _exception);
anthony805a2d42011-09-25 08:25:12 +00003245 break;
3246 }
anthonyf42014d2012-03-25 09:53:06 +00003247 if (LocaleCompare("segment",option+1) == 0)
3248 {
3249 if (IsGeometry(arg1) == MagickFalse)
3250 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3251 flags=ParseGeometry(arg1,&geometry_info);
3252 if ((flags & SigmaValue) == 0)
3253 geometry_info.sigma=1.0;
3254 (void) SegmentImage(_image,_image->colorspace,
3255 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3256 _exception);
3257 break;
3258 }
anthonyafa3dfc2012-03-03 11:31:30 +00003259 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003260 {
anthonyf42014d2012-03-25 09:53:06 +00003261 if (IsGeometry(arg1) == MagickFalse)
3262 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003263 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003264 if ((flags & PercentValue) != 0)
3265 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003266 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3267 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003268 break;
3269 }
anthonyafa3dfc2012-03-03 11:31:30 +00003270 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003271 {
anthony31f1bf72012-01-30 12:37:22 +00003272 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003273 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003274 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003275 break;
3276 }
anthonyafa3dfc2012-03-03 11:31:30 +00003277 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003278 {
anthonyf42014d2012-03-25 09:53:06 +00003279 if (IsGeometry(arg1) == MagickFalse)
3280 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3281 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3282 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003283 break;
3284 }
anthonyafa3dfc2012-03-03 11:31:30 +00003285 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003286 {
3287 char
3288 *value;
3289
anthonyf42014d2012-03-25 09:53:06 +00003290 if (IfPlusOp) {
anthonyfd706f92012-01-19 04:22:02 +00003291 if (LocaleNCompare(arg1,"registry:",9) == 0)
3292 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003293 else
anthony31f1bf72012-01-30 12:37:22 +00003294 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003295 {
anthony92c93bd2012-03-19 14:02:47 +00003296 (void) DeleteImageOption(_image_info,arg1+7);
3297 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003298 }
3299 else
anthony92c93bd2012-03-19 14:02:47 +00003300 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003301 break;
3302 }
anthonyf42014d2012-03-25 09:53:06 +00003303 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003304 if (value == (char *) NULL)
3305 break;
anthonyfd706f92012-01-19 04:22:02 +00003306 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003307 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003308 else
anthonyfd706f92012-01-19 04:22:02 +00003309 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003310 {
anthony92c93bd2012-03-19 14:02:47 +00003311 (void) SetImageOption(_image_info,arg1+7,value);
3312 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003313 }
3314 else
anthony92c93bd2012-03-19 14:02:47 +00003315 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003316 value=DestroyString(value);
3317 break;
3318 }
anthonyafa3dfc2012-03-03 11:31:30 +00003319 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003320 {
anthonyf42014d2012-03-25 09:53:06 +00003321 if (IsGeometry(arg1) == MagickFalse)
3322 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003323 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003324 if ((flags & SigmaValue) == 0)
3325 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003326 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3327 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003328 break;
3329 }
anthonyafa3dfc2012-03-03 11:31:30 +00003330 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003331 {
anthonyf42014d2012-03-25 09:53:06 +00003332 if (IsGeometry(arg1) == MagickFalse)
3333 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003334 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003335 if ((flags & SigmaValue) == 0)
3336 geometry_info.sigma=1.0;
3337 if ((flags & XiValue) == 0)
3338 geometry_info.xi=4.0;
3339 if ((flags & PsiValue) == 0)
3340 geometry_info.psi=4.0;
anthony92c93bd2012-03-19 14:02:47 +00003341 new_image=ShadowImage(_image,geometry_info.rho,
3342 geometry_info.sigma,_image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003343 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
anthony92c93bd2012-03-19 14:02:47 +00003344 _exception);
anthony805a2d42011-09-25 08:25:12 +00003345 break;
3346 }
anthonyafa3dfc2012-03-03 11:31:30 +00003347 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003348 {
anthonyf42014d2012-03-25 09:53:06 +00003349 if (IsGeometry(arg1) == MagickFalse)
3350 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003351 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003352 if ((flags & SigmaValue) == 0)
3353 geometry_info.sigma=1.0;
3354 if ((flags & XiValue) == 0)
3355 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00003356 new_image=SharpenImage(_image,geometry_info.rho,
3357 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003358 break;
3359 }
anthonyafa3dfc2012-03-03 11:31:30 +00003360 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003361 {
anthonyf42014d2012-03-25 09:53:06 +00003362 if (IsGeometry(arg1) == MagickFalse)
3363 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003364 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3365 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003366 break;
3367 }
anthonyafa3dfc2012-03-03 11:31:30 +00003368 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003369 {
anthonyf42014d2012-03-25 09:53:06 +00003370 if (IsGeometry(arg1) == MagickFalse)
3371 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003372 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003373 if ((flags & SigmaValue) == 0)
3374 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003375 new_image=ShearImage(_image,geometry_info.rho,
3376 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003377 break;
3378 }
anthonyafa3dfc2012-03-03 11:31:30 +00003379 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003380 {
anthonyf42014d2012-03-25 09:53:06 +00003381 if (IsGeometry(arg1) == MagickFalse)
3382 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003383 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003384 if ((flags & SigmaValue) == 0)
3385 geometry_info.sigma=(double) QuantumRange/2.0;
3386 if ((flags & PercentValue) != 0)
3387 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3388 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003389 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003390 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003391 _exception);
anthony805a2d42011-09-25 08:25:12 +00003392 break;
3393 }
anthonyafa3dfc2012-03-03 11:31:30 +00003394 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003395 {
anthonyf42014d2012-03-25 09:53:06 +00003396 if (IsGeometry(arg1) == MagickFalse)
3397 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003398 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003399 if ((flags & SigmaValue) == 0)
3400 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003401 new_image=SketchImage(_image,geometry_info.rho,
3402 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003403 break;
3404 }
anthonyafa3dfc2012-03-03 11:31:30 +00003405 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003406 {
anthonyf42014d2012-03-25 09:53:06 +00003407 if (IsGeometry(arg1) == MagickFalse)
3408 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003409 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3410 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003411 break;
3412 }
anthonyafa3dfc2012-03-03 11:31:30 +00003413 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003414 {
anthony805a2d42011-09-25 08:25:12 +00003415 char
3416 *arguments;
3417
anthonyf42014d2012-03-25 09:53:06 +00003418 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3419 if ( parse < 0 )
3420 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3421 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003422 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003423 if (arguments == (char *) NULL)
anthonyf42014d2012-03-25 09:53:06 +00003424 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3425 new_image=SparseColorOption(_image,(SparseColorMethod)parse,
3426 arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003427 arguments=DestroyString(arguments);
3428 break;
3429 }
anthonyafa3dfc2012-03-03 11:31:30 +00003430 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003431 {
anthonyf42014d2012-03-25 09:53:06 +00003432 if (IsGeometry(arg1) == MagickFalse)
3433 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003434 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3435 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003436 break;
3437 }
anthonyafa3dfc2012-03-03 11:31:30 +00003438 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003439 {
anthonyf42014d2012-03-25 09:53:06 +00003440 if (IsGeometry(arg1) == MagickFalse)
3441 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003442 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003443 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3444 _exception);
anthony805a2d42011-09-25 08:25:12 +00003445 break;
3446 }
anthonyafa3dfc2012-03-03 11:31:30 +00003447 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003448 {
anthony7bc87992012-03-25 02:32:51 +00003449 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3450 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003451 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003452 option,arg1);
3453 if (IsGeometry(arg2) == MagickFalse)
3454 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00003455 (void) ParseGeometry(arg2,&geometry_info);
anthony7bc87992012-03-25 02:32:51 +00003456 new_image=StatisticImage(_image,(StatisticType)parse,
3457 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3458 _exception);
anthony805a2d42011-09-25 08:25:12 +00003459 break;
3460 }
anthonyafa3dfc2012-03-03 11:31:30 +00003461 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003462 {
anthony92c93bd2012-03-19 14:02:47 +00003463 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003464 break;
3465 }
anthonyafa3dfc2012-03-03 11:31:30 +00003466 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003467 {
anthonyf42014d2012-03-25 09:53:06 +00003468 if (IsGeometry(arg1) == MagickFalse)
3469 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003470 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003471 new_image=SwirlImage(_image,geometry_info.rho,
3472 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003473 break;
3474 }
anthonyebb73a22012-03-22 14:25:52 +00003475 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003476 }
3477 case 't':
3478 {
anthonyafa3dfc2012-03-03 11:31:30 +00003479 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003480 {
3481 double
3482 threshold;
3483
anthonyafa3dfc2012-03-03 11:31:30 +00003484 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003485 threshold=(double) QuantumRange/2;
3486 else
anthonyfd706f92012-01-19 04:22:02 +00003487 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003488 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003489 break;
3490 }
anthonyafa3dfc2012-03-03 11:31:30 +00003491 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003492 {
anthony92c93bd2012-03-19 14:02:47 +00003493 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3494 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3495 _exception);
anthony805a2d42011-09-25 08:25:12 +00003496 break;
3497 }
anthonyafa3dfc2012-03-03 11:31:30 +00003498 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003499 {
anthony92c93bd2012-03-19 14:02:47 +00003500 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003501 break;
3502 }
anthonyafa3dfc2012-03-03 11:31:30 +00003503 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003504 {
anthonya3ef4ed2012-03-17 06:52:53 +00003505 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony92c93bd2012-03-19 14:02:47 +00003506 new_image=AffineTransformImage(_image,&_draw_info->affine,
3507 _exception);
anthony805a2d42011-09-25 08:25:12 +00003508 break;
3509 }
anthonyafa3dfc2012-03-03 11:31:30 +00003510 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003511 {
3512 PixelInfo
3513 target;
3514
anthony92c93bd2012-03-19 14:02:47 +00003515 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3516 (void) TransparentPaintImage(_image,&target,(Quantum)
3517 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003518 break;
3519 }
anthonyafa3dfc2012-03-03 11:31:30 +00003520 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003521 {
anthony92c93bd2012-03-19 14:02:47 +00003522 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003523 break;
3524 }
anthonyafa3dfc2012-03-03 11:31:30 +00003525 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003526 {
anthony92c93bd2012-03-19 14:02:47 +00003527 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003528 break;
3529 }
anthonyafa3dfc2012-03-03 11:31:30 +00003530 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003531 {
anthony92c93bd2012-03-19 14:02:47 +00003532 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003533 break;
3534 }
anthonyafa3dfc2012-03-03 11:31:30 +00003535 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003536 {
anthonyab3a50c2011-10-27 11:48:57 +00003537 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003538 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003539 break;
3540 }
anthonyebb73a22012-03-22 14:25:52 +00003541 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003542 }
3543 case 'u':
3544 {
anthonyafa3dfc2012-03-03 11:31:30 +00003545 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003546 {
anthony31f1bf72012-01-30 12:37:22 +00003547 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthony24aa8822012-03-11 00:56:06 +00003548 /* FUTURE: This option is not documented!!!!! */
anthonyafa3dfc2012-03-03 11:31:30 +00003549 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003550 {
anthony92c93bd2012-03-19 14:02:47 +00003551 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003552 break;
3553 }
anthony92c93bd2012-03-19 14:02:47 +00003554 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3555 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003556 break;
3557 }
anthonyafa3dfc2012-03-03 11:31:30 +00003558 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003559 {
anthony92c93bd2012-03-19 14:02:47 +00003560 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003561 break;
3562 }
anthonyafa3dfc2012-03-03 11:31:30 +00003563 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003564 {
anthonyfd706f92012-01-19 04:22:02 +00003565 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003566 if ((flags & SigmaValue) == 0)
3567 geometry_info.sigma=1.0;
3568 if ((flags & XiValue) == 0)
3569 geometry_info.xi=1.0;
3570 if ((flags & PsiValue) == 0)
3571 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003572 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3573 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003574 break;
3575 }
anthonyebb73a22012-03-22 14:25:52 +00003576 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003577 }
3578 case 'v':
3579 {
anthonyafa3dfc2012-03-03 11:31:30 +00003580 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003581 {
anthonyafa3dfc2012-03-03 11:31:30 +00003582 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003583 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003584 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003585 */
anthony92c93bd2012-03-19 14:02:47 +00003586 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003587 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003588 break;
3589 }
anthonyafa3dfc2012-03-03 11:31:30 +00003590 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003591 {
anthonyfd706f92012-01-19 04:22:02 +00003592 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003593 if ((flags & SigmaValue) == 0)
3594 geometry_info.sigma=1.0;
3595 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003596 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003597 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003598 geometry_info.psi=0.1*_image->rows;
3599 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3600 _image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3601 (ssize_t) ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003602 break;
3603 }
anthonyebb73a22012-03-22 14:25:52 +00003604 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003605 }
3606 case 'w':
3607 {
anthonyafa3dfc2012-03-03 11:31:30 +00003608 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003609 {
anthonyfd706f92012-01-19 04:22:02 +00003610 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003611 if ((flags & SigmaValue) == 0)
3612 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003613 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3614 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003615 break;
3616 }
anthonyafa3dfc2012-03-03 11:31:30 +00003617 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003618 {
anthony92c93bd2012-03-19 14:02:47 +00003619 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003620 break;
3621 }
anthonyebb73a22012-03-22 14:25:52 +00003622 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003623 }
3624 default:
anthonyebb73a22012-03-22 14:25:52 +00003625 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003626 }
3627 /*
3628 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003629 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003630 */
3631 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003632 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003633
anthony31f1bf72012-01-30 12:37:22 +00003634 return;
anthony92c93bd2012-03-19 14:02:47 +00003635#undef _image_info
3636#undef _draw_info
3637#undef _quantize_info
3638#undef _image
3639#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003640#undef IfNormalOp
3641#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003642#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003643#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003644}
anthonyfd706f92012-01-19 04:22:02 +00003645
anthony43f425d2012-02-26 12:58:58 +00003646WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003647 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003648{
3649 size_t
anthony43f425d2012-02-26 12:58:58 +00003650 n,
anthony31f1bf72012-01-30 12:37:22 +00003651 i;
3652
anthony43f425d2012-02-26 12:58:58 +00003653 assert(cli_wand != (MagickCLI *) NULL);
3654 assert(cli_wand->signature == WandSignature);
3655 assert(cli_wand->wand.signature == WandSignature);
3656 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3657 if (cli_wand->wand.debug != MagickFalse)
3658 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003659
anthonyafa3dfc2012-03-03 11:31:30 +00003660#if !USE_WAND_METHODS
3661 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003662 i=0;
anthony43f425d2012-02-26 12:58:58 +00003663 n=GetImageListLength(cli_wand->wand.images);
3664 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003665 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003666 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003667 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003668 if ( cli_wand->wand.images->next == (Image *) NULL )
3669 break;
3670 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003671 }
anthony43f425d2012-02-26 12:58:58 +00003672 assert( i == n );
3673 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003674#else
3675 MagickResetIterator(&cli_wand->wand);
3676 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3677 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3678 MagickResetIterator(&cli_wand->wand);
3679#endif
anthony31f1bf72012-01-30 12:37:22 +00003680 return;
anthony805a2d42011-09-25 08:25:12 +00003681}
3682
3683/*
3684%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3685% %
3686% %
3687% %
anthony43f425d2012-02-26 12:58:58 +00003688+ 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 +00003689% %
3690% %
3691% %
3692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3693%
anthony43f425d2012-02-26 12:58:58 +00003694% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003695% entire image list as a whole. The result is often a complete replacment
3696% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003697%
3698% The format of the MogrifyImage method is:
3699%
anthony43f425d2012-02-26 12:58:58 +00003700% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003701% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003702%
3703% A description of each parameter follows:
3704%
anthony43f425d2012-02-26 12:58:58 +00003705% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003706%
anthony36a8c2c2012-02-10 00:08:44 +00003707% o option: The option string for the operation
3708%
anthony31f1bf72012-01-30 12:37:22 +00003709% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003710%
anthonyfe1aa782012-03-24 13:43:04 +00003711% NOTE: only "limit" uses two arguments.
anthony8b10b462012-02-08 12:32:44 +00003712%
3713% Example usage...
3714%
anthonyafa3dfc2012-03-03 11:31:30 +00003715% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3716% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003717%
anthony24aa8822012-03-11 00:56:06 +00003718% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003719%
anthony43f425d2012-02-26 12:58:58 +00003720% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003721% argc,argv
3722% i=index in argv
3723%
anthony2052d272012-02-28 12:48:29 +00003724% option_info = GetCommandOptionInfo(argv[i]);
3725% count=option_info->type;
3726% option_type=option_info->flags;
3727%
3728% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003729% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003730% count>=1 ? argv[i+1] : (char *)NULL,
3731% count>=2 ? argv[i+2] : (char *)NULL );
3732% i += count+1;
3733%
anthony805a2d42011-09-25 08:25:12 +00003734*/
anthony43f425d2012-02-26 12:58:58 +00003735WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003736 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003737{
anthony2a0ec8c2012-03-24 04:35:56 +00003738 ssize_t
3739 parse;
3740
anthony31f1bf72012-01-30 12:37:22 +00003741 Image
3742 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003743
anthony92c93bd2012-03-19 14:02:47 +00003744#define _image_info (cli_wand->wand.image_info)
3745#define _images (cli_wand->wand.images)
3746#define _exception (cli_wand->wand.exception)
3747#define _draw_info (cli_wand->draw_info)
3748#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003749#define IfNormalOp (*option=='-')
3750#define IfPlusOp (*option!='-')
3751#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003752
anthony43f425d2012-02-26 12:58:58 +00003753 assert(cli_wand != (MagickCLI *) NULL);
3754 assert(cli_wand->signature == WandSignature);
3755 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003756 assert(_images != (Image *) NULL); /* _images must be present */
anthony43f425d2012-02-26 12:58:58 +00003757 if (cli_wand->wand.debug != MagickFalse)
3758 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003759
anthony92c93bd2012-03-19 14:02:47 +00003760 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003761
3762 new_images=NewImageList();
3763
anthonyafa3dfc2012-03-03 11:31:30 +00003764 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003765 {
3766 case 'a':
3767 {
anthonyafa3dfc2012-03-03 11:31:30 +00003768 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003769 {
anthony92c93bd2012-03-19 14:02:47 +00003770 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003771 break;
3772 }
anthonyafa3dfc2012-03-03 11:31:30 +00003773 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003774 {
anthony31f1bf72012-01-30 12:37:22 +00003775 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003776 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003777 break;
3778 }
anthonyebb73a22012-03-22 14:25:52 +00003779 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003780 }
3781 case 'c':
3782 {
cristy5f257b22012-03-07 00:27:29 +00003783 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003784 {
anthony92c93bd2012-03-19 14:02:47 +00003785 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003786 break;
3787 }
anthonyafa3dfc2012-03-03 11:31:30 +00003788 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003789 {
anthony805a2d42011-09-25 08:25:12 +00003790 Image
anthony31f1bf72012-01-30 12:37:22 +00003791 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003792
anthonyafa3dfc2012-03-03 11:31:30 +00003793 /* FUTURE - make this a compose option, and thus can be used
3794 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003795 _images.
cristy87c02f42012-02-24 00:19:10 +00003796 */
anthony92c93bd2012-03-19 14:02:47 +00003797 new_images=RemoveFirstImageFromList(&_images);
3798 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003799 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003800 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003801 break;
anthony92c93bd2012-03-19 14:02:47 +00003802 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003803 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003804 break;
3805 }
anthonyafa3dfc2012-03-03 11:31:30 +00003806 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003807 {
anthony92c93bd2012-03-19 14:02:47 +00003808 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003809 break;
3810 }
anthonyafa3dfc2012-03-03 11:31:30 +00003811 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003812 {
anthony43f425d2012-02-26 12:58:58 +00003813 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003814 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003815 break;
3816 }
anthonyafa3dfc2012-03-03 11:31:30 +00003817 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003818 {
3819 Image
3820 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003821 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003822
3823 RectangleInfo
3824 geometry;
3825
anthony31f1bf72012-01-30 12:37:22 +00003826 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003827 compose;
3828
3829 const char*
3830 value;
3831
anthony92c93bd2012-03-19 14:02:47 +00003832 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003833 if (value != (const char *) NULL)
3834 compose=(CompositeOperator) ParseCommandOption(
3835 MagickComposeOptions,MagickFalse,value);
3836 else
anthony31f1bf72012-01-30 12:37:22 +00003837 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003838
anthony92c93bd2012-03-19 14:02:47 +00003839 new_images=RemoveFirstImageFromList(&_images);
3840 source_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003841 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003842 if (source_image == (Image *) NULL)
3843 break;
anthonye8f56492012-02-12 12:39:02 +00003844
anthony31f1bf72012-01-30 12:37:22 +00003845 /* FUTURE - this should not be here! - should be part of -geometry */
3846 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003847 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003848
anthony31f1bf72012-01-30 12:37:22 +00003849 SetGeometry(source_image,&geometry);
3850 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3851 GravityAdjustGeometry(new_images->columns,new_images->rows,
3852 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003853
anthony92c93bd2012-03-19 14:02:47 +00003854 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003855 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003856 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003857 if ((compose == DisplaceCompositeOp) ||
3858 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003859 { /* Merge Y displacement into X displace/distort map. */
3860 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony92c93bd2012-03-19 14:02:47 +00003861 mask_image,0,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003862 mask_image=DestroyImage(mask_image);
3863 }
3864 else
3865 {
3866 /*
3867 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003868 */
anthony92c93bd2012-03-19 14:02:47 +00003869 (void) NegateImage(mask_image,MagickFalse,_exception);
3870 (void) SetImageMask(new_images,mask_image,_exception);
cristy1539afd2012-01-30 01:32:59 +00003871 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003872 }
3873 }
anthony31f1bf72012-01-30 12:37:22 +00003874 (void) CompositeImage(new_images,compose,source_image,geometry.x,
anthony92c93bd2012-03-19 14:02:47 +00003875 geometry.y,_exception);
3876 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003877 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003878 break;
3879 }
anthonyebb73a22012-03-22 14:25:52 +00003880 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003881 }
3882 case 'd':
3883 {
anthonyafa3dfc2012-03-03 11:31:30 +00003884 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003885 {
anthony31f1bf72012-01-30 12:37:22 +00003886 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003887 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003888 break;
3889 }
anthonyafa3dfc2012-03-03 11:31:30 +00003890 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003891 {
anthonyafa3dfc2012-03-03 11:31:30 +00003892 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003893 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003894 else
anthony92c93bd2012-03-19 14:02:47 +00003895 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003896 break;
3897 }
anthonyafa3dfc2012-03-03 11:31:30 +00003898 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003899 {
anthonyafa3dfc2012-03-03 11:31:30 +00003900 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003901 {
3902 const char
3903 *p;
3904
3905 size_t
3906 number_duplicates;
3907
anthonyebb73a22012-03-22 14:25:52 +00003908 if (IsGeometry(arg1) == MagickFalse)
3909 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3910 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003911 number_duplicates=(size_t) StringToLong(arg1);
3912 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003913 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003914 new_images=DuplicateImages(_images,number_duplicates,"-1",
3915 _exception);
anthony805a2d42011-09-25 08:25:12 +00003916 else
anthony92c93bd2012-03-19 14:02:47 +00003917 new_images=DuplicateImages(_images,number_duplicates,p,
3918 _exception);
anthony805a2d42011-09-25 08:25:12 +00003919 }
anthonyafa3dfc2012-03-03 11:31:30 +00003920 else
anthony92c93bd2012-03-19 14:02:47 +00003921 new_images=DuplicateImages(_images,1,"-1",_exception);
3922 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003923 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003924 break;
3925 }
anthonyebb73a22012-03-22 14:25:52 +00003926 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003927 }
3928 case 'e':
3929 {
anthonyafa3dfc2012-03-03 11:31:30 +00003930 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003931 {
anthony2a0ec8c2012-03-24 04:35:56 +00003932 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3933 if ( parse < 0 )
3934 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3935 option,arg1);
3936 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3937 _exception);
anthony805a2d42011-09-25 08:25:12 +00003938 break;
3939 }
anthonyebb73a22012-03-22 14:25:52 +00003940 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003941 }
3942 case 'f':
3943 {
anthonyafa3dfc2012-03-03 11:31:30 +00003944 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003945 {
anthony92c93bd2012-03-19 14:02:47 +00003946 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003947 break;
3948 }
anthonyafa3dfc2012-03-03 11:31:30 +00003949 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003950 {
anthony319dac62012-03-06 04:12:44 +00003951 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003952 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003953 break;
3954 }
anthonyafa3dfc2012-03-03 11:31:30 +00003955 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003956 {
anthony92c93bd2012-03-19 14:02:47 +00003957 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003958 break;
3959 }
anthonyebb73a22012-03-22 14:25:52 +00003960 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003961 }
3962 case 'h':
3963 {
anthonyafa3dfc2012-03-03 11:31:30 +00003964 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003965 {
anthony31f1bf72012-01-30 12:37:22 +00003966 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003967 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003968 */
anthony805a2d42011-09-25 08:25:12 +00003969 Image
anthony31f1bf72012-01-30 12:37:22 +00003970 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003971
anthony92c93bd2012-03-19 14:02:47 +00003972 new_images=RemoveFirstImageFromList(&_images);
3973 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003974 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003975 break;
anthony92c93bd2012-03-19 14:02:47 +00003976 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003977 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003978 break;
3979 }
anthonyebb73a22012-03-22 14:25:52 +00003980 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003981 }
3982 case 'i':
3983 {
anthonyafa3dfc2012-03-03 11:31:30 +00003984 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003985 {
3986 Image
anthony805a2d42011-09-25 08:25:12 +00003987 *magnitude_image,
3988 *phase_image;
3989
anthony92c93bd2012-03-19 14:02:47 +00003990 magnitude_image=RemoveFirstImageFromList(&_images);
3991 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003992 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003993 if (phase_image == (Image *) NULL)
3994 break;
3995 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003996 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003997 magnitude_image=DestroyImage(magnitude_image);
3998 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003999 break;
4000 }
anthonyafa3dfc2012-03-03 11:31:30 +00004001 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004002 {
4003 Image
anthony31f1bf72012-01-30 12:37:22 +00004004 *insert_image,
4005 *index_image;
4006
4007 ssize_t
4008 index;
anthony805a2d42011-09-25 08:25:12 +00004009
anthonyfe1aa782012-03-24 13:43:04 +00004010 if (IfNormalOp && IsGeometry(arg1) == MagickFalse)
4011 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004012 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004013 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004014 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004015 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004016 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004017 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004018 PrependImageToList(&_images,insert_image);
4019 else if (index == (ssize_t) GetImageListLength(_images))
4020 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004021 else
anthony43f425d2012-02-26 12:58:58 +00004022 {
anthony92c93bd2012-03-19 14:02:47 +00004023 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004024 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004025 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004026 InsertImageInList(&index_image,insert_image);
4027 }
anthony92c93bd2012-03-19 14:02:47 +00004028 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004029 break;
4030 }
anthonyebb73a22012-03-22 14:25:52 +00004031 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004032 }
4033 case 'l':
4034 {
anthonyafa3dfc2012-03-03 11:31:30 +00004035 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004036 {
anthonyfe1aa782012-03-24 13:43:04 +00004037 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4038 if ( parse < 0 )
4039 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4040 option,arg1);
4041 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004042 {
4043 case CoalesceLayer:
4044 {
anthony92c93bd2012-03-19 14:02:47 +00004045 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004046 break;
4047 }
4048 case CompareAnyLayer:
4049 case CompareClearLayer:
4050 case CompareOverlayLayer:
4051 default:
4052 {
anthonyfe1aa782012-03-24 13:43:04 +00004053 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
4054 _exception);
anthony805a2d42011-09-25 08:25:12 +00004055 break;
4056 }
4057 case MergeLayer:
4058 case FlattenLayer:
4059 case MosaicLayer:
4060 case TrimBoundsLayer:
4061 {
anthonyfe1aa782012-03-24 13:43:04 +00004062 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
4063 _exception);
anthony805a2d42011-09-25 08:25:12 +00004064 break;
4065 }
4066 case DisposeLayer:
4067 {
anthony92c93bd2012-03-19 14:02:47 +00004068 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004069 break;
4070 }
4071 case OptimizeImageLayer:
4072 {
anthony92c93bd2012-03-19 14:02:47 +00004073 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004074 break;
4075 }
4076 case OptimizePlusLayer:
4077 {
anthony92c93bd2012-03-19 14:02:47 +00004078 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004079 break;
4080 }
4081 case OptimizeTransLayer:
4082 {
anthony92c93bd2012-03-19 14:02:47 +00004083 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004084 break;
4085 }
4086 case RemoveDupsLayer:
4087 {
anthony92c93bd2012-03-19 14:02:47 +00004088 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004089 break;
4090 }
4091 case RemoveZeroLayer:
4092 {
anthony92c93bd2012-03-19 14:02:47 +00004093 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004094 break;
4095 }
4096 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004097 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004098 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004099 if (new_images == (Image *) NULL)
4100 break;
anthony92c93bd2012-03-19 14:02:47 +00004101 _images=DestroyImageList(_images);
4102 _images=OptimizeImageLayers(new_images,_exception);
4103 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004104 break;
4105 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004106 OptimizeImageTransparency(_images,_exception);
4107 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4108 _exception);
anthony805a2d42011-09-25 08:25:12 +00004109 break;
4110 }
4111 case CompositeLayer:
4112 {
anthony805a2d42011-09-25 08:25:12 +00004113 Image
4114 *source;
4115
4116 RectangleInfo
4117 geometry;
4118
anthony31f1bf72012-01-30 12:37:22 +00004119 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004120 compose;
4121
4122 const char*
4123 value;
4124
anthony92c93bd2012-03-19 14:02:47 +00004125 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004126 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004127 if (value != (const char *) NULL)
4128 compose=(CompositeOperator) ParseCommandOption(
4129 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004130
anthony31f1bf72012-01-30 12:37:22 +00004131 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004132 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004133 while (source != (Image *) NULL)
4134 {
4135 source=GetNextImageInList(source);
4136 if ((source != (Image *) NULL) &&
4137 (LocaleCompare(source->magick,"NULL") == 0))
4138 break;
4139 }
4140 if (source != (Image *) NULL)
4141 {
4142 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4143 (GetNextImageInList(source) == (Image *) NULL))
4144 source=(Image *) NULL;
4145 else
anthony31f1bf72012-01-30 12:37:22 +00004146 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004147 source=SplitImageList(source->previous);
4148 DeleteImageFromList(&source);
4149 }
4150 }
4151 if (source == (Image *) NULL)
4152 {
anthony92c93bd2012-03-19 14:02:47 +00004153 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004154 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004155 break;
4156 }
anthony31f1bf72012-01-30 12:37:22 +00004157 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004158 SetGeometry(_images,&geometry);
4159 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004160 geometry.width=source->page.width != 0 ?
4161 source->page.width : source->columns;
4162 geometry.height=source->page.height != 0 ?
4163 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004164 GravityAdjustGeometry(_images->page.width != 0 ?
4165 _images->page.width : _images->columns,
4166 _images->page.height != 0 ? _images->page.height :
4167 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004168
anthony31f1bf72012-01-30 12:37:22 +00004169 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004170 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4171 _exception);
anthony805a2d42011-09-25 08:25:12 +00004172 source=DestroyImageList(source);
4173 break;
4174 }
4175 }
anthony805a2d42011-09-25 08:25:12 +00004176 break;
4177 }
anthonyafa3dfc2012-03-03 11:31:30 +00004178 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00004179 {
4180 MagickSizeType
4181 limit;
4182
anthony72feaa62012-01-17 06:46:23 +00004183 limit=MagickResourceInfinity;
anthonyfe1aa782012-03-24 13:43:04 +00004184 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4185 if ( parse < 0 )
4186 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4187 option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004188 if (LocaleCompare("unlimited",arg2) != 0)
4189 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthonyfe1aa782012-03-24 13:43:04 +00004190 (void) SetMagickResourceLimit((ResourceType)parse,limit);
anthony72feaa62012-01-17 06:46:23 +00004191 break;
4192 }
anthonyebb73a22012-03-22 14:25:52 +00004193 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004194 }
4195 case 'm':
4196 {
anthonyafa3dfc2012-03-03 11:31:30 +00004197 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004198 {
anthony31f1bf72012-01-30 12:37:22 +00004199 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004200 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004201 break;
4202 }
anthonyafa3dfc2012-03-03 11:31:30 +00004203 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004204 {
4205 Image
4206 *morph_image;
4207
anthony7bc87992012-03-25 02:32:51 +00004208 if (IsGeometry(arg1) == MagickFalse)
4209 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004210 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4211 _exception);
anthony805a2d42011-09-25 08:25:12 +00004212 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004213 break;
anthony92c93bd2012-03-19 14:02:47 +00004214 _images=DestroyImageList(_images);
4215 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004216 break;
4217 }
anthonyafa3dfc2012-03-03 11:31:30 +00004218 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004219 {
anthony319dac62012-03-06 04:12:44 +00004220 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00004221 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004222 break;
4223 }
anthonyebb73a22012-03-22 14:25:52 +00004224 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004225 }
4226 case 'p':
4227 {
anthonyafa3dfc2012-03-03 11:31:30 +00004228 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004229 {
4230 char
4231 *string;
4232
anthony92c93bd2012-03-19 14:02:47 +00004233 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004234 if (string == (char *) NULL)
4235 break;
4236 (void) FormatLocaleFile(stdout,"%s",string);
4237 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004238 break;
anthony805a2d42011-09-25 08:25:12 +00004239 }
anthonyafa3dfc2012-03-03 11:31:30 +00004240 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004241 {
4242 char
4243 **arguments;
4244
4245 int
4246 j,
4247 number_arguments;
4248
anthony31f1bf72012-01-30 12:37:22 +00004249 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004250 if (arguments == (char **) NULL)
4251 break;
anthony31f1bf72012-01-30 12:37:22 +00004252 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004253 {
4254 char
4255 breaker,
4256 quote,
4257 *token;
4258
4259 const char
4260 *arguments;
4261
4262 int
4263 next,
4264 status;
4265
4266 size_t
4267 length;
4268
4269 TokenInfo
4270 *token_info;
4271
4272 /*
anthony24aa8822012-03-11 00:56:06 +00004273 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004274 */
anthony31f1bf72012-01-30 12:37:22 +00004275 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004276 token=(char *) NULL;
4277 if (~length >= (MaxTextExtent-1))
4278 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4279 sizeof(*token));
4280 if (token == (char *) NULL)
4281 break;
4282 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004283 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004284 token_info=AcquireTokenInfo();
4285 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4286 "\"",'\0',&breaker,&next,&quote);
4287 token_info=DestroyTokenInfo(token_info);
4288 if (status == 0)
4289 {
4290 const char
4291 *argv;
4292
4293 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004294 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4295 _exception);
anthony805a2d42011-09-25 08:25:12 +00004296 }
4297 token=DestroyString(token);
4298 break;
4299 }
4300 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004301 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4302 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004303 for (j=0; j < number_arguments; j++)
4304 arguments[j]=DestroyString(arguments[j]);
4305 arguments=(char **) RelinquishMagickMemory(arguments);
4306 break;
4307 }
anthonyebb73a22012-03-22 14:25:52 +00004308 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004309 }
4310 case 'r':
4311 {
anthonyafa3dfc2012-03-03 11:31:30 +00004312 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004313 {
anthony92c93bd2012-03-19 14:02:47 +00004314 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004315 break;
4316 }
anthonyafa3dfc2012-03-03 11:31:30 +00004317 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004318 {
anthony92c93bd2012-03-19 14:02:47 +00004319 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004320 break;
4321 }
anthonyebb73a22012-03-22 14:25:52 +00004322 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004323 }
4324 case 's':
4325 {
anthonyafa3dfc2012-03-03 11:31:30 +00004326 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004327 {
4328 Image
4329 *smush_image;
4330
4331 ssize_t
4332 offset;
4333
anthonyf42014d2012-03-25 09:53:06 +00004334 if (IsGeometry(arg1) == MagickFalse)
4335 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004336 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004337 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004338 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004339 break;
anthony92c93bd2012-03-19 14:02:47 +00004340 _images=DestroyImageList(_images);
4341 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004342 break;
4343 }
anthonyafa3dfc2012-03-03 11:31:30 +00004344 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004345 {
4346 Image
4347 *p,
4348 *q,
4349 *swap;
4350
4351 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004352 index,
anthony805a2d42011-09-25 08:25:12 +00004353 swap_index;
4354
anthonyf42014d2012-03-25 09:53:06 +00004355 if (IsGeometry(arg1) == MagickFalse)
4356 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004357 index=-1;
4358 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004359 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004360 {
4361 GeometryInfo
4362 geometry_info;
4363
4364 MagickStatusType
4365 flags;
4366
4367 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004368 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004369 index=(ssize_t) geometry_info.rho;
4370 if ((flags & SigmaValue) != 0)
4371 swap_index=(ssize_t) geometry_info.sigma;
4372 }
anthony92c93bd2012-03-19 14:02:47 +00004373 p=GetImageFromList(_images,index);
4374 q=GetImageFromList(_images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004375 if ((p == (Image *) NULL) || (q == (Image *) NULL))
anthonyf42014d2012-03-25 09:53:06 +00004376 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004377 if (p == q)
anthonyf42014d2012-03-25 09:53:06 +00004378 break; /* same image - no-op - not an error */
anthony92c93bd2012-03-19 14:02:47 +00004379 swap=CloneImage(p,0,0,MagickTrue,_exception);
4380 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
anthony805a2d42011-09-25 08:25:12 +00004381 ReplaceImageInList(&q,swap);
anthony92c93bd2012-03-19 14:02:47 +00004382 _images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004383 break;
4384 }
anthonyebb73a22012-03-22 14:25:52 +00004385 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004386 }
4387 case 'w':
4388 {
anthonyafa3dfc2012-03-03 11:31:30 +00004389 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004390 {
4391 char
4392 key[MaxTextExtent];
4393
4394 Image
4395 *write_images;
4396
4397 ImageInfo
4398 *write_info;
4399
anthony31f1bf72012-01-30 12:37:22 +00004400 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004401 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004402 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004403 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004404 write_images=CloneImageList(_images,_exception);
4405 write_info=CloneImageInfo(_image_info);
4406 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004407 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004408 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004409 write_images=DestroyImageList(write_images);
4410 break;
4411 }
anthonyebb73a22012-03-22 14:25:52 +00004412 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004413 }
4414 default:
anthonyebb73a22012-03-22 14:25:52 +00004415 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004416 }
anthony31f1bf72012-01-30 12:37:22 +00004417 if (new_images == (Image *) NULL)
4418 return;
anthony805a2d42011-09-25 08:25:12 +00004419
anthony92c93bd2012-03-19 14:02:47 +00004420 if (_images != (Image *) NULL)
4421 _images=DestroyImageList(_images);
4422 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004423 return;
4424
anthony92c93bd2012-03-19 14:02:47 +00004425#undef _image_info
4426#undef _images
4427#undef _exception
4428#undef _draw_info
4429#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004430#undef IfNormalOp
4431#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004432#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004433}
anthony43f425d2012-02-26 12:58:58 +00004434
4435/*
4436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4437% %
4438% %
4439% %
4440+ C L I S p e c i a l O p e r a t i o n s %
4441% %
4442% %
4443% %
4444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4445%
4446% CLISpecialOption() Applies operations that may involve empty image lists
4447% and or stacks of image lists or image_info settings.
4448%
anthonyafa3dfc2012-03-03 11:31:30 +00004449% The classic operators of this type is -read, and image stack operators,
4450% which can be applied to empty image lists.
4451%
4452% Note: unlike other Operators, these may involve other special 'option'
4453% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004454%
4455% The format of the CLISpecialOption method is:
4456%
4457% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004458% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004459%
4460% A description of each parameter follows:
4461%
4462% o cli_wand: the main CLI Wand to use.
4463%
4464% o option: The special option (with any switch char) to process
4465%
anthony24aa8822012-03-11 00:56:06 +00004466% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004467%
anthony2052d272012-02-28 12:48:29 +00004468% Example Usage...
4469%
anthonyce8dcb32012-03-21 13:20:31 +00004470% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004471%
anthony24aa8822012-03-11 00:56:06 +00004472% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004473%
4474% cli_wand
4475% argc,argv
4476% i=index in argv
4477%
4478% option_info = GetCommandOptionInfo(argv[i]);
4479% count=option_info->type;
4480% option_type=option_info->flags;
4481%
4482% if ( (option_type & SpecialOptionFlag) != 0 )
4483% CLISpecialOperator(cli_wand,argv[i],
4484% count>=1 ? argv[i+1] : (char *)NULL);
4485% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004486%
4487*/
4488
anthony43f425d2012-02-26 12:58:58 +00004489WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004490 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004491{
anthony92c93bd2012-03-19 14:02:47 +00004492#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004493
4494 assert(cli_wand != (MagickCLI *) NULL);
4495 assert(cli_wand->signature == WandSignature);
4496 assert(cli_wand->wand.signature == WandSignature);
4497 if (cli_wand->wand.debug != MagickFalse)
4498 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4499
anthony24aa8822012-03-11 00:56:06 +00004500 if(cli_wand->wand.images != (Image *)NULL)
4501 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004502 _exception);
anthony24aa8822012-03-11 00:56:06 +00004503
anthonyce8dcb32012-03-21 13:20:31 +00004504 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
anthonyf42014d2012-03-25 09:53:06 +00004505 /* link image and setting stacks - option is itself saved on stack! */
anthonyce8dcb32012-03-21 13:20:31 +00004506 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4507 *option == '-' ? "true" : (char *) NULL);
4508 return;
4509 }
4510 if (LocaleCompare("(",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004511 /* stack 'push' images */
4512 Stack
4513 *node;
4514
4515 size_t
4516 size;
4517
anthony43f425d2012-02-26 12:58:58 +00004518 size=0;
4519 node=cli_wand->image_list_stack;
4520 for ( ; node != (Stack *)NULL; node=node->next)
4521 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004522 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004523 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004524 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4525 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004526 CLIWandExceptionReturn(ResourceLimitFatalError,
4527 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004528 node->data = (void *)cli_wand->wand.images;
4529 cli_wand->wand.images = NewImageList();
4530 node->next = cli_wand->image_list_stack;
4531 cli_wand->image_list_stack = node;
4532
4533 /* handle respect-parenthesis */
anthonyf42014d2012-03-25 09:53:06 +00004534 if (IsMagickTrue(GetImageOption(cli_wand->wand.image_info,
anthonyce8dcb32012-03-21 13:20:31 +00004535 "respect-parenthesis")) != MagickFalse )
anthonyf42014d2012-03-25 09:53:06 +00004536 option="{"; /* fall-thru so as to push image settings too */
anthony43f425d2012-02-26 12:58:58 +00004537 else
4538 return;
4539 }
anthonyce8dcb32012-03-21 13:20:31 +00004540 if (LocaleCompare("{",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004541 /* stack 'push' of image_info settings */
4542 Stack
4543 *node;
4544
4545 size_t
4546 size;
4547
4548 size=0;
4549 node=cli_wand->image_info_stack;
4550 for ( ; node != (Stack *)NULL; node=node->next)
4551 size++;
anthony92c93bd2012-03-19 14:02:47 +00004552 if ( size >= MAX_STACK_DEPTH )
anthony4d4f2c72012-03-22 03:22:03 +00004553 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004554 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004555 if (node == (Stack *) NULL)
4556 CLIWandExceptionReturn(ResourceLimitFatalError,
4557 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004558
4559 node->data = (void *)cli_wand->wand.image_info;
4560 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004561 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
anthony92c93bd2012-03-19 14:02:47 +00004562 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4563 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004564 cli_wand->wand.image_info = (ImageInfo *)node->data;
4565 node = (Stack *)RelinquishMagickMemory(node);
4566 return;
4567 }
anthony43f425d2012-02-26 12:58:58 +00004568
4569 node->next = cli_wand->image_info_stack;
4570 cli_wand->image_info_stack = node;
4571
4572 return;
4573 }
anthonyce8dcb32012-03-21 13:20:31 +00004574 if (LocaleCompare(")",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004575 /* pop images from stack */
4576 Stack
4577 *node;
4578
anthony43f425d2012-02-26 12:58:58 +00004579 node = (void *)cli_wand->image_list_stack;
4580 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004581 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004582 cli_wand->image_list_stack = node->next;
4583
4584 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4585 cli_wand->wand.images= (Image *)node->data;
4586 node = (Stack *)RelinquishMagickMemory(node);
4587
anthony4d4f2c72012-03-22 03:22:03 +00004588 /* handle respect-parenthesis - of the previous 'pushed' settings */
anthony43f425d2012-02-26 12:58:58 +00004589 node = cli_wand->image_info_stack;
4590 if ( node != (Stack *)NULL)
4591 {
anthonyce8dcb32012-03-21 13:20:31 +00004592 if (IsMagickTrue(GetImageOption((ImageInfo *)node->data,
4593 "respect-parenthesis")) != MagickFalse )
anthonyf42014d2012-03-25 09:53:06 +00004594 option="}"; /* fall-thru so as to pop image settings too */
anthony43f425d2012-02-26 12:58:58 +00004595 else
4596 return;
4597 }
4598 else
4599 return;
4600 }
anthonyce8dcb32012-03-21 13:20:31 +00004601 if (LocaleCompare("}",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004602 /* pop image_info settings from stack */
4603 Stack
4604 *node;
4605
4606 node = (void *)cli_wand->image_info_stack;
4607 if ( node == (Stack *)NULL)
anthony4d4f2c72012-03-22 03:22:03 +00004608 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
anthony43f425d2012-02-26 12:58:58 +00004609 cli_wand->image_info_stack = node->next;
4610
4611 (void) DestroyImageInfo(cli_wand->wand.image_info);
4612 cli_wand->wand.image_info = (ImageInfo *)node->data;
4613 node = (Stack *)RelinquishMagickMemory(node);
4614
4615 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4616 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4617 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4618
4619 return;
4620 }
anthonyce8dcb32012-03-21 13:20:31 +00004621 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004622 Image
4623 *new_images;
4624
4625 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004626 arg1="-1";
4627 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004628 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004629 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004630 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004631 new_images = (Image *)cli_wand->image_list_stack->data;
4632 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004633 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4634 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004635 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004636 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004637 AppendImageToList(&cli_wand->wand.images,new_images);
4638 return;
4639 }
anthony319dac62012-03-06 04:12:44 +00004640 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthonyce8dcb32012-03-21 13:20:31 +00004641 ( LocaleCompare("--",option) == 0 ) ) {
anthonyafa3dfc2012-03-03 11:31:30 +00004642#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004643 Image *
4644 new_images;
4645
anthony43f425d2012-02-26 12:58:58 +00004646 if (cli_wand->wand.image_info->ping != MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004647 new_images=PingImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004648 else
anthony92c93bd2012-03-19 14:02:47 +00004649 new_images=ReadImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004650 AppendImageToList(&cli_wand->wand.images, new_images);
4651#else
4652 /* read images using MagickWand method - no ping */
4653 /* This is not working! - it locks up in a CPU loop! */
4654 MagickSetLastIterator(&cli_wand->wand);
anthony24aa8822012-03-11 00:56:06 +00004655 MagickReadImage(&cli_wand->wand,arg1);
anthony43f425d2012-02-26 12:58:58 +00004656 MagickSetFirstIterator(&cli_wand->wand);
4657#endif
4658 return;
4659 }
anthonyafa3dfc2012-03-03 11:31:30 +00004660 /* No-op options */
4661 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004662 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004663 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004664 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004665 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004666 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004667 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004668 return;
anthonyce8dcb32012-03-21 13:20:31 +00004669 if (LocaleCompare("list",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004670 /* FUTURE: This should really be built into the MagickCore
4671 It does not actually require any wand or images at all!
4672 */
4673 ssize_t
4674 list;
4675
anthony24aa8822012-03-11 00:56:06 +00004676 list=ParseCommandOption(MagickListOptions,MagickFalse, arg1);
anthonyfe1aa782012-03-24 13:43:04 +00004677 if ( list < 0 ) {
4678 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4679 return;
4680 }
anthony43f425d2012-02-26 12:58:58 +00004681 switch (list)
4682 {
4683 case MagickCoderOptions:
4684 {
anthony92c93bd2012-03-19 14:02:47 +00004685 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004686 break;
4687 }
4688 case MagickColorOptions:
4689 {
anthony92c93bd2012-03-19 14:02:47 +00004690 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004691 break;
4692 }
4693 case MagickConfigureOptions:
4694 {
anthony92c93bd2012-03-19 14:02:47 +00004695 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004696 break;
4697 }
4698 case MagickDelegateOptions:
4699 {
anthony92c93bd2012-03-19 14:02:47 +00004700 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004701 break;
4702 }
4703 case MagickFontOptions:
4704 {
anthony92c93bd2012-03-19 14:02:47 +00004705 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004706 break;
4707 }
4708 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004709 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004710 break;
4711 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004712 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004713 break;
4714 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004715 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004716 break;
4717 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004718 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004719 break;
4720 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004721 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004722 break;
4723 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004724 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004725 break;
4726 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004727 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004728 break;
4729 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004730 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004731 break;
4732 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004733 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004734 break;
4735 default:
4736 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004737 _exception);
anthony43f425d2012-02-26 12:58:58 +00004738 break;
4739 }
4740 return;
4741 }
4742
4743#if 0
4744 // adjust stack handling
4745 // Other 'special' options this should handle
4746 // "region" "list" "version"
4747 // It does not do "exit" however as due to its side-effect requirements
4748#endif
4749#if 0
4750 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004751#endif
anthonyebb73a22012-03-22 14:25:52 +00004752 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004753
anthony92c93bd2012-03-19 14:02:47 +00004754#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004755}