blob: 8622bb17c78d03a882608f923de50237a418bfac [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 */
anthony5330ae02012-03-20 14:17:01 +0000717 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
718 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000719 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000720 break;
721 }
anthonyafa3dfc2012-03-03 11:31:30 +0000722 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000723 {
anthony92c93bd2012-03-19 14:02:47 +0000724 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000725 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000726 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000727 */
anthony74b1cfc2011-10-06 12:44:16 +0000728 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000729 {
anthony92c93bd2012-03-19 14:02:47 +0000730 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000731 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000732 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000733 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000734 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000735 break;
736 }
anthony92c93bd2012-03-19 14:02:47 +0000737 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000738 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000739 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000740 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000741 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000742 break;
743 }
anthonyafa3dfc2012-03-03 11:31:30 +0000744 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000745 {
anthonyfd706f92012-01-19 04:22:02 +0000746 /* DEPRECIATED - now "undercolor" */
anthony24aa8822012-03-11 00:56:06 +0000747 CLISettingOptionInfo(cli_wand,"undercolor",arg1);
anthonyfd706f92012-01-19 04:22:02 +0000748 break;
anthony805a2d42011-09-25 08:25:12 +0000749 }
anthonyebb73a22012-03-22 14:25:52 +0000750 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000751 }
752 case 'c':
753 {
anthonyafa3dfc2012-03-03 11:31:30 +0000754 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000755 {
756 MagickSizeType
757 limit;
758
anthony5330ae02012-03-20 14:17:01 +0000759 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
760 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000761 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000762 if (LocaleCompare("unlimited",arg1) != 0)
763 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000764 (void) SetMagickResourceLimit(MemoryResource,limit);
765 (void) SetMagickResourceLimit(MapResource,2*limit);
766 break;
767 }
anthonyafa3dfc2012-03-03 11:31:30 +0000768 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000769 {
anthony92c93bd2012-03-19 14:02:47 +0000770 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000771 break;
772 }
anthonyafa3dfc2012-03-03 11:31:30 +0000773 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000774 {
anthony30b912a2012-03-22 01:20:28 +0000775 arg1=ArgOption("default");
776 parse=ParseChannelOption(arg1);
777 if (parse < 0)
778 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
779 option,arg1);
780 _image_info->channel=(ChannelType) parse;
781 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000782 break;
783 }
anthonyafa3dfc2012-03-03 11:31:30 +0000784 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000785 {
anthonyafbaed72011-10-26 12:05:04 +0000786 /* Setting used for new images via AquireImage()
787 But also used as a SimpleImageOperator
788 Undefined colorspace means don't modify images on
789 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000790 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
791 ArgOption("undefined"));
792 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000793 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
794 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000795 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000796 break;
797 }
anthonyafa3dfc2012-03-03 11:31:30 +0000798 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000799 {
anthony92c93bd2012-03-19 14:02:47 +0000800 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000801 break;
802 }
anthonyafa3dfc2012-03-03 11:31:30 +0000803 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000804 {
anthony92c93bd2012-03-19 14:02:47 +0000805 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000806 SyncImageSettings() used to set per-image attribute. - REMOVE
807
anthonyafbaed72011-10-26 12:05:04 +0000808 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000809 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000810 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000811 */
anthonyebb73a22012-03-22 14:25:52 +0000812 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
813 ArgOption("undefined"));
814 if (parse < 0)
815 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
816 option,arg1);
817 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000818 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000819 break;
820 }
anthonyafa3dfc2012-03-03 11:31:30 +0000821 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000822 {
anthony92c93bd2012-03-19 14:02:47 +0000823 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000824 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000825 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000826
anthony92c93bd2012-03-19 14:02:47 +0000827 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000828 however the image attribute (for save) is set from the
829 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000830
831 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000832 */
anthonyebb73a22012-03-22 14:25:52 +0000833 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
834 ArgOption("undefined"));
835 if (parse < 0)
836 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
837 option,arg1);
838 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000839 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000840 break;
841 }
anthonyebb73a22012-03-22 14:25:52 +0000842 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000843 }
844 case 'd':
845 {
anthonyafa3dfc2012-03-03 11:31:30 +0000846 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000847 {
anthony72feaa62012-01-17 06:46:23 +0000848 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000849 arg1=ArgOption("none");
850 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
851 if (parse < 0)
852 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
853 option,arg1);
854 (void) SetLogEventMask(arg1);
855 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000856 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000857 break;
858 }
anthonyafa3dfc2012-03-03 11:31:30 +0000859 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000860 {
anthony24aa8822012-03-11 00:56:06 +0000861 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000862 {
anthony5f867ae2011-10-09 10:28:34 +0000863 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000864 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000865 else
anthony24aa8822012-03-11 00:56:06 +0000866 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000867 break;
868 }
anthony24aa8822012-03-11 00:56:06 +0000869 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000870 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000871 (void) DefineImageOption(_image_info,arg1);
anthonyebb73a22012-03-22 14:25:52 +0000872 else if ( DeleteImageOption(_image_info,arg1) == MagickFalse )
873 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000874 break;
875 }
anthonyafa3dfc2012-03-03 11:31:30 +0000876 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000877 {
anthonyafbaed72011-10-26 12:05:04 +0000878 /* Only used for new images via AcquireImage()
879 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000880 */
anthonyebb73a22012-03-22 14:25:52 +0000881 arg1=ArgOption("0");
882 if (IsGeometry(arg1) == MagickFalse)
883 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
884 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000885 break;
886 }
anthonyafa3dfc2012-03-03 11:31:30 +0000887 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000888 {
anthony92c93bd2012-03-19 14:02:47 +0000889 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000890 Basically as density can be in a XxY form!
891
892 SyncImageSettings() used to set per-image attribute.
893 */
anthonyebb73a22012-03-22 14:25:52 +0000894 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
895 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000896 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
897 (void) CloneString(&_image_info->density,ArgOption(NULL));
898 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000899 break;
900 }
anthonyafa3dfc2012-03-03 11:31:30 +0000901 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000902 {
anthony72feaa62012-01-17 06:46:23 +0000903 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
904 SyncImageSettings() used to set per-image attribute.
905 */
anthonyebb73a22012-03-22 14:25:52 +0000906 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
907 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000908 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000909 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000910 break;
911 }
anthonyafa3dfc2012-03-03 11:31:30 +0000912 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000913 {
anthony92c93bd2012-03-19 14:02:47 +0000914 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000915 arg1=ArgOption("undefined");
916 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
917 if (parse < 0)
918 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
919 option,arg1);
920 _draw_info->direction=(DirectionType) parse;
921 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000922 break;
923 }
anthonyafa3dfc2012-03-03 11:31:30 +0000924 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000925 {
anthony92c93bd2012-03-19 14:02:47 +0000926 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
927 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000928 break;
929 }
anthonyafa3dfc2012-03-03 11:31:30 +0000930 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000931 {
anthony72feaa62012-01-17 06:46:23 +0000932 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000933 arg1=ArgOption("undefined");
934 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
935 if (parse < 0)
936 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
937 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000938 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000939 break;
940 }
anthonyafa3dfc2012-03-03 11:31:30 +0000941 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000942 {
anthony92c93bd2012-03-19 14:02:47 +0000943 /* _image_info attr (on/off), _quantize_info attr (on/off)
944 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000945 FUTURE: merge the duality of the dithering options
946 */
anthony92c93bd2012-03-19 14:02:47 +0000947 _image_info->dither = _quantize_info->dither = ArgBoolean;
948 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
949 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000950 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000951 if (_quantize_info->dither_method == NoDitherMethod)
952 _image_info->dither = _quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000953 break;
954 }
anthonyebb73a22012-03-22 14:25:52 +0000955 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000956 }
957 case 'e':
958 {
anthonyafa3dfc2012-03-03 11:31:30 +0000959 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000960 {
anthony92c93bd2012-03-19 14:02:47 +0000961 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
962 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000963 break;
964 }
anthonyafa3dfc2012-03-03 11:31:30 +0000965 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000966 {
anthony92c93bd2012-03-19 14:02:47 +0000967 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000968 arg1 = ArgOption("undefined");
969 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
970 if (parse < 0)
971 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
972 option,arg1);
973 _image_info->endian=(EndianType) arg1;
974 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000975 break;
976 }
anthonyafa3dfc2012-03-03 11:31:30 +0000977 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000978 {
anthony92c93bd2012-03-19 14:02:47 +0000979 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000980 break;
981 }
anthonyebb73a22012-03-22 14:25:52 +0000982 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000983 }
984 case 'f':
985 {
anthonyafa3dfc2012-03-03 11:31:30 +0000986 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000987 {
anthony92c93bd2012-03-19 14:02:47 +0000988 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000989 break;
990 }
anthonyafa3dfc2012-03-03 11:31:30 +0000991 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000992 {
anthony92c93bd2012-03-19 14:02:47 +0000993 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000994 The original fill color is preserved if a fill-pattern is given.
995 That way it does not effect other operations that directly using
996 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000997 */
anthony72feaa62012-01-17 06:46:23 +0000998 MagickBooleanType
999 status;
anthony6dc09cd2011-10-12 08:56:49 +00001000
1001 ExceptionInfo
1002 *sans;
1003
anthonyfd706f92012-01-19 04:22:02 +00001004 PixelInfo
1005 color;
1006
anthony2a0ec8c2012-03-24 04:35:56 +00001007 arg1 = ArgOption("none"); /* +fill turns it off! */
1008 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001009 if (_draw_info->fill_pattern != (Image *) NULL)
1010 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +00001011
1012 /* is it a color or a image? -- ignore exceptions */
1013 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001014 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +00001015 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001016
anthony6dc09cd2011-10-12 08:56:49 +00001017 if (status == MagickFalse)
anthony2a0ec8c2012-03-24 04:35:56 +00001018 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001019 else
anthony92c93bd2012-03-19 14:02:47 +00001020 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +00001021 break;
1022 }
anthonyafa3dfc2012-03-03 11:31:30 +00001023 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001024 {
anthony72feaa62012-01-17 06:46:23 +00001025 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +00001026 arg1 = ArgOption("undefined");
1027 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
1028 if (parse < 0)
1029 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
1030 option,arg1);
1031 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001032 break;
1033 }
anthonyafa3dfc2012-03-03 11:31:30 +00001034 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001035 {
anthony92c93bd2012-03-19 14:02:47 +00001036 (void) CloneString(&_draw_info->font,ArgOption(NULL));
1037 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +00001038 break;
1039 }
anthonyafa3dfc2012-03-03 11:31:30 +00001040 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001041 {
anthonydcf510d2011-10-30 13:51:40 +00001042 /* FUTURE: why the ping test, you could set ping after this! */
1043 /*
anthony805a2d42011-09-25 08:25:12 +00001044 register const char
1045 *q;
1046
anthony24aa8822012-03-11 00:56:06 +00001047 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +00001048 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00001049 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +00001050 */
anthony92c93bd2012-03-19 14:02:47 +00001051 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001052 break;
1053 }
anthonyafa3dfc2012-03-03 11:31:30 +00001054 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001055 {
anthony72feaa62012-01-17 06:46:23 +00001056 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +00001057 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +00001058 SyncImageSettings() used to set per-image attribute.
1059
anthony2a0ec8c2012-03-24 04:35:56 +00001060 FUTURE: Can't find anything else using _image_info->fuzz directly!
1061 remove direct sttribute from image_info
anthony6613bf32011-10-15 07:24:44 +00001062 */
anthony2a0ec8c2012-03-24 04:35:56 +00001063 arg1=ArgOption("0");
1064 if (IsGeometry(arg1) == MagickFalse)
1065 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1066 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +00001067 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00001068 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001069 break;
1070 }
anthonyebb73a22012-03-22 14:25:52 +00001071 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001072 }
1073 case 'g':
1074 {
anthonyafa3dfc2012-03-03 11:31:30 +00001075 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001076 {
anthony72feaa62012-01-17 06:46:23 +00001077 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001078 arg1 = ArgOption("none");
1079 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
1080 if (parse < 0)
1081 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
1082 option,arg1);
1083 (void) SetImageOption(_image_info,option+1,arg1);
1084 _draw_info->gravity=(GravityType) parse;
anthony805a2d42011-09-25 08:25:12 +00001085 break;
1086 }
anthonyafa3dfc2012-03-03 11:31:30 +00001087 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001088 {
anthonydcf510d2011-10-30 13:51:40 +00001089 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +00001090 SyncImageSettings() used to set per-image attribute.
1091 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +00001092 */
anthonyfe1aa782012-03-24 13:43:04 +00001093 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1094 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001095 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001096 break;
1097 }
anthonyebb73a22012-03-22 14:25:52 +00001098 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001099 }
1100 case 'i':
1101 {
anthonyafa3dfc2012-03-03 11:31:30 +00001102 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001103 {
anthony72feaa62012-01-17 06:46:23 +00001104 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +00001105 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +00001106 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001107 */
anthonyfe1aa782012-03-24 13:43:04 +00001108 arg1 = ArgOption("indefined");
1109 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
1110 if (parse < 0)
1111 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
1112 option,arg1);
1113 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001114 break;
1115 }
anthonyafa3dfc2012-03-03 11:31:30 +00001116 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001117 {
anthony92c93bd2012-03-19 14:02:47 +00001118 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +00001119 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001120 */
anthonyfe1aa782012-03-24 13:43:04 +00001121 arg1 = ArgOption("undefined");
1122 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
1123 if (parse < 0)
1124 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
1125 option,arg1);
1126 _image_info->interlace=(InterlaceType) parse;
1127 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001128 break;
1129 }
anthonyafa3dfc2012-03-03 11:31:30 +00001130 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001131 {
anthonyfe1aa782012-03-24 13:43:04 +00001132 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1133 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001134 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1135 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001136 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001137 break;
1138 }
anthonyafa3dfc2012-03-03 11:31:30 +00001139 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001140 {
anthonyfd706f92012-01-19 04:22:02 +00001141 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001142 arg1 = ArgOption("undefined");
1143 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1144 if (parse < 0)
1145 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1146 option,arg1);
1147 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001148 break;
1149 }
anthonyafa3dfc2012-03-03 11:31:30 +00001150 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001151 {
anthonyfe1aa782012-03-24 13:43:04 +00001152 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1153 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001154 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1155 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001156 break;
1157 }
anthonyebb73a22012-03-22 14:25:52 +00001158 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001159 }
1160 case 'k':
1161 {
anthonyafa3dfc2012-03-03 11:31:30 +00001162 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001163 {
anthonyfe1aa782012-03-24 13:43:04 +00001164 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1165 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001166 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1167 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001168 break;
1169 }
anthonyebb73a22012-03-22 14:25:52 +00001170 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001171 }
1172 case 'l':
1173 {
anthonyafa3dfc2012-03-03 11:31:30 +00001174 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001175 {
anthony72feaa62012-01-17 06:46:23 +00001176 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001177 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001178 break;
1179 }
anthonyafa3dfc2012-03-03 11:31:30 +00001180 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001181 {
anthonyfe1aa782012-03-24 13:43:04 +00001182 if (IfSetOption) {
1183 if ((strchr(arg1,'%') == (char *) NULL))
1184 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony24aa8822012-03-11 00:56:06 +00001185 (void) SetLogFormat(arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001186 }
anthony805a2d42011-09-25 08:25:12 +00001187 break;
1188 }
anthonyafa3dfc2012-03-03 11:31:30 +00001189 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001190 {
anthony72feaa62012-01-17 06:46:23 +00001191 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001192 arg1=ArgOption("0");
1193 if (IsGeometry(arg1) == MagickFalse)
1194 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1195 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001196 break;
1197 }
anthonyebb73a22012-03-22 14:25:52 +00001198 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001199 }
1200 case 'm':
1201 {
anthonyafa3dfc2012-03-03 11:31:30 +00001202 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001203 {
anthony72feaa62012-01-17 06:46:23 +00001204 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001205 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001206 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001207 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001208 break;
1209 }
anthonyafa3dfc2012-03-03 11:31:30 +00001210 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001211 {
anthony92c93bd2012-03-19 14:02:47 +00001212 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001213 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001214 break;
1215 }
anthonyafa3dfc2012-03-03 11:31:30 +00001216 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001217 {
anthony24aa8822012-03-11 00:56:06 +00001218 /* Setting (used by some input coders!) -- why?
1219 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001220 */
anthony92c93bd2012-03-19 14:02:47 +00001221 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001222 break;
1223 }
anthonyebb73a22012-03-22 14:25:52 +00001224 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001225 }
1226 case 'o':
1227 {
anthonyafa3dfc2012-03-03 11:31:30 +00001228 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001229 {
anthony72feaa62012-01-17 06:46:23 +00001230 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001231 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001232 FUTURE: make set meta-data operator instead.
1233 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001234 */
anthony7bc87992012-03-25 02:32:51 +00001235 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1236 ArgOption("undefined"));
1237 if (parse < 0)
1238 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1239 option,arg1);
1240 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001241 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001242 break;
1243 }
anthonyebb73a22012-03-22 14:25:52 +00001244 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001245 }
1246 case 'p':
1247 {
anthonyafa3dfc2012-03-03 11:31:30 +00001248 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001249 {
anthony7bc87992012-03-25 02:32:51 +00001250 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001251 SyncImageSettings() used to set per-image attribute. ?????
1252 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001253 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001254 */
anthony805a2d42011-09-25 08:25:12 +00001255 char
1256 *canonical_page,
1257 page[MaxTextExtent];
1258
1259 const char
1260 *image_option;
1261
1262 MagickStatusType
1263 flags;
1264
1265 RectangleInfo
1266 geometry;
1267
anthonydcf510d2011-10-30 13:51:40 +00001268 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001269 {
anthony92c93bd2012-03-19 14:02:47 +00001270 (void) DeleteImageOption(_image_info,option+1);
1271 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001272 break;
1273 }
1274 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001275 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001276 if (image_option != (const char *) NULL)
1277 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001278 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001279 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1280 canonical_page=DestroyString(canonical_page);
1281 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1282 (unsigned long) geometry.width,(unsigned long) geometry.height);
1283 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1284 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1285 (unsigned long) geometry.width,(unsigned long) geometry.height,
1286 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001287 (void) SetImageOption(_image_info,option+1,page);
1288 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001289 break;
1290 }
anthonyafa3dfc2012-03-03 11:31:30 +00001291 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001292 {
anthony92c93bd2012-03-19 14:02:47 +00001293 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001294 break;
1295 }
anthonyafa3dfc2012-03-03 11:31:30 +00001296 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001297 {
anthony7bc87992012-03-25 02:32:51 +00001298 if (IsGeometry(arg1) == MagickFalse)
1299 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001300 _image_info->pointsize=_draw_info->pointsize=
anthony72feaa62012-01-17 06:46:23 +00001301 StringToDouble(ArgOption("12"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001302 break;
1303 }
anthonyafa3dfc2012-03-03 11:31:30 +00001304 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001305 {
anthony72feaa62012-01-17 06:46:23 +00001306 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
anthony805a2d42011-09-25 08:25:12 +00001307 break;
1308 }
anthonydcf510d2011-10-30 13:51:40 +00001309 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001310 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001311 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001312 {
anthony92c93bd2012-03-19 14:02:47 +00001313 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001314 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001315 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001316 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001317 break;
1318 }
anthonydcf510d2011-10-30 13:51:40 +00001319 */
anthonyebb73a22012-03-22 14:25:52 +00001320 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001321 }
1322 case 'q':
1323 {
anthonyafa3dfc2012-03-03 11:31:30 +00001324 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001325 {
anthony7bc87992012-03-25 02:32:51 +00001326 if (IsGeometry(arg1) == MagickFalse)
1327 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001328 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1329 _image_info->quality=UNDEFINED_COMPRESSION_QUALITY;
anthony72feaa62012-01-17 06:46:23 +00001330 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001331 _image_info->quality=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00001332 break;
1333 }
anthonyafa3dfc2012-03-03 11:31:30 +00001334 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001335 {
anthony92c93bd2012-03-19 14:02:47 +00001336 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001337 arg1=ArgOption("undefined");
1338 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1339 if (parse < 0)
1340 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1341 option,arg1);
1342 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001343 break;
1344 }
anthonyafa3dfc2012-03-03 11:31:30 +00001345 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001346 {
anthonydcf510d2011-10-30 13:51:40 +00001347 /* FUTURE: if two -quiet is performed you can not do +quiet! */
anthony805a2d42011-09-25 08:25:12 +00001348 static WarningHandler
1349 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001350
anthonyafbaed72011-10-26 12:05:04 +00001351 WarningHandler
1352 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001353
anthonyafbaed72011-10-26 12:05:04 +00001354 if ( tmp != (WarningHandler) NULL)
1355 warning_handler = tmp; /* remember the old handler */
1356 if (!IfSetOption) /* set the old handler */
1357 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001358 break;
1359 }
anthonyebb73a22012-03-22 14:25:52 +00001360 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001361 }
1362 case 'r':
1363 {
anthonyafa3dfc2012-03-03 11:31:30 +00001364 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001365 {
anthonydcf510d2011-10-30 13:51:40 +00001366 /* Image chromaticity X,Y NB: Y=X if Y not defined
1367 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001368 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001369 */
anthonyfe1aa782012-03-24 13:43:04 +00001370 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1371 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001372 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001373 break;
1374 }
anthonyafa3dfc2012-03-03 11:31:30 +00001375 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001376 {
anthony92c93bd2012-03-19 14:02:47 +00001377 /* _draw_info only setting */
1378 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001379 break;
1380 }
anthonyebb73a22012-03-22 14:25:52 +00001381 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001382 }
1383 case 's':
1384 {
anthonyafa3dfc2012-03-03 11:31:30 +00001385 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001386 {
anthonyafbaed72011-10-26 12:05:04 +00001387 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony92c93bd2012-03-19 14:02:47 +00001388 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001389 break;
1390 }
anthonyafa3dfc2012-03-03 11:31:30 +00001391 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001392 {
anthony72feaa62012-01-17 06:46:23 +00001393 /* SyncImageSettings() used to set per-image attribute.
1394 What ??? Why ????
1395 */
anthony92c93bd2012-03-19 14:02:47 +00001396 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1397 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001398 break;
1399 }
anthonyafa3dfc2012-03-03 11:31:30 +00001400 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001401 {
anthonyafbaed72011-10-26 12:05:04 +00001402 SeedPseudoRandomGenerator(
anthony24aa8822012-03-11 00:56:06 +00001403 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001404 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001405 break;
1406 }
anthonyafa3dfc2012-03-03 11:31:30 +00001407 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001408 {
anthony92c93bd2012-03-19 14:02:47 +00001409 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001410 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001411 */
anthony92c93bd2012-03-19 14:02:47 +00001412 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001413 break;
1414 }
anthonyafa3dfc2012-03-03 11:31:30 +00001415 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001416 {
anthony92c93bd2012-03-19 14:02:47 +00001417 _draw_info->stretch=(StretchType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001418 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001419 break;
1420 }
anthonyafa3dfc2012-03-03 11:31:30 +00001421 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001422 {
anthonyafbaed72011-10-26 12:05:04 +00001423 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001424 UPDATE: ensure stroke color is not destroyed is a pattern
1425 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001426 */
anthony72feaa62012-01-17 06:46:23 +00001427 MagickBooleanType
1428 status;
anthonyafbaed72011-10-26 12:05:04 +00001429
1430 ExceptionInfo
1431 *sans;
1432
anthonyfd706f92012-01-19 04:22:02 +00001433 PixelInfo
1434 color;
1435
anthony2a0ec8c2012-03-24 04:35:56 +00001436 arg1 = ArgOption("none"); /* +fill turns it off! */
1437 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001438 if (_draw_info->stroke_pattern != (Image *) NULL)
1439 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001440
1441 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001442 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001443 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001444 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001445
anthonyafbaed72011-10-26 12:05:04 +00001446 if (status == MagickFalse)
anthony2a0ec8c2012-03-24 04:35:56 +00001447 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001448 else
anthony92c93bd2012-03-19 14:02:47 +00001449 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001450 break;
1451 }
anthonyafa3dfc2012-03-03 11:31:30 +00001452 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001453 {
anthony92c93bd2012-03-19 14:02:47 +00001454 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1455 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001456 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001457 break;
1458 }
anthonyafa3dfc2012-03-03 11:31:30 +00001459 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001460 {
anthony92c93bd2012-03-19 14:02:47 +00001461 _draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
anthony72feaa62012-01-17 06:46:23 +00001462 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001463 break;
1464 }
anthonyafa3dfc2012-03-03 11:31:30 +00001465 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001466 {
anthony92c93bd2012-03-19 14:02:47 +00001467 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001468 break;
1469 }
anthonyebb73a22012-03-22 14:25:52 +00001470 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001471 }
1472 case 't':
1473 {
anthonyafa3dfc2012-03-03 11:31:30 +00001474 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001475 {
anthony72feaa62012-01-17 06:46:23 +00001476 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001477 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001478 break;
1479 }
anthonyafa3dfc2012-03-03 11:31:30 +00001480 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001481 {
anthony92c93bd2012-03-19 14:02:47 +00001482 /* FUTURE: move _image_info string to option splay-tree */
1483 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001484 break;
1485 }
anthonyafa3dfc2012-03-03 11:31:30 +00001486 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001487 {
anthony92c93bd2012-03-19 14:02:47 +00001488 _draw_info->fill_pattern=IfSetOption
1489 ?GetImageCache(_image_info,arg1,_exception)
1490 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001491 break;
1492 }
anthonyafa3dfc2012-03-03 11:31:30 +00001493 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001494 {
anthony72feaa62012-01-17 06:46:23 +00001495 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony92c93bd2012-03-19 14:02:47 +00001496 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001497 break;
1498 }
anthonyafa3dfc2012-03-03 11:31:30 +00001499 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001500 {
anthony92c93bd2012-03-19 14:02:47 +00001501 /* FUTURE: both _image_info attribute & ImageOption in use!
1502 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001503 SyncImageSettings() used to set per-image attribute.
1504
anthonyafbaed72011-10-26 12:05:04 +00001505 Note that +transparent-color, means fall-back to image
1506 attribute so ImageOption is deleted, not set to a default.
1507 */
anthony92c93bd2012-03-19 14:02:47 +00001508 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001509 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001510 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001511 break;
1512 }
anthonyafa3dfc2012-03-03 11:31:30 +00001513 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001514 {
anthony92c93bd2012-03-19 14:02:47 +00001515 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1516 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001517 break;
1518 }
anthonyafa3dfc2012-03-03 11:31:30 +00001519 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001520 {
anthony72feaa62012-01-17 06:46:23 +00001521 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001522 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1523 _image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
anthony72feaa62012-01-17 06:46:23 +00001524 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001525 break;
1526 }
anthonyebb73a22012-03-22 14:25:52 +00001527 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001528 }
1529 case 'u':
1530 {
anthonyafa3dfc2012-03-03 11:31:30 +00001531 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001532 {
anthony92c93bd2012-03-19 14:02:47 +00001533 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001534 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001535 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001536 break;
1537 }
anthonyafa3dfc2012-03-03 11:31:30 +00001538 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001539 {
anthony72feaa62012-01-17 06:46:23 +00001540 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001541 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001542 FUTURE: this probably should be part of the density setting
1543 */
anthony92c93bd2012-03-19 14:02:47 +00001544 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1545 _image_info->units=(ResolutionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001546 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001547 break;
1548 }
anthonyebb73a22012-03-22 14:25:52 +00001549 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001550 }
1551 case 'v':
1552 {
anthonyafa3dfc2012-03-03 11:31:30 +00001553 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001554 {
anthony24aa8822012-03-11 00:56:06 +00001555 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001556 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001557 */
anthony92c93bd2012-03-19 14:02:47 +00001558 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1559 _image_info->verbose= ArgBoolean;
1560 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001561 break;
1562 }
anthonyafa3dfc2012-03-03 11:31:30 +00001563 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001564 {
anthony92c93bd2012-03-19 14:02:47 +00001565 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001566 Only used by coder FPX
1567 */
anthony92c93bd2012-03-19 14:02:47 +00001568 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001569 break;
1570 }
anthonyafa3dfc2012-03-03 11:31:30 +00001571 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001572 {
anthonyfd706f92012-01-19 04:22:02 +00001573 /* SyncImageSettings() used to set per-image attribute.
1574 This is VERY deep in the image caching structure.
1575 */
anthony92c93bd2012-03-19 14:02:47 +00001576 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001577 break;
1578 }
anthonyebb73a22012-03-22 14:25:52 +00001579 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001580 }
1581 case 'w':
1582 {
anthonyafa3dfc2012-03-03 11:31:30 +00001583 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001584 {
anthony72feaa62012-01-17 06:46:23 +00001585 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001586 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001587 */
anthony72feaa62012-01-17 06:46:23 +00001588 if (!IfSetOption)
1589 break;
anthony92c93bd2012-03-19 14:02:47 +00001590 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001591 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001592 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001593 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001594 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001595 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001596 if (_draw_info->weight <= 800)
1597 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001598 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001599 if (_draw_info->weight >= 100)
1600 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001601 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001602 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001603 break;
1604 }
anthonyafa3dfc2012-03-03 11:31:30 +00001605 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001606 {
anthony72feaa62012-01-17 06:46:23 +00001607 /* Used as a image chromaticity setting
1608 SyncImageSettings() used to set per-image attribute.
1609 */
anthony92c93bd2012-03-19 14:02:47 +00001610 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001611 break;
1612 }
anthonyebb73a22012-03-22 14:25:52 +00001613 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001614 }
1615 default:
anthonyebb73a22012-03-22 14:25:52 +00001616 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001617 }
anthony24aa8822012-03-11 00:56:06 +00001618
anthony92c93bd2012-03-19 14:02:47 +00001619#undef _image_info
1620#undef _exception
1621#undef _draw_info
1622#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001623#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001624#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001625#undef ArgBooleanNot
1626#undef ArgBooleanString
1627#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001628
anthony31f1bf72012-01-30 12:37:22 +00001629 return;
anthony805a2d42011-09-25 08:25:12 +00001630}
1631
1632/*
1633%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634% %
1635% %
1636% %
anthony43f425d2012-02-26 12:58:58 +00001637+ 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 +00001638% %
1639% %
1640% %
1641%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1642%
anthony31f1bf72012-01-30 12:37:22 +00001643% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001644% the images in the CLI wand, with the settings that was previously saved in
1645% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001646%
1647% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001648% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001649%
anthonyd1447672012-01-19 05:33:53 +00001650% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001651%
anthony43f425d2012-02-26 12:58:58 +00001652% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001653% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001654%
1655% A description of each parameter follows:
1656%
anthony43f425d2012-02-26 12:58:58 +00001657% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001658%
anthonyfd706f92012-01-19 04:22:02 +00001659% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001660%
anthonyfd706f92012-01-19 04:22:02 +00001661% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001662%
anthony31f1bf72012-01-30 12:37:22 +00001663% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001664%
anthony31f1bf72012-01-30 12:37:22 +00001665% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001666%
anthonyafa3dfc2012-03-03 11:31:30 +00001667% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1668% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1669% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001670%
anthony24aa8822012-03-11 00:56:06 +00001671% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001672%
anthony43f425d2012-02-26 12:58:58 +00001673% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001674% argc,argv
1675% i=index in argv
1676%
anthony2052d272012-02-28 12:48:29 +00001677% option_info = GetCommandOptionInfo(argv[i]);
1678% count=option_info->type;
1679% option_type=option_info->flags;
1680%
1681% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001682% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001683% count>=1 ? argv[i+1] : (char *)NULL,
1684% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001685% i += count+1;
1686%
anthony805a2d42011-09-25 08:25:12 +00001687*/
anthony31f1bf72012-01-30 12:37:22 +00001688
1689/*
1690 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001691 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001692
1693 The image in the list may be modified in three different ways...
1694 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1695 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1696 * one image replace by a list of images (-separate and -crop only!)
1697
anthonyafa3dfc2012-03-03 11:31:30 +00001698 In each case the result replaces the single original image in the list, as
1699 well as the pointer to the modified image (last image added if replaced by a
1700 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001701
1702 As the image pointed to may be replaced, the first image in the list may
1703 also change. GetFirstImageInList() should be used by caller if they wish
1704 return the Image pointer to the first image in list.
1705*/
anthony43f425d2012-02-26 12:58:58 +00001706static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001707 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001708{
1709 Image *
1710 new_image;
1711
anthony805a2d42011-09-25 08:25:12 +00001712 GeometryInfo
1713 geometry_info;
1714
1715 RectangleInfo
1716 geometry;
1717
1718 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001719 flags;
1720
anthony92c93bd2012-03-19 14:02:47 +00001721 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001722 parse;
anthony92c93bd2012-03-19 14:02:47 +00001723
1724#define _image_info (cli_wand->wand.image_info)
1725#define _image (cli_wand->wand.images)
1726#define _exception (cli_wand->wand.exception)
1727#define _draw_info (cli_wand->draw_info)
1728#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001729#define IfNormalOp (*option=='-')
1730#define IfPlusOp (*option!='-')
1731#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1732#define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001733
anthony43f425d2012-02-26 12:58:58 +00001734 assert(cli_wand != (MagickCLI *) NULL);
1735 assert(cli_wand->signature == WandSignature);
1736 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001737 assert(_image != (Image *) NULL); /* an image must be present */
anthony43f425d2012-02-26 12:58:58 +00001738 if (cli_wand->wand.debug != MagickFalse)
1739 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001740
anthony92c93bd2012-03-19 14:02:47 +00001741 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001742
anthony805a2d42011-09-25 08:25:12 +00001743 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001744
anthony5330ae02012-03-20 14:17:01 +00001745 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001746
anthonyfd706f92012-01-19 04:22:02 +00001747 /* FUTURE: We may need somthing a little more optimized than this!
1748 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1749 */
anthonyafa3dfc2012-03-03 11:31:30 +00001750 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001751 {
1752 case 'a':
1753 {
anthonyafa3dfc2012-03-03 11:31:30 +00001754 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001755 {
anthony92c93bd2012-03-19 14:02:47 +00001756 if (IsGeometry(arg1) == MagickFalse)
1757 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001758 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001759 if ((flags & SigmaValue) == 0)
1760 geometry_info.sigma=1.0;
1761 if ((flags & XiValue) == 0)
1762 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001763 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1764 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001765 break;
1766 }
anthonyafa3dfc2012-03-03 11:31:30 +00001767 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001768 {
anthonyfe1aa782012-03-24 13:43:04 +00001769 /* FUTURE: Roll into a resize special operator */
anthony92c93bd2012-03-19 14:02:47 +00001770 if (IsGeometry(arg1) == MagickFalse)
1771 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1772 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1773 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1774 _exception);
anthony805a2d42011-09-25 08:25:12 +00001775 break;
1776 }
anthonyafa3dfc2012-03-03 11:31:30 +00001777 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001778 {
anthony92c93bd2012-03-19 14:02:47 +00001779 if (IsGeometry(arg1) == MagickFalse)
1780 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001781 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001782 if ((flags & SigmaValue) == 0)
1783 geometry_info.sigma=1.0;
1784 if ((flags & XiValue) == 0)
1785 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001786 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1787 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001788 break;
1789 }
anthonyafa3dfc2012-03-03 11:31:30 +00001790 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001791 {
anthony2a0ec8c2012-03-24 04:35:56 +00001792 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1793 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001794 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1795 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001796 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1797 _exception);
anthony805a2d42011-09-25 08:25:12 +00001798 break;
1799 }
anthonyafa3dfc2012-03-03 11:31:30 +00001800 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001801 {
1802 char
1803 *text,
1804 geometry[MaxTextExtent];
1805
anthony92c93bd2012-03-19 14:02:47 +00001806 if (IsGeometry(arg1) == MagickFalse)
1807 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001808 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001809 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001810 if ((flags & SigmaValue) == 0)
1811 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001812 text=InterpretImageProperties(_image_info,_image,arg2,
1813 _exception);
anthony805a2d42011-09-25 08:25:12 +00001814 if (text == (char *) NULL)
1815 break;
anthony92c93bd2012-03-19 14:02:47 +00001816 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001817 text=DestroyString(text);
1818 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1819 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001820 (void) CloneString(&_draw_info->geometry,geometry);
1821 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001822 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001823 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001824 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001825 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001826 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001827 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001828 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001829 (void) AnnotateImage(_image,_draw_info,_exception);
1830 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001831 break;
1832 }
anthonyafa3dfc2012-03-03 11:31:30 +00001833 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001834 {
anthony92c93bd2012-03-19 14:02:47 +00001835 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001836 break;
1837 }
anthonyafa3dfc2012-03-03 11:31:30 +00001838 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001839 {
anthony92c93bd2012-03-19 14:02:47 +00001840 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001841 break;
1842 }
anthonyafa3dfc2012-03-03 11:31:30 +00001843 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001844 {
anthony5330ae02012-03-20 14:17:01 +00001845 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001846 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001847 {
1848 case TopRightOrientation:
1849 {
anthony92c93bd2012-03-19 14:02:47 +00001850 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001851 break;
1852 }
1853 case BottomRightOrientation:
1854 {
anthony92c93bd2012-03-19 14:02:47 +00001855 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001856 break;
1857 }
1858 case BottomLeftOrientation:
1859 {
anthony92c93bd2012-03-19 14:02:47 +00001860 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001861 break;
1862 }
1863 case LeftTopOrientation:
1864 {
anthony92c93bd2012-03-19 14:02:47 +00001865 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001866 break;
1867 }
1868 case RightTopOrientation:
1869 {
anthony92c93bd2012-03-19 14:02:47 +00001870 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001871 break;
1872 }
1873 case RightBottomOrientation:
1874 {
anthony92c93bd2012-03-19 14:02:47 +00001875 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001876 break;
1877 }
1878 case LeftBottomOrientation:
1879 {
anthony92c93bd2012-03-19 14:02:47 +00001880 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001881 break;
1882 }
1883 default:
1884 break;
1885 }
1886 if (new_image != (Image *) NULL)
1887 new_image->orientation=TopLeftOrientation;
1888 break;
1889 }
anthonyebb73a22012-03-22 14:25:52 +00001890 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001891 }
1892 case 'b':
1893 {
anthonyafa3dfc2012-03-03 11:31:30 +00001894 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001895 {
anthony5330ae02012-03-20 14:17:01 +00001896 if (IsGeometry(arg1) == MagickFalse)
1897 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001898 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001899 break;
1900 }
anthonyafa3dfc2012-03-03 11:31:30 +00001901 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001902 {
anthony805a2d42011-09-25 08:25:12 +00001903 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001904 if (IfNormalOp) {
1905 if (IsGeometry(arg1) == MagickFalse)
1906 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001907 flags=ParseGeometry(arg1,&geometry_info);
anthony5330ae02012-03-20 14:17:01 +00001908 }
anthony92c93bd2012-03-19 14:02:47 +00001909 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001910 break;
1911 }
anthonyafa3dfc2012-03-03 11:31:30 +00001912 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001913 {
anthony74b1cfc2011-10-06 12:44:16 +00001914 /* FUTURE: use of "bias" in a blur is non-sensible */
anthony5330ae02012-03-20 14:17:01 +00001915 if (IsGeometry(arg1) == MagickFalse)
1916 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001917 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001918 if ((flags & SigmaValue) == 0)
1919 geometry_info.sigma=1.0;
1920 if ((flags & XiValue) == 0)
1921 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001922 new_image=BlurImage(_image,geometry_info.rho,
1923 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001924 break;
1925 }
anthonyafa3dfc2012-03-03 11:31:30 +00001926 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001927 {
anthony31f1bf72012-01-30 12:37:22 +00001928 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001929 compose;
1930
1931 const char*
anthony5f867ae2011-10-09 10:28:34 +00001932 value;
1933
anthony5330ae02012-03-20 14:17:01 +00001934 if (IsGeometry(arg1) == MagickFalse)
1935 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1936
anthony92c93bd2012-03-19 14:02:47 +00001937 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001938 if (value != (const char *) NULL)
1939 compose=(CompositeOperator) ParseCommandOption(
1940 MagickComposeOptions,MagickFalse,value);
1941 else
anthony92c93bd2012-03-19 14:02:47 +00001942 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001943
anthony92c93bd2012-03-19 14:02:47 +00001944 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001945 if ((flags & SigmaValue) == 0)
1946 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001947 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001948 break;
1949 }
anthonyafa3dfc2012-03-03 11:31:30 +00001950 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001951 {
1952 double
1953 brightness,
1954 contrast;
1955
1956 GeometryInfo
1957 geometry_info;
1958
1959 MagickStatusType
1960 flags;
1961
anthony5330ae02012-03-20 14:17:01 +00001962 if (IsGeometry(arg1) == MagickFalse)
1963 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001964 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001965 brightness=geometry_info.rho;
1966 contrast=0.0;
1967 if ((flags & SigmaValue) != 0)
1968 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001969 (void) BrightnessContrastImage(_image,brightness,contrast,
1970 _exception);
anthony805a2d42011-09-25 08:25:12 +00001971 break;
1972 }
anthonyebb73a22012-03-22 14:25:52 +00001973 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001974 }
1975 case 'c':
1976 {
anthonyafa3dfc2012-03-03 11:31:30 +00001977 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001978 {
1979 char
1980 *color_correction_collection;
1981
1982 /*
1983 Color correct with a color decision list.
1984 */
anthony92c93bd2012-03-19 14:02:47 +00001985 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001986 if (color_correction_collection == (char *) NULL)
1987 break;
anthony92c93bd2012-03-19 14:02:47 +00001988 (void) ColorDecisionListImage(_image,color_correction_collection,
1989 _exception);
anthony805a2d42011-09-25 08:25:12 +00001990 break;
1991 }
anthonyafa3dfc2012-03-03 11:31:30 +00001992 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001993 {
anthony5330ae02012-03-20 14:17:01 +00001994 if (IsGeometry(arg1) == MagickFalse)
1995 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001996 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001997 if ((flags & SigmaValue) == 0)
1998 geometry_info.sigma=1.0;
1999 if ((flags & XiValue) == 0)
2000 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002001 new_image=CharcoalImage(_image,geometry_info.rho,
2002 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002003 break;
2004 }
anthonyafa3dfc2012-03-03 11:31:30 +00002005 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002006 {
anthony5330ae02012-03-20 14:17:01 +00002007 if (IsGeometry(arg1) == MagickFalse)
2008 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002009 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
2010 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002011 break;
2012 }
anthonyafa3dfc2012-03-03 11:31:30 +00002013 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002014 {
anthony92c93bd2012-03-19 14:02:47 +00002015 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002016 break;
2017 }
anthonyafa3dfc2012-03-03 11:31:30 +00002018 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002019 {
anthonyafa3dfc2012-03-03 11:31:30 +00002020 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002021 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00002022 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002023 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002024 break;
2025 }
anthonyafa3dfc2012-03-03 11:31:30 +00002026 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002027 {
2028 CacheView
2029 *mask_view;
2030
2031 Image
2032 *mask_image;
2033
2034 register Quantum
2035 *restrict q;
2036
2037 register ssize_t
2038 x;
2039
2040 ssize_t
2041 y;
2042
anthonyafa3dfc2012-03-03 11:31:30 +00002043 if (IfPlusOp) {
2044 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002045 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002046 break;
2047 }
anthony92c93bd2012-03-19 14:02:47 +00002048 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002049 if (mask_image == (Image *) NULL)
2050 break;
anthony92c93bd2012-03-19 14:02:47 +00002051 if (SetImageStorageClass(mask_image,DirectClass,_exception)
anthonyfd706f92012-01-19 04:22:02 +00002052 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00002053 break;
anthony5330ae02012-03-20 14:17:01 +00002054 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002055 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00002056 mask_view=AcquireCacheView(mask_image);
2057 for (y=0; y < (ssize_t) mask_image->rows; y++)
2058 {
2059 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002060 _exception);
anthony805a2d42011-09-25 08:25:12 +00002061 if (q == (Quantum *) NULL)
2062 break;
2063 for (x=0; x < (ssize_t) mask_image->columns; x++)
2064 {
2065 if (mask_image->matte == MagickFalse)
2066 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2067 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2068 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2069 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2070 q+=GetPixelChannels(mask_image);
2071 }
anthony92c93bd2012-03-19 14:02:47 +00002072 if (SyncCacheViewAuthenticPixels(mask_view,_exception) == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002073 break;
2074 }
anthonyfd706f92012-01-19 04:22:02 +00002075 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002076 mask_view=DestroyCacheView(mask_view);
2077 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002078 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002079 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002080 break;
2081 }
anthonyafa3dfc2012-03-03 11:31:30 +00002082 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002083 {
anthony92c93bd2012-03-19 14:02:47 +00002084 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002085 break;
2086 }
anthonyafa3dfc2012-03-03 11:31:30 +00002087 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002088 {
anthony5330ae02012-03-20 14:17:01 +00002089 if (IsGeometry(arg1) == MagickFalse)
2090 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002091 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002092 break;
2093 }
anthonyafa3dfc2012-03-03 11:31:30 +00002094 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002095 {
2096 KernelInfo
2097 *kernel;
2098
anthonyfd706f92012-01-19 04:22:02 +00002099 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002100 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002101 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002102 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002103 kernel=DestroyKernelInfo(kernel);
2104 break;
2105 }
anthonyafa3dfc2012-03-03 11:31:30 +00002106 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002107 {
anthony5330ae02012-03-20 14:17:01 +00002108 /* Reduce the number of colors in the image.
2109 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002110 */
anthony92c93bd2012-03-19 14:02:47 +00002111 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2112 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002113 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002114 if ((_image->storage_class == DirectClass) ||
2115 _image->colors > _quantize_info->number_colors)
2116 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002117 else
anthony92c93bd2012-03-19 14:02:47 +00002118 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002119 break;
2120 }
anthonyafa3dfc2012-03-03 11:31:30 +00002121 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002122 {
anthony5330ae02012-03-20 14:17:01 +00002123 /* WARNING: this is both a image_info setting (already done)
2124 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002125
2126 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002127 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002128
anthonyd2cdc862011-10-07 14:07:17 +00002129 Note that +colorspace sets "undefined" or no effect on
2130 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002131 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002132 */
anthony92c93bd2012-03-19 14:02:47 +00002133 (void) TransformImageColorspace(_image,
2134 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2135 _exception);
anthony805a2d42011-09-25 08:25:12 +00002136 break;
2137 }
anthonyafa3dfc2012-03-03 11:31:30 +00002138 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002139 {
anthonydcf3a912012-03-22 14:33:17 +00002140 /* DEPRECIATED: The -/+level provides far more controlled form */
anthony92c93bd2012-03-19 14:02:47 +00002141 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002142 break;
2143 }
anthonyafa3dfc2012-03-03 11:31:30 +00002144 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002145 {
2146 double
2147 black_point,
2148 white_point;
2149
2150 MagickStatusType
2151 flags;
2152
anthonyebb73a22012-03-22 14:25:52 +00002153 if (IsGeometry(arg1) == MagickFalse)
2154 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002155 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002156 black_point=geometry_info.rho;
2157 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2158 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002159 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002160 black_point*=(double) _image->columns*_image->rows/100.0;
2161 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002162 }
anthony92c93bd2012-03-19 14:02:47 +00002163 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002164 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002165 (void) ContrastStretchImage(_image,black_point,white_point,
2166 _exception);
anthony805a2d42011-09-25 08:25:12 +00002167 break;
2168 }
anthonyafa3dfc2012-03-03 11:31:30 +00002169 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002170 {
2171 KernelInfo
2172 *kernel_info;
2173
anthonyfd706f92012-01-19 04:22:02 +00002174 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002175 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002176 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002177 kernel_info->bias=_image->bias;
2178 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002179 kernel_info=DestroyKernelInfo(kernel_info);
2180 break;
2181 }
anthonyafa3dfc2012-03-03 11:31:30 +00002182 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002183 {
anthony31f1bf72012-01-30 12:37:22 +00002184 /* WARNING: This can generate multiple images! */
anthonyebb73a22012-03-22 14:25:52 +00002185 if (IsGeometry(arg1) == MagickFalse)
2186 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002187 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002188 break;
2189 }
anthonyafa3dfc2012-03-03 11:31:30 +00002190 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002191 {
anthonyebb73a22012-03-22 14:25:52 +00002192 if (IsGeometry(arg1) == MagickFalse)
2193 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002194 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2195 _exception);
anthony805a2d42011-09-25 08:25:12 +00002196 break;
2197 }
anthonyebb73a22012-03-22 14:25:52 +00002198 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002199 }
2200 case 'd':
2201 {
anthonyafa3dfc2012-03-03 11:31:30 +00002202 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002203 {
2204 StringInfo
2205 *passkey;
2206
anthony92c93bd2012-03-19 14:02:47 +00002207 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002208 if (passkey == (StringInfo *) NULL)
2209 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2210
2211 (void) PasskeyDecipherImage(_image,passkey,_exception);
2212 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002213 break;
2214 }
anthonyafa3dfc2012-03-03 11:31:30 +00002215 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002216 {
anthony92c93bd2012-03-19 14:02:47 +00002217 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002218 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002219
anthonydcf510d2011-10-30 13:51:40 +00002220 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2221 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002222
anthonyfd706f92012-01-19 04:22:02 +00002223 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002224 */
anthony92c93bd2012-03-19 14:02:47 +00002225 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002226 break;
2227 }
anthonyafa3dfc2012-03-03 11:31:30 +00002228 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002229 {
2230 double
2231 threshold;
2232
anthonyebb73a22012-03-22 14:25:52 +00002233 if (IfNormalOp) {
2234 if (IsGeometry(arg1) == MagickFalse)
2235 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002236 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002237 }
anthonyafa3dfc2012-03-03 11:31:30 +00002238 else
2239 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002240 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002241 break;
2242 }
anthonyafa3dfc2012-03-03 11:31:30 +00002243 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002244 {
anthony92c93bd2012-03-19 14:02:47 +00002245 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002246 break;
2247 }
anthonyafa3dfc2012-03-03 11:31:30 +00002248 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002249 {
2250 char
2251 *args,
2252 token[MaxTextExtent];
2253
2254 const char
2255 *p;
2256
anthony805a2d42011-09-25 08:25:12 +00002257 double
2258 *arguments;
2259
2260 register ssize_t
2261 x;
2262
2263 size_t
2264 number_arguments;
2265
anthony2a0ec8c2012-03-24 04:35:56 +00002266 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2267 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002268 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2269 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002270 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002271 {
anthony80c37752012-01-16 01:03:11 +00002272 double
2273 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002274 /* Special Case - Argument is actually a resize geometry!
2275 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002276 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002277 Roll into a resize special operator */
anthonyebb73a22012-03-22 14:25:52 +00002278 if (IsGeometry(arg2) == MagickFalse)
2279 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2280 option,arg2);
2281 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002282 resize_args[0]=(double) geometry.width;
2283 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002284 new_image=DistortImage(_image,(DistortImageMethod) parse,
2285 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002286 break;
2287 }
anthonyfd706f92012-01-19 04:22:02 +00002288 /* handle percent arguments */
anthonyebb73a22012-03-22 14:25:52 +00002289 args=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00002290 if (args == (char *) NULL)
2291 break;
anthonyfd706f92012-01-19 04:22:02 +00002292 /* convert arguments into an array of doubles
2293 FUTURE: make this a separate function.
2294 Also make use of new 'sentinal' feature to avoid need for
2295 tokenization.
2296 */
anthony805a2d42011-09-25 08:25:12 +00002297 p=(char *) args;
2298 for (x=0; *p != '\0'; x++)
2299 {
2300 GetMagickToken(p,&p,token);
2301 if (*token == ',')
2302 GetMagickToken(p,&p,token);
2303 }
2304 number_arguments=(size_t) x;
2305 arguments=(double *) AcquireQuantumMemory(number_arguments,
2306 sizeof(*arguments));
2307 if (arguments == (double *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002308 CLIWandExceptionBreak(ResourceLimitFatalError,
2309 "MemoryAllocationFailed",option);
anthony805a2d42011-09-25 08:25:12 +00002310 (void) ResetMagickMemory(arguments,0,number_arguments*
anthonyebb73a22012-03-22 14:25:52 +00002311 sizeof(*arguments));
anthony805a2d42011-09-25 08:25:12 +00002312 p=(char *) args;
2313 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2314 {
2315 GetMagickToken(p,&p,token);
2316 if (*token == ',')
2317 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002318 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002319 }
2320 args=DestroyString(args);
anthony2a0ec8c2012-03-24 04:35:56 +00002321 new_image=DistortImage(_image,(DistortImageMethod) parse,
2322 number_arguments,arguments,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002323 arguments=(double *) RelinquishMagickMemory(arguments);
2324 break;
2325 }
anthonyafa3dfc2012-03-03 11:31:30 +00002326 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002327 {
anthony92c93bd2012-03-19 14:02:47 +00002328 (void) CloneString(&_draw_info->primitive,arg1);
2329 (void) DrawImage(_image,_draw_info,_exception);
2330 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002331 break;
2332 }
anthonyebb73a22012-03-22 14:25:52 +00002333 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002334 }
2335 case 'e':
2336 {
anthonyafa3dfc2012-03-03 11:31:30 +00002337 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002338 {
anthony2a0ec8c2012-03-24 04:35:56 +00002339 if (IsGeometry(arg1) == MagickFalse)
2340 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002341 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002342 if ((flags & SigmaValue) == 0)
2343 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002344 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2345 _exception);
anthony805a2d42011-09-25 08:25:12 +00002346 break;
2347 }
anthonyafa3dfc2012-03-03 11:31:30 +00002348 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002349 {
anthony2a0ec8c2012-03-24 04:35:56 +00002350 if (IsGeometry(arg1) == MagickFalse)
2351 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002352 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002353 if ((flags & SigmaValue) == 0)
2354 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002355 new_image=EmbossImage(_image,geometry_info.rho,
2356 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002357 break;
2358 }
anthonyafa3dfc2012-03-03 11:31:30 +00002359 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002360 {
2361 StringInfo
2362 *passkey;
2363
anthony92c93bd2012-03-19 14:02:47 +00002364 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002365 if (passkey != (StringInfo *) NULL)
2366 {
anthony92c93bd2012-03-19 14:02:47 +00002367 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002368 passkey=DestroyStringInfo(passkey);
2369 }
2370 break;
2371 }
anthonyafa3dfc2012-03-03 11:31:30 +00002372 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002373 {
anthony92c93bd2012-03-19 14:02:47 +00002374 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002375 break;
2376 }
anthonyafa3dfc2012-03-03 11:31:30 +00002377 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002378 {
anthony92c93bd2012-03-19 14:02:47 +00002379 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002380 break;
2381 }
anthonyafa3dfc2012-03-03 11:31:30 +00002382 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002383 {
2384 double
2385 constant;
2386
anthony2a0ec8c2012-03-24 04:35:56 +00002387 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2388 if ( parse < 0 )
2389 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2390 option,arg1);
2391 if (IsGeometry(arg2) == MagickFalse)
2392 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002393 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002394 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2395 _exception);
anthony805a2d42011-09-25 08:25:12 +00002396 break;
2397 }
anthonyafa3dfc2012-03-03 11:31:30 +00002398 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002399 {
anthony2a0ec8c2012-03-24 04:35:56 +00002400 if (IsGeometry(arg1) == MagickFalse)
2401 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002402 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002403 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002404 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002405 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002406 geometry.height=_image->rows;
2407 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002408 break;
2409 }
anthonyebb73a22012-03-22 14:25:52 +00002410 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002411 }
2412 case 'f':
2413 {
anthonyafa3dfc2012-03-03 11:31:30 +00002414 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002415 {
anthony31f1bf72012-01-30 12:37:22 +00002416 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002417 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002418 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002419 break;
2420 }
anthony92c93bd2012-03-19 14:02:47 +00002421 (void) SetImageArtifact(_image,"identify:features","true");
2422 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002423 break;
2424 }
anthonyafa3dfc2012-03-03 11:31:30 +00002425 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002426 {
anthony92c93bd2012-03-19 14:02:47 +00002427 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002428 break;
2429 }
anthonyafa3dfc2012-03-03 11:31:30 +00002430 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002431 {
anthony92c93bd2012-03-19 14:02:47 +00002432 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002433 break;
2434 }
anthonyafa3dfc2012-03-03 11:31:30 +00002435 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002436 {
2437 PixelInfo
2438 target;
2439
anthony2a0ec8c2012-03-24 04:35:56 +00002440 if (IsGeometry(arg1) == MagickFalse)
2441 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002442 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2443 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2444 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2445 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002446 break;
2447 }
anthonyafa3dfc2012-03-03 11:31:30 +00002448 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002449 {
2450 FrameInfo
2451 frame_info;
2452
anthony31f1bf72012-01-30 12:37:22 +00002453 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002454 compose;
2455
2456 const char*
2457 value;
2458
anthony92c93bd2012-03-19 14:02:47 +00002459 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002460 if (value != (const char *) NULL)
2461 compose=(CompositeOperator) ParseCommandOption(
2462 MagickComposeOptions,MagickFalse,value);
2463 else
anthony92c93bd2012-03-19 14:02:47 +00002464 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002465
anthony2a0ec8c2012-03-24 04:35:56 +00002466 if (IsGeometry(arg1) == MagickFalse)
2467 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002468 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002469 frame_info.width=geometry.width;
2470 frame_info.height=geometry.height;
2471 if ((flags & HeightValue) == 0)
2472 frame_info.height=geometry.width;
2473 frame_info.outer_bevel=geometry.x;
2474 frame_info.inner_bevel=geometry.y;
2475 frame_info.x=(ssize_t) frame_info.width;
2476 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002477 frame_info.width=_image->columns+2*frame_info.width;
2478 frame_info.height=_image->rows+2*frame_info.height;
2479 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002480 break;
2481 }
anthonyafa3dfc2012-03-03 11:31:30 +00002482 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002483 {
2484 char
2485 *arguments,
2486 token[MaxTextExtent];
2487
2488 const char
2489 *p;
2490
2491 double
2492 *parameters;
2493
anthony805a2d42011-09-25 08:25:12 +00002494 register ssize_t
2495 x;
2496
2497 size_t
2498 number_parameters;
2499
cristy947cb4c2011-10-20 18:41:46 +00002500 /*
2501 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002502 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002503 */
anthony2a0ec8c2012-03-24 04:35:56 +00002504 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2505 if ( parse < 0 )
2506 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2507 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002508 arguments=InterpretImageProperties(_image_info,_image,arg2,
2509 _exception);
anthony805a2d42011-09-25 08:25:12 +00002510 if (arguments == (char *) NULL)
anthony2a0ec8c2012-03-24 04:35:56 +00002511 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony805a2d42011-09-25 08:25:12 +00002512 p=(char *) arguments;
2513 for (x=0; *p != '\0'; x++)
2514 {
2515 GetMagickToken(p,&p,token);
2516 if (*token == ',')
2517 GetMagickToken(p,&p,token);
2518 }
2519 number_parameters=(size_t) x;
2520 parameters=(double *) AcquireQuantumMemory(number_parameters,
2521 sizeof(*parameters));
2522 if (parameters == (double *) NULL)
2523 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002524 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002525 (void) ResetMagickMemory(parameters,0,number_parameters*
2526 sizeof(*parameters));
2527 p=(char *) arguments;
anthony2a0ec8c2012-03-24 04:35:56 +00002528 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++) {
anthony805a2d42011-09-25 08:25:12 +00002529 GetMagickToken(p,&p,token);
2530 if (*token == ',')
2531 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002532 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002533 }
2534 arguments=DestroyString(arguments);
anthony2a0ec8c2012-03-24 04:35:56 +00002535 (void) FunctionImage(_image,(MagickFunction)parse,number_parameters,
2536 parameters,_exception);
anthony805a2d42011-09-25 08:25:12 +00002537 parameters=(double *) RelinquishMagickMemory(parameters);
2538 break;
2539 }
anthonyebb73a22012-03-22 14:25:52 +00002540 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002541 }
2542 case 'g':
2543 {
anthonyafa3dfc2012-03-03 11:31:30 +00002544 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002545 {
anthonyfe1aa782012-03-24 13:43:04 +00002546 if (IsGeometry(arg1) == MagickFalse)
2547 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafa3dfc2012-03-03 11:31:30 +00002548 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002549 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2550 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002551 else
anthony92c93bd2012-03-19 14:02:47 +00002552 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002553 break;
2554 }
anthonyafa3dfc2012-03-03 11:31:30 +00002555 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2556 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002557 {
anthonyfe1aa782012-03-24 13:43:04 +00002558 if (IsGeometry(arg1) == MagickFalse)
2559 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002560 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002561 if ((flags & SigmaValue) == 0)
2562 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002563 new_image=GaussianBlurImage(_image,geometry_info.rho,
2564 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002565 break;
2566 }
anthonyafa3dfc2012-03-03 11:31:30 +00002567 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002568 {
anthonyfd706f92012-01-19 04:22:02 +00002569 /*
anthony31f1bf72012-01-30 12:37:22 +00002570 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002571 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002572 FUTURE: Why if no 'offset' does this resize ALL images?
2573 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002574 */
anthonyafa3dfc2012-03-03 11:31:30 +00002575 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002576 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002577 if (_image->geometry != (char *) NULL)
2578 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002579 break;
2580 }
anthonyfe1aa782012-03-24 13:43:04 +00002581 if (IsGeometry(arg1) == MagickFalse)
2582 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002583 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002584 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002585 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002586 else
anthony92c93bd2012-03-19 14:02:47 +00002587 new_image=ResizeImage(_image,geometry.width,geometry.height,
2588 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00002589 break;
2590 }
anthonyebb73a22012-03-22 14:25:52 +00002591 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002592 }
2593 case 'h':
2594 {
anthonyafa3dfc2012-03-03 11:31:30 +00002595 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002596 {
anthony92c93bd2012-03-19 14:02:47 +00002597 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002598 break;
2599 }
anthonyebb73a22012-03-22 14:25:52 +00002600 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002601 }
2602 case 'i':
2603 {
anthonyafa3dfc2012-03-03 11:31:30 +00002604 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002605 {
anthony31f1bf72012-01-30 12:37:22 +00002606 const char
2607 *format,
anthony805a2d42011-09-25 08:25:12 +00002608 *text;
2609
anthony92c93bd2012-03-19 14:02:47 +00002610 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002611 if (format == (char *) NULL)
2612 {
anthony92c93bd2012-03-19 14:02:47 +00002613 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2614 _exception);
anthony805a2d42011-09-25 08:25:12 +00002615 break;
2616 }
anthony92c93bd2012-03-19 14:02:47 +00002617 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002618 if (text == (char *) NULL)
2619 break;
2620 (void) fputs(text,stdout);
2621 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002622 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002623 break;
2624 }
anthonyafa3dfc2012-03-03 11:31:30 +00002625 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002626 {
anthonyfe1aa782012-03-24 13:43:04 +00002627 if (IsGeometry(arg1) == MagickFalse)
2628 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002629 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002630 new_image=ImplodeImage(_image,geometry_info.rho,
2631 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002632 break;
2633 }
anthonyafa3dfc2012-03-03 11:31:30 +00002634 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002635 {
anthonyfe1aa782012-03-24 13:43:04 +00002636 /* FUTURE: New to IMv7
2637 Roll into a resize special operator */
2638 if (IsGeometry(arg1) == MagickFalse)
2639 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002640 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2641 new_image=InterpolativeResizeImage(_image,geometry.width,
2642 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002643 break;
2644 }
anthonyebb73a22012-03-22 14:25:52 +00002645 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002646 }
2647 case 'l':
2648 {
anthonyafa3dfc2012-03-03 11:31:30 +00002649 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002650 {
anthonyfe1aa782012-03-24 13:43:04 +00002651 if (IsGeometry(arg1) == MagickFalse)
2652 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002653 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002654 if ((flags & PercentValue) != 0)
2655 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002656 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002657 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002658 _exception);
anthony805a2d42011-09-25 08:25:12 +00002659 break;
2660 }
anthonyafa3dfc2012-03-03 11:31:30 +00002661 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002662 {
2663 MagickRealType
2664 black_point,
2665 gamma,
2666 white_point;
2667
2668 MagickStatusType
2669 flags;
2670
anthonyfe1aa782012-03-24 13:43:04 +00002671 if (IsGeometry(arg1) == MagickFalse)
2672 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002673 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002674 black_point=geometry_info.rho;
2675 white_point=(MagickRealType) QuantumRange;
2676 if ((flags & SigmaValue) != 0)
2677 white_point=geometry_info.sigma;
2678 gamma=1.0;
2679 if ((flags & XiValue) != 0)
2680 gamma=geometry_info.xi;
2681 if ((flags & PercentValue) != 0)
2682 {
2683 black_point*=(MagickRealType) (QuantumRange/100.0);
2684 white_point*=(MagickRealType) (QuantumRange/100.0);
2685 }
2686 if ((flags & SigmaValue) == 0)
2687 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002688 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002689 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002690 else
anthony92c93bd2012-03-19 14:02:47 +00002691 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002692 break;
2693 }
anthonyafa3dfc2012-03-03 11:31:30 +00002694 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002695 {
2696 char
2697 token[MaxTextExtent];
2698
2699 const char
2700 *p;
2701
2702 PixelInfo
2703 black_point,
2704 white_point;
2705
anthonyfd706f92012-01-19 04:22:02 +00002706 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002707 GetMagickToken(p,&p,token); /* get black point color */
2708 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002709 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002710 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002711 else
cristy269c9412011-10-13 23:41:15 +00002712 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002713 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002714 if (isalpha((int) token[0]) || (token[0] == '#'))
2715 GetMagickToken(p,&p,token);
2716 if (*token == '\0')
2717 white_point=black_point; /* set everything to that color */
2718 else
2719 {
2720 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2721 GetMagickToken(p,&p,token); /* Get white point color. */
2722 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002723 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002724 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002725 else
cristy269c9412011-10-13 23:41:15 +00002726 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002727 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002728 }
anthony92c93bd2012-03-19 14:02:47 +00002729 (void) LevelImageColors(_image,&black_point,&white_point,
2730 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002731 break;
2732 }
anthonyafa3dfc2012-03-03 11:31:30 +00002733 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002734 {
2735 double
2736 black_point,
2737 white_point;
2738
2739 MagickStatusType
2740 flags;
2741
anthonyfe1aa782012-03-24 13:43:04 +00002742 if (IsGeometry(arg1) == MagickFalse)
2743 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002744 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002745 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002746 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002747 if ((flags & SigmaValue) != 0)
2748 white_point=geometry_info.sigma;
2749 if ((flags & PercentValue) != 0)
2750 {
anthony92c93bd2012-03-19 14:02:47 +00002751 black_point*=(double) _image->columns*_image->rows/100.0;
2752 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002753 }
2754 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002755 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002756 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002757 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002758 break;
2759 }
anthonyafa3dfc2012-03-03 11:31:30 +00002760 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002761 {
anthonyfe1aa782012-03-24 13:43:04 +00002762 /* FUTURE: Roll into a resize special operator */
2763 if (IsGeometry(arg1) == MagickFalse)
2764 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002765 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002766 if ((flags & XValue) == 0)
2767 geometry.x=1;
2768 if ((flags & YValue) == 0)
2769 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002770 new_image=LiquidRescaleImage(_image,geometry.width,
2771 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002772 break;
2773 }
anthonyafa3dfc2012-03-03 11:31:30 +00002774 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002775 {
anthony92c93bd2012-03-19 14:02:47 +00002776 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002777 break;
2778 }
anthonyebb73a22012-03-22 14:25:52 +00002779 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002780 }
2781 case 'm':
2782 {
anthonyafa3dfc2012-03-03 11:31:30 +00002783 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002784 {
2785 Image
2786 *remap_image;
2787
anthony31f1bf72012-01-30 12:37:22 +00002788 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002789 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002790 if (remap_image == (Image *) NULL)
2791 break;
anthony92c93bd2012-03-19 14:02:47 +00002792 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002793 remap_image=DestroyImage(remap_image);
2794 break;
2795 }
anthonyafa3dfc2012-03-03 11:31:30 +00002796 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002797 {
2798 Image
2799 *mask;
2800
anthonyafa3dfc2012-03-03 11:31:30 +00002801 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002802 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002803 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002804 break;
2805 }
anthony5330ae02012-03-20 14:17:01 +00002806 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002807 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002808 if (mask == (Image *) NULL)
2809 break;
anthony92c93bd2012-03-19 14:02:47 +00002810 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002811 mask=DestroyImage(mask);
2812 break;
2813 }
anthonyafa3dfc2012-03-03 11:31:30 +00002814 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002815 {
anthony31f1bf72012-01-30 12:37:22 +00002816 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002817 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2818 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002819 break;
2820 }
anthonya3ef4ed2012-03-17 06:52:53 +00002821 if (LocaleCompare("median",option+1) == 0)
2822 {
2823 /* DEPRECIATED - use -statistic Median */
anthony7bc87992012-03-25 02:32:51 +00002824 if (IsGeometry(arg1) == MagickFalse)
2825 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya3ef4ed2012-03-17 06:52:53 +00002826 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2827 break;
2828 }
anthonyafa3dfc2012-03-03 11:31:30 +00002829 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002830 {
anthony7bc87992012-03-25 02:32:51 +00002831 if (IsGeometry(arg1) == MagickFalse)
2832 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002833 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002834 if ((flags & SigmaValue) == 0)
2835 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002836 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2837 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002838 break;
2839 }
anthonyafa3dfc2012-03-03 11:31:30 +00002840 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002841 {
anthony7bc87992012-03-25 02:32:51 +00002842 if (IsGeometry(arg1) == MagickFalse)
2843 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002844 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002845 break;
2846 }
anthonyafa3dfc2012-03-03 11:31:30 +00002847 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002848 {
anthony92c93bd2012-03-19 14:02:47 +00002849 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002850 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002851 break;
2852 }
anthonyafa3dfc2012-03-03 11:31:30 +00002853 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002854 {
anthony92c93bd2012-03-19 14:02:47 +00002855 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002856 break;
2857 }
anthonyafa3dfc2012-03-03 11:31:30 +00002858 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002859 {
2860 char
2861 token[MaxTextExtent];
2862
2863 const char
2864 *p;
2865
2866 KernelInfo
2867 *kernel;
2868
anthony805a2d42011-09-25 08:25:12 +00002869 ssize_t
2870 iterations;
2871
anthonyfd706f92012-01-19 04:22:02 +00002872 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002873 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002874 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2875 if ( parse < 0 )
2876 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2877 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002878 iterations=1L;
2879 GetMagickToken(p,&p,token);
2880 if ((*p == ':') || (*p == ','))
2881 GetMagickToken(p,&p,token);
2882 if ((*p != '\0'))
2883 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002884 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002885 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002886 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2887 option,arg2);
2888 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2889 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002890 kernel=DestroyKernelInfo(kernel);
2891 break;
2892 }
anthonyafa3dfc2012-03-03 11:31:30 +00002893 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002894 {
anthony7bc87992012-03-25 02:32:51 +00002895 if (IsGeometry(arg1) == MagickFalse)
2896 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002897 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002898 if ((flags & SigmaValue) == 0)
2899 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002900 new_image=MotionBlurImage(_image,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002901 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
anthony92c93bd2012-03-19 14:02:47 +00002902 _exception);
anthony805a2d42011-09-25 08:25:12 +00002903 break;
2904 }
anthonyebb73a22012-03-22 14:25:52 +00002905 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002906 }
2907 case 'n':
2908 {
anthonyafa3dfc2012-03-03 11:31:30 +00002909 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002910 {
anthony92c93bd2012-03-19 14:02:47 +00002911 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002912 break;
2913 }
anthonyafa3dfc2012-03-03 11:31:30 +00002914 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002915 {
anthonyafa3dfc2012-03-03 11:31:30 +00002916 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002917 {
anthony7bc87992012-03-25 02:32:51 +00002918 if (IsGeometry(arg1) == MagickFalse)
2919 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002920 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002921 if ((flags & SigmaValue) == 0)
2922 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002923 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2924 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002925 }
2926 else
2927 {
anthony31f1bf72012-01-30 12:37:22 +00002928 double
2929 attenuate;
2930
2931 const char*
2932 value;
2933
anthony7bc87992012-03-25 02:32:51 +00002934 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2935 if ( parse < 0 )
2936 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2937 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002938 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002939 if (value != (const char *) NULL)
2940 attenuate=StringToDouble(value,(char **) NULL);
2941 else
2942 attenuate=1.0;
2943
anthony7bc87992012-03-25 02:32:51 +00002944 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2945 _exception);
anthony805a2d42011-09-25 08:25:12 +00002946 }
2947 break;
2948 }
anthonyafa3dfc2012-03-03 11:31:30 +00002949 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002950 {
anthony92c93bd2012-03-19 14:02:47 +00002951 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002952 break;
2953 }
anthonyebb73a22012-03-22 14:25:52 +00002954 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002955 }
2956 case 'o':
2957 {
anthonyafa3dfc2012-03-03 11:31:30 +00002958 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002959 {
2960 PixelInfo
2961 target;
2962
anthony92c93bd2012-03-19 14:02:47 +00002963 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2964 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2965 _exception);
anthony805a2d42011-09-25 08:25:12 +00002966 break;
2967 }
anthonyafa3dfc2012-03-03 11:31:30 +00002968 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002969 {
anthony92c93bd2012-03-19 14:02:47 +00002970 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002971 break;
2972 }
anthonyebb73a22012-03-22 14:25:52 +00002973 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002974 }
2975 case 'p':
2976 {
anthonyafa3dfc2012-03-03 11:31:30 +00002977 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002978 {
anthonyfd706f92012-01-19 04:22:02 +00002979 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002980 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2981 _exception);
anthony805a2d42011-09-25 08:25:12 +00002982 break;
2983 }
anthonyafa3dfc2012-03-03 11:31:30 +00002984 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002985 {
cristye9e3d382011-12-14 01:50:13 +00002986 const char
2987 *caption;
2988
anthony805a2d42011-09-25 08:25:12 +00002989 double
2990 angle;
2991
anthony7bc87992012-03-25 02:32:51 +00002992 if (IfPlusOp) {
anthony31f1bf72012-01-30 12:37:22 +00002993 RandomInfo
2994 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002995
anthony31f1bf72012-01-30 12:37:22 +00002996 random_info=AcquireRandomInfo();
2997 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2998 random_info=DestroyRandomInfo(random_info);
2999 }
anthony7bc87992012-03-25 02:32:51 +00003000 else {
3001 if (IsGeometry(arg1) == MagickFalse)
3002 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option
3003 ,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003004 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003005 angle=geometry_info.rho;
3006 }
anthony92c93bd2012-03-19 14:02:47 +00003007 caption=GetImageProperty(_image,"caption",_exception);
3008 new_image=PolaroidImage(_image,_draw_info,caption,angle,
3009 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003010 break;
3011 }
anthonyafa3dfc2012-03-03 11:31:30 +00003012 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003013 {
anthony7bc87992012-03-25 02:32:51 +00003014 if (IsGeometry(arg1) == MagickFalse)
3015 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003016 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003017 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
3018 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00003019 break;
3020 }
anthonyafa3dfc2012-03-03 11:31:30 +00003021 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003022 {
anthony31f1bf72012-01-30 12:37:22 +00003023 /* FUTURE: should be a 'Genesis' option?
3024 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00003025 Why???
cristy947cb4c2011-10-20 18:41:46 +00003026 */
anthony7bc87992012-03-25 02:32:51 +00003027 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
3028 if ( parse < 0 )
3029 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
3030 option,arg1);
3031 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003032 break;
3033 }
anthonyafa3dfc2012-03-03 11:31:30 +00003034 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003035 {
3036 const char
3037 *name;
3038
3039 const StringInfo
3040 *profile;
3041
3042 Image
3043 *profile_image;
3044
3045 ImageInfo
3046 *profile_info;
3047
anthonyafa3dfc2012-03-03 11:31:30 +00003048 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003049 { /* Remove a profile from the _image. */
3050 (void) ProfileImage(_image,arg1,(const unsigned char *)
3051 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003052 break;
3053 }
anthony92c93bd2012-03-19 14:02:47 +00003054 /* Associate a profile with the _image. */
3055 profile_info=CloneImageInfo(_image_info);
3056 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003057 if (profile != (StringInfo *) NULL)
3058 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003059 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003060 profile_info=DestroyImageInfo(profile_info);
3061 if (profile_image == (Image *) NULL)
3062 {
3063 StringInfo
3064 *profile;
3065
anthony92c93bd2012-03-19 14:02:47 +00003066 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003067 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00003068 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00003069 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003070 if (profile != (StringInfo *) NULL)
3071 {
anthony92c93bd2012-03-19 14:02:47 +00003072 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003073 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003074 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003075 profile=DestroyStringInfo(profile);
3076 }
3077 profile_info=DestroyImageInfo(profile_info);
3078 break;
3079 }
3080 ResetImageProfileIterator(profile_image);
3081 name=GetNextImageProfile(profile_image);
3082 while (name != (const char *) NULL)
3083 {
3084 profile=GetImageProfile(profile_image,name);
3085 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003086 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3087 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003088 name=GetNextImageProfile(profile_image);
3089 }
3090 profile_image=DestroyImage(profile_image);
3091 break;
3092 }
anthonyebb73a22012-03-22 14:25:52 +00003093 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003094 }
anthony805a2d42011-09-25 08:25:12 +00003095 case 'r':
3096 {
anthonyafa3dfc2012-03-03 11:31:30 +00003097 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003098 {
anthonyfd706f92012-01-19 04:22:02 +00003099 flags=ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003100 new_image=RadialBlurImage(_image,geometry_info.rho,
3101 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003102 break;
3103 }
anthonyafa3dfc2012-03-03 11:31:30 +00003104 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003105 {
anthony92c93bd2012-03-19 14:02:47 +00003106 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003107 if ((flags & SigmaValue) == 0)
3108 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00003109 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003110 break;
3111 }
anthonyafa3dfc2012-03-03 11:31:30 +00003112 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003113 {
anthony92c93bd2012-03-19 14:02:47 +00003114 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003115 break;
3116 }
anthonyafa3dfc2012-03-03 11:31:30 +00003117 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003118 {
3119 Image
3120 *remap_image;
3121
anthony92c93bd2012-03-19 14:02:47 +00003122 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003123 if (remap_image == (Image *) NULL)
3124 break;
anthony92c93bd2012-03-19 14:02:47 +00003125 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003126 remap_image=DestroyImage(remap_image);
3127 break;
3128 }
anthonyafa3dfc2012-03-03 11:31:30 +00003129 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003130 {
anthonyafa3dfc2012-03-03 11:31:30 +00003131 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003132 (void) ResetImagePage(_image,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003133 else
anthony92c93bd2012-03-19 14:02:47 +00003134 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003135 break;
3136 }
anthonyafa3dfc2012-03-03 11:31:30 +00003137 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003138 {
anthony31f1bf72012-01-30 12:37:22 +00003139 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00003140 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003141 if ((flags & SigmaValue) == 0)
3142 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003143 new_image=ResampleImage(_image,geometry_info.rho,
3144 geometry_info.sigma,_image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003145 break;
3146 }
anthonyafa3dfc2012-03-03 11:31:30 +00003147 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003148 {
anthonyafbaed72011-10-26 12:05:04 +00003149 /* FUTURE: remove blur argument - no longer used */
anthony92c93bd2012-03-19 14:02:47 +00003150 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3151 new_image=ResizeImage(_image,geometry.width,geometry.height,
3152 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003153 break;
3154 }
anthonyafa3dfc2012-03-03 11:31:30 +00003155 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003156 {
anthony92c93bd2012-03-19 14:02:47 +00003157 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3158 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003159 break;
3160 }
anthonyafa3dfc2012-03-03 11:31:30 +00003161 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003162 {
anthonyfd706f92012-01-19 04:22:02 +00003163 if (strchr(arg1,'>') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003164 if (_image->columns <= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003165 break;
anthonyfd706f92012-01-19 04:22:02 +00003166 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003167 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003168 break;
anthonyafbaed72011-10-26 12:05:04 +00003169
anthonyfd706f92012-01-19 04:22:02 +00003170 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003171 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003172 break;
3173 }
anthonyebb73a22012-03-22 14:25:52 +00003174 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003175 }
3176 case 's':
3177 {
anthonyafa3dfc2012-03-03 11:31:30 +00003178 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003179 {
anthonyfe1aa782012-03-24 13:43:04 +00003180 /* FUTURE: Roll into a resize special operator */
anthony92c93bd2012-03-19 14:02:47 +00003181 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3182 new_image=SampleImage(_image,geometry.width,geometry.height,
3183 _exception);
anthony805a2d42011-09-25 08:25:12 +00003184 break;
3185 }
anthonyafa3dfc2012-03-03 11:31:30 +00003186 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003187 {
anthonyfe1aa782012-03-24 13:43:04 +00003188 /* FUTURE: Roll into a resize special operator */
anthony92c93bd2012-03-19 14:02:47 +00003189 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3190 new_image=ScaleImage(_image,geometry.width,geometry.height,
3191 _exception);
anthony805a2d42011-09-25 08:25:12 +00003192 break;
3193 }
anthonyafa3dfc2012-03-03 11:31:30 +00003194 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003195 {
anthonyfd706f92012-01-19 04:22:02 +00003196 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003197 if ((flags & PercentValue) != 0)
3198 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003199 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3200 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003201 break;
3202 }
anthonyafa3dfc2012-03-03 11:31:30 +00003203 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003204 {
anthony31f1bf72012-01-30 12:37:22 +00003205 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003206 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003207 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003208 break;
3209 }
anthonyafa3dfc2012-03-03 11:31:30 +00003210 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003211 {
3212 double
3213 threshold;
3214
anthonyfd706f92012-01-19 04:22:02 +00003215 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003216 new_image=SepiaToneImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003217 break;
3218 }
anthonyafa3dfc2012-03-03 11:31:30 +00003219 if (LocaleCompare("segment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003220 {
anthonyfd706f92012-01-19 04:22:02 +00003221 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003222 if ((flags & SigmaValue) == 0)
3223 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003224 (void) SegmentImage(_image,_image->colorspace,
3225 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3226 _exception);
anthony805a2d42011-09-25 08:25:12 +00003227 break;
3228 }
anthonyafa3dfc2012-03-03 11:31:30 +00003229 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003230 {
3231 char
3232 *value;
3233
anthonyafa3dfc2012-03-03 11:31:30 +00003234 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00003235 {
anthonyfd706f92012-01-19 04:22:02 +00003236 if (LocaleNCompare(arg1,"registry:",9) == 0)
3237 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003238 else
anthony31f1bf72012-01-30 12:37:22 +00003239 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003240 {
anthony92c93bd2012-03-19 14:02:47 +00003241 (void) DeleteImageOption(_image_info,arg1+7);
3242 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003243 }
3244 else
anthony92c93bd2012-03-19 14:02:47 +00003245 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003246 break;
3247 }
anthony92c93bd2012-03-19 14:02:47 +00003248 value=InterpretImageProperties(_image_info,_image,arg2,
3249 _exception);
anthony805a2d42011-09-25 08:25:12 +00003250 if (value == (char *) NULL)
3251 break;
anthonyfd706f92012-01-19 04:22:02 +00003252 if (LocaleNCompare(arg1,"registry:",9) == 0)
3253 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony92c93bd2012-03-19 14:02:47 +00003254 _exception);
anthony805a2d42011-09-25 08:25:12 +00003255 else
anthonyfd706f92012-01-19 04:22:02 +00003256 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003257 {
anthony92c93bd2012-03-19 14:02:47 +00003258 (void) SetImageOption(_image_info,arg1+7,value);
3259 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003260 }
3261 else
anthony92c93bd2012-03-19 14:02:47 +00003262 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003263 value=DestroyString(value);
3264 break;
3265 }
anthonyafa3dfc2012-03-03 11:31:30 +00003266 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003267 {
anthonyfd706f92012-01-19 04:22:02 +00003268 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003269 if ((flags & SigmaValue) == 0)
3270 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003271 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3272 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003273 break;
3274 }
anthonyafa3dfc2012-03-03 11:31:30 +00003275 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003276 {
anthonyfd706f92012-01-19 04:22:02 +00003277 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003278 if ((flags & SigmaValue) == 0)
3279 geometry_info.sigma=1.0;
3280 if ((flags & XiValue) == 0)
3281 geometry_info.xi=4.0;
3282 if ((flags & PsiValue) == 0)
3283 geometry_info.psi=4.0;
anthony92c93bd2012-03-19 14:02:47 +00003284 new_image=ShadowImage(_image,geometry_info.rho,
3285 geometry_info.sigma,_image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003286 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
anthony92c93bd2012-03-19 14:02:47 +00003287 _exception);
anthony805a2d42011-09-25 08:25:12 +00003288 break;
3289 }
anthonyafa3dfc2012-03-03 11:31:30 +00003290 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003291 {
anthonyfd706f92012-01-19 04:22:02 +00003292 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003293 if ((flags & SigmaValue) == 0)
3294 geometry_info.sigma=1.0;
3295 if ((flags & XiValue) == 0)
3296 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00003297 new_image=SharpenImage(_image,geometry_info.rho,
3298 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003299 break;
3300 }
anthonyafa3dfc2012-03-03 11:31:30 +00003301 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003302 {
anthony92c93bd2012-03-19 14:02:47 +00003303 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3304 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003305 break;
3306 }
anthonyafa3dfc2012-03-03 11:31:30 +00003307 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003308 {
anthonyfd706f92012-01-19 04:22:02 +00003309 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003310 if ((flags & SigmaValue) == 0)
3311 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003312 new_image=ShearImage(_image,geometry_info.rho,
3313 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003314 break;
3315 }
anthonyafa3dfc2012-03-03 11:31:30 +00003316 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003317 {
anthonyfd706f92012-01-19 04:22:02 +00003318 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003319 if ((flags & SigmaValue) == 0)
3320 geometry_info.sigma=(double) QuantumRange/2.0;
3321 if ((flags & PercentValue) != 0)
3322 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3323 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003324 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003325 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003326 _exception);
anthony805a2d42011-09-25 08:25:12 +00003327 break;
3328 }
anthonyafa3dfc2012-03-03 11:31:30 +00003329 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003330 {
anthonyfd706f92012-01-19 04:22:02 +00003331 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003332 if ((flags & SigmaValue) == 0)
3333 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003334 new_image=SketchImage(_image,geometry_info.rho,
3335 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003336 break;
3337 }
anthonyafa3dfc2012-03-03 11:31:30 +00003338 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003339 {
anthony92c93bd2012-03-19 14:02:47 +00003340 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3341 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003342 break;
3343 }
anthonyafa3dfc2012-03-03 11:31:30 +00003344 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003345 {
3346 SparseColorMethod
3347 method;
3348
3349 char
3350 *arguments;
3351
anthony805a2d42011-09-25 08:25:12 +00003352 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003353 MagickSparseColorOptions,MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003354 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003355 if (arguments == (char *) NULL)
3356 break;
anthony92c93bd2012-03-19 14:02:47 +00003357 new_image=SparseColorOption(_image,method,arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003358 arguments=DestroyString(arguments);
3359 break;
3360 }
anthonyafa3dfc2012-03-03 11:31:30 +00003361 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003362 {
anthony92c93bd2012-03-19 14:02:47 +00003363 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3364 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003365 break;
3366 }
anthonyafa3dfc2012-03-03 11:31:30 +00003367 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003368 {
anthonyfd706f92012-01-19 04:22:02 +00003369 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003370 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3371 _exception);
anthony805a2d42011-09-25 08:25:12 +00003372 break;
3373 }
anthonyafa3dfc2012-03-03 11:31:30 +00003374 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003375 {
anthony7bc87992012-03-25 02:32:51 +00003376 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3377 if ( parse < 0 )
3378 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
3379 option,arg1);
3380 if (IsGeometry(arg2) == MagickFalse)
3381 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00003382 (void) ParseGeometry(arg2,&geometry_info);
anthony7bc87992012-03-25 02:32:51 +00003383 new_image=StatisticImage(_image,(StatisticType)parse,
3384 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3385 _exception);
anthony805a2d42011-09-25 08:25:12 +00003386 break;
3387 }
anthonyafa3dfc2012-03-03 11:31:30 +00003388 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003389 {
anthony92c93bd2012-03-19 14:02:47 +00003390 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003391 break;
3392 }
anthonyafa3dfc2012-03-03 11:31:30 +00003393 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003394 {
anthonyfd706f92012-01-19 04:22:02 +00003395 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003396 new_image=SwirlImage(_image,geometry_info.rho,
3397 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003398 break;
3399 }
anthonyebb73a22012-03-22 14:25:52 +00003400 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003401 }
3402 case 't':
3403 {
anthonyafa3dfc2012-03-03 11:31:30 +00003404 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003405 {
3406 double
3407 threshold;
3408
anthonyafa3dfc2012-03-03 11:31:30 +00003409 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003410 threshold=(double) QuantumRange/2;
3411 else
anthonyfd706f92012-01-19 04:22:02 +00003412 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003413 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003414 break;
3415 }
anthonyafa3dfc2012-03-03 11:31:30 +00003416 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003417 {
anthony92c93bd2012-03-19 14:02:47 +00003418 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3419 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3420 _exception);
anthony805a2d42011-09-25 08:25:12 +00003421 break;
3422 }
anthonyafa3dfc2012-03-03 11:31:30 +00003423 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003424 {
anthony92c93bd2012-03-19 14:02:47 +00003425 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003426 break;
3427 }
anthonyafa3dfc2012-03-03 11:31:30 +00003428 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003429 {
anthonya3ef4ed2012-03-17 06:52:53 +00003430 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony92c93bd2012-03-19 14:02:47 +00003431 new_image=AffineTransformImage(_image,&_draw_info->affine,
3432 _exception);
anthony805a2d42011-09-25 08:25:12 +00003433 break;
3434 }
anthonyafa3dfc2012-03-03 11:31:30 +00003435 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003436 {
3437 PixelInfo
3438 target;
3439
anthony92c93bd2012-03-19 14:02:47 +00003440 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3441 (void) TransparentPaintImage(_image,&target,(Quantum)
3442 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003443 break;
3444 }
anthonyafa3dfc2012-03-03 11:31:30 +00003445 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003446 {
anthony92c93bd2012-03-19 14:02:47 +00003447 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003448 break;
3449 }
anthonyafa3dfc2012-03-03 11:31:30 +00003450 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003451 {
anthony92c93bd2012-03-19 14:02:47 +00003452 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003453 break;
3454 }
anthonyafa3dfc2012-03-03 11:31:30 +00003455 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003456 {
anthony92c93bd2012-03-19 14:02:47 +00003457 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003458 break;
3459 }
anthonyafa3dfc2012-03-03 11:31:30 +00003460 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003461 {
anthonyab3a50c2011-10-27 11:48:57 +00003462 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003463 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003464 break;
3465 }
anthonyebb73a22012-03-22 14:25:52 +00003466 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003467 }
3468 case 'u':
3469 {
anthonyafa3dfc2012-03-03 11:31:30 +00003470 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003471 {
anthony31f1bf72012-01-30 12:37:22 +00003472 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthony24aa8822012-03-11 00:56:06 +00003473 /* FUTURE: This option is not documented!!!!! */
anthonyafa3dfc2012-03-03 11:31:30 +00003474 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003475 {
anthony92c93bd2012-03-19 14:02:47 +00003476 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003477 break;
3478 }
anthony92c93bd2012-03-19 14:02:47 +00003479 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3480 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003481 break;
3482 }
anthonyafa3dfc2012-03-03 11:31:30 +00003483 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003484 {
anthony92c93bd2012-03-19 14:02:47 +00003485 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003486 break;
3487 }
anthonyafa3dfc2012-03-03 11:31:30 +00003488 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003489 {
anthonyfd706f92012-01-19 04:22:02 +00003490 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003491 if ((flags & SigmaValue) == 0)
3492 geometry_info.sigma=1.0;
3493 if ((flags & XiValue) == 0)
3494 geometry_info.xi=1.0;
3495 if ((flags & PsiValue) == 0)
3496 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003497 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3498 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003499 break;
3500 }
anthonyebb73a22012-03-22 14:25:52 +00003501 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003502 }
3503 case 'v':
3504 {
anthonyafa3dfc2012-03-03 11:31:30 +00003505 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003506 {
anthonyafa3dfc2012-03-03 11:31:30 +00003507 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003508 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003509 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003510 */
anthony92c93bd2012-03-19 14:02:47 +00003511 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003512 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003513 break;
3514 }
anthonyafa3dfc2012-03-03 11:31:30 +00003515 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003516 {
anthonyfd706f92012-01-19 04:22:02 +00003517 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003518 if ((flags & SigmaValue) == 0)
3519 geometry_info.sigma=1.0;
3520 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003521 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003522 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003523 geometry_info.psi=0.1*_image->rows;
3524 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3525 _image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3526 (ssize_t) ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003527 break;
3528 }
anthonyebb73a22012-03-22 14:25:52 +00003529 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003530 }
3531 case 'w':
3532 {
anthonyafa3dfc2012-03-03 11:31:30 +00003533 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003534 {
anthonyfd706f92012-01-19 04:22:02 +00003535 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003536 if ((flags & SigmaValue) == 0)
3537 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003538 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3539 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003540 break;
3541 }
anthonyafa3dfc2012-03-03 11:31:30 +00003542 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003543 {
anthony92c93bd2012-03-19 14:02:47 +00003544 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003545 break;
3546 }
anthonyebb73a22012-03-22 14:25:52 +00003547 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003548 }
3549 default:
anthonyebb73a22012-03-22 14:25:52 +00003550 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003551 }
3552 /*
3553 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003554 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003555 */
3556 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003557 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003558
anthony31f1bf72012-01-30 12:37:22 +00003559 return;
anthony92c93bd2012-03-19 14:02:47 +00003560#undef _image_info
3561#undef _draw_info
3562#undef _quantize_info
3563#undef _image
3564#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003565#undef IfNormalOp
3566#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003567#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003568#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003569}
anthonyfd706f92012-01-19 04:22:02 +00003570
anthony43f425d2012-02-26 12:58:58 +00003571WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003572 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003573{
3574 size_t
anthony43f425d2012-02-26 12:58:58 +00003575 n,
anthony31f1bf72012-01-30 12:37:22 +00003576 i;
3577
anthony43f425d2012-02-26 12:58:58 +00003578 assert(cli_wand != (MagickCLI *) NULL);
3579 assert(cli_wand->signature == WandSignature);
3580 assert(cli_wand->wand.signature == WandSignature);
3581 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3582 if (cli_wand->wand.debug != MagickFalse)
3583 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003584
anthonyafa3dfc2012-03-03 11:31:30 +00003585#if !USE_WAND_METHODS
3586 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003587 i=0;
anthony43f425d2012-02-26 12:58:58 +00003588 n=GetImageListLength(cli_wand->wand.images);
3589 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003590 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003591 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003592 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003593 if ( cli_wand->wand.images->next == (Image *) NULL )
3594 break;
3595 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003596 }
anthony43f425d2012-02-26 12:58:58 +00003597 assert( i == n );
3598 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003599#else
3600 MagickResetIterator(&cli_wand->wand);
3601 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3602 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3603 MagickResetIterator(&cli_wand->wand);
3604#endif
anthony31f1bf72012-01-30 12:37:22 +00003605 return;
anthony805a2d42011-09-25 08:25:12 +00003606}
3607
3608/*
3609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3610% %
3611% %
3612% %
anthony43f425d2012-02-26 12:58:58 +00003613+ 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 +00003614% %
3615% %
3616% %
3617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3618%
anthony43f425d2012-02-26 12:58:58 +00003619% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003620% entire image list as a whole. The result is often a complete replacment
3621% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003622%
3623% The format of the MogrifyImage method is:
3624%
anthony43f425d2012-02-26 12:58:58 +00003625% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003626% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003627%
3628% A description of each parameter follows:
3629%
anthony43f425d2012-02-26 12:58:58 +00003630% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003631%
anthony36a8c2c2012-02-10 00:08:44 +00003632% o option: The option string for the operation
3633%
anthony31f1bf72012-01-30 12:37:22 +00003634% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003635%
anthonyfe1aa782012-03-24 13:43:04 +00003636% NOTE: only "limit" uses two arguments.
anthony8b10b462012-02-08 12:32:44 +00003637%
3638% Example usage...
3639%
anthonyafa3dfc2012-03-03 11:31:30 +00003640% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3641% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003642%
anthony24aa8822012-03-11 00:56:06 +00003643% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003644%
anthony43f425d2012-02-26 12:58:58 +00003645% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003646% argc,argv
3647% i=index in argv
3648%
anthony2052d272012-02-28 12:48:29 +00003649% option_info = GetCommandOptionInfo(argv[i]);
3650% count=option_info->type;
3651% option_type=option_info->flags;
3652%
3653% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003654% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003655% count>=1 ? argv[i+1] : (char *)NULL,
3656% count>=2 ? argv[i+2] : (char *)NULL );
3657% i += count+1;
3658%
anthony805a2d42011-09-25 08:25:12 +00003659*/
anthony43f425d2012-02-26 12:58:58 +00003660WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003661 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003662{
anthony2a0ec8c2012-03-24 04:35:56 +00003663 ssize_t
3664 parse;
3665
anthony31f1bf72012-01-30 12:37:22 +00003666 Image
3667 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003668
anthony92c93bd2012-03-19 14:02:47 +00003669#define _image_info (cli_wand->wand.image_info)
3670#define _images (cli_wand->wand.images)
3671#define _exception (cli_wand->wand.exception)
3672#define _draw_info (cli_wand->draw_info)
3673#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003674#define IfNormalOp (*option=='-')
3675#define IfPlusOp (*option!='-')
3676#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003677
anthony43f425d2012-02-26 12:58:58 +00003678 assert(cli_wand != (MagickCLI *) NULL);
3679 assert(cli_wand->signature == WandSignature);
3680 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003681 assert(_images != (Image *) NULL); /* _images must be present */
anthony43f425d2012-02-26 12:58:58 +00003682 if (cli_wand->wand.debug != MagickFalse)
3683 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003684
anthony92c93bd2012-03-19 14:02:47 +00003685 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003686
3687 new_images=NewImageList();
3688
anthonyafa3dfc2012-03-03 11:31:30 +00003689 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003690 {
3691 case 'a':
3692 {
anthonyafa3dfc2012-03-03 11:31:30 +00003693 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003694 {
anthony92c93bd2012-03-19 14:02:47 +00003695 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003696 break;
3697 }
anthonyafa3dfc2012-03-03 11:31:30 +00003698 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003699 {
anthony31f1bf72012-01-30 12:37:22 +00003700 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003701 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003702 break;
3703 }
anthonyebb73a22012-03-22 14:25:52 +00003704 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003705 }
3706 case 'c':
3707 {
cristy5f257b22012-03-07 00:27:29 +00003708 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003709 {
anthony92c93bd2012-03-19 14:02:47 +00003710 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003711 break;
3712 }
anthonyafa3dfc2012-03-03 11:31:30 +00003713 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003714 {
anthony805a2d42011-09-25 08:25:12 +00003715 Image
anthony31f1bf72012-01-30 12:37:22 +00003716 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003717
anthonyafa3dfc2012-03-03 11:31:30 +00003718 /* FUTURE - make this a compose option, and thus can be used
3719 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003720 _images.
cristy87c02f42012-02-24 00:19:10 +00003721 */
anthony92c93bd2012-03-19 14:02:47 +00003722 new_images=RemoveFirstImageFromList(&_images);
3723 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003724 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003725 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003726 break;
anthony92c93bd2012-03-19 14:02:47 +00003727 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003728 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003729 break;
3730 }
anthonyafa3dfc2012-03-03 11:31:30 +00003731 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003732 {
anthony92c93bd2012-03-19 14:02:47 +00003733 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003734 break;
3735 }
anthonyafa3dfc2012-03-03 11:31:30 +00003736 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003737 {
anthony43f425d2012-02-26 12:58:58 +00003738 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003739 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003740 break;
3741 }
anthonyafa3dfc2012-03-03 11:31:30 +00003742 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003743 {
3744 Image
3745 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003746 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003747
3748 RectangleInfo
3749 geometry;
3750
anthony31f1bf72012-01-30 12:37:22 +00003751 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003752 compose;
3753
3754 const char*
3755 value;
3756
anthony92c93bd2012-03-19 14:02:47 +00003757 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003758 if (value != (const char *) NULL)
3759 compose=(CompositeOperator) ParseCommandOption(
3760 MagickComposeOptions,MagickFalse,value);
3761 else
anthony31f1bf72012-01-30 12:37:22 +00003762 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003763
anthony92c93bd2012-03-19 14:02:47 +00003764 new_images=RemoveFirstImageFromList(&_images);
3765 source_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003766 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003767 if (source_image == (Image *) NULL)
3768 break;
anthonye8f56492012-02-12 12:39:02 +00003769
anthony31f1bf72012-01-30 12:37:22 +00003770 /* FUTURE - this should not be here! - should be part of -geometry */
3771 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003772 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003773
anthony31f1bf72012-01-30 12:37:22 +00003774 SetGeometry(source_image,&geometry);
3775 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3776 GravityAdjustGeometry(new_images->columns,new_images->rows,
3777 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003778
anthony92c93bd2012-03-19 14:02:47 +00003779 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003780 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003781 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003782 if ((compose == DisplaceCompositeOp) ||
3783 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003784 { /* Merge Y displacement into X displace/distort map. */
3785 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony92c93bd2012-03-19 14:02:47 +00003786 mask_image,0,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003787 mask_image=DestroyImage(mask_image);
3788 }
3789 else
3790 {
3791 /*
3792 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003793 */
anthony92c93bd2012-03-19 14:02:47 +00003794 (void) NegateImage(mask_image,MagickFalse,_exception);
3795 (void) SetImageMask(new_images,mask_image,_exception);
cristy1539afd2012-01-30 01:32:59 +00003796 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003797 }
3798 }
anthony31f1bf72012-01-30 12:37:22 +00003799 (void) CompositeImage(new_images,compose,source_image,geometry.x,
anthony92c93bd2012-03-19 14:02:47 +00003800 geometry.y,_exception);
3801 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003802 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003803 break;
3804 }
anthonyebb73a22012-03-22 14:25:52 +00003805 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003806 }
3807 case 'd':
3808 {
anthonyafa3dfc2012-03-03 11:31:30 +00003809 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003810 {
anthony31f1bf72012-01-30 12:37:22 +00003811 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003812 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003813 break;
3814 }
anthonyafa3dfc2012-03-03 11:31:30 +00003815 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003816 {
anthonyafa3dfc2012-03-03 11:31:30 +00003817 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003818 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003819 else
anthony92c93bd2012-03-19 14:02:47 +00003820 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003821 break;
3822 }
anthonyafa3dfc2012-03-03 11:31:30 +00003823 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003824 {
anthonyafa3dfc2012-03-03 11:31:30 +00003825 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003826 {
3827 const char
3828 *p;
3829
3830 size_t
3831 number_duplicates;
3832
anthonyebb73a22012-03-22 14:25:52 +00003833 if (IsGeometry(arg1) == MagickFalse)
3834 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3835 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003836 number_duplicates=(size_t) StringToLong(arg1);
3837 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003838 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003839 new_images=DuplicateImages(_images,number_duplicates,"-1",
3840 _exception);
anthony805a2d42011-09-25 08:25:12 +00003841 else
anthony92c93bd2012-03-19 14:02:47 +00003842 new_images=DuplicateImages(_images,number_duplicates,p,
3843 _exception);
anthony805a2d42011-09-25 08:25:12 +00003844 }
anthonyafa3dfc2012-03-03 11:31:30 +00003845 else
anthony92c93bd2012-03-19 14:02:47 +00003846 new_images=DuplicateImages(_images,1,"-1",_exception);
3847 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003848 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003849 break;
3850 }
anthonyebb73a22012-03-22 14:25:52 +00003851 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003852 }
3853 case 'e':
3854 {
anthonyafa3dfc2012-03-03 11:31:30 +00003855 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003856 {
anthony2a0ec8c2012-03-24 04:35:56 +00003857 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3858 if ( parse < 0 )
3859 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3860 option,arg1);
3861 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3862 _exception);
anthony805a2d42011-09-25 08:25:12 +00003863 break;
3864 }
anthonyebb73a22012-03-22 14:25:52 +00003865 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003866 }
3867 case 'f':
3868 {
anthonyafa3dfc2012-03-03 11:31:30 +00003869 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003870 {
anthony92c93bd2012-03-19 14:02:47 +00003871 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003872 break;
3873 }
anthonyafa3dfc2012-03-03 11:31:30 +00003874 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003875 {
anthony319dac62012-03-06 04:12:44 +00003876 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003877 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003878 break;
3879 }
anthonyafa3dfc2012-03-03 11:31:30 +00003880 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003881 {
anthony92c93bd2012-03-19 14:02:47 +00003882 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003883 break;
3884 }
anthonyebb73a22012-03-22 14:25:52 +00003885 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003886 }
3887 case 'h':
3888 {
anthonyafa3dfc2012-03-03 11:31:30 +00003889 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003890 {
anthony31f1bf72012-01-30 12:37:22 +00003891 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003892 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003893 */
anthony805a2d42011-09-25 08:25:12 +00003894 Image
anthony31f1bf72012-01-30 12:37:22 +00003895 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003896
anthony92c93bd2012-03-19 14:02:47 +00003897 new_images=RemoveFirstImageFromList(&_images);
3898 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003899 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003900 break;
anthony92c93bd2012-03-19 14:02:47 +00003901 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003902 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003903 break;
3904 }
anthonyebb73a22012-03-22 14:25:52 +00003905 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003906 }
3907 case 'i':
3908 {
anthonyafa3dfc2012-03-03 11:31:30 +00003909 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003910 {
3911 Image
anthony805a2d42011-09-25 08:25:12 +00003912 *magnitude_image,
3913 *phase_image;
3914
anthony92c93bd2012-03-19 14:02:47 +00003915 magnitude_image=RemoveFirstImageFromList(&_images);
3916 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003917 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003918 if (phase_image == (Image *) NULL)
3919 break;
3920 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003921 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003922 magnitude_image=DestroyImage(magnitude_image);
3923 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003924 break;
3925 }
anthonyafa3dfc2012-03-03 11:31:30 +00003926 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003927 {
3928 Image
anthony31f1bf72012-01-30 12:37:22 +00003929 *insert_image,
3930 *index_image;
3931
3932 ssize_t
3933 index;
anthony805a2d42011-09-25 08:25:12 +00003934
anthonyfe1aa782012-03-24 13:43:04 +00003935 if (IfNormalOp && IsGeometry(arg1) == MagickFalse)
3936 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003937 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003938 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003939 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003940 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003941 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003942 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003943 PrependImageToList(&_images,insert_image);
3944 else if (index == (ssize_t) GetImageListLength(_images))
3945 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003946 else
anthony43f425d2012-02-26 12:58:58 +00003947 {
anthony92c93bd2012-03-19 14:02:47 +00003948 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003949 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00003950 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00003951 InsertImageInList(&index_image,insert_image);
3952 }
anthony92c93bd2012-03-19 14:02:47 +00003953 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003954 break;
3955 }
anthonyebb73a22012-03-22 14:25:52 +00003956 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003957 }
3958 case 'l':
3959 {
anthonyafa3dfc2012-03-03 11:31:30 +00003960 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003961 {
anthonyfe1aa782012-03-24 13:43:04 +00003962 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3963 if ( parse < 0 )
3964 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3965 option,arg1);
3966 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00003967 {
3968 case CoalesceLayer:
3969 {
anthony92c93bd2012-03-19 14:02:47 +00003970 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003971 break;
3972 }
3973 case CompareAnyLayer:
3974 case CompareClearLayer:
3975 case CompareOverlayLayer:
3976 default:
3977 {
anthonyfe1aa782012-03-24 13:43:04 +00003978 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
3979 _exception);
anthony805a2d42011-09-25 08:25:12 +00003980 break;
3981 }
3982 case MergeLayer:
3983 case FlattenLayer:
3984 case MosaicLayer:
3985 case TrimBoundsLayer:
3986 {
anthonyfe1aa782012-03-24 13:43:04 +00003987 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
3988 _exception);
anthony805a2d42011-09-25 08:25:12 +00003989 break;
3990 }
3991 case DisposeLayer:
3992 {
anthony92c93bd2012-03-19 14:02:47 +00003993 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003994 break;
3995 }
3996 case OptimizeImageLayer:
3997 {
anthony92c93bd2012-03-19 14:02:47 +00003998 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003999 break;
4000 }
4001 case OptimizePlusLayer:
4002 {
anthony92c93bd2012-03-19 14:02:47 +00004003 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004004 break;
4005 }
4006 case OptimizeTransLayer:
4007 {
anthony92c93bd2012-03-19 14:02:47 +00004008 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004009 break;
4010 }
4011 case RemoveDupsLayer:
4012 {
anthony92c93bd2012-03-19 14:02:47 +00004013 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004014 break;
4015 }
4016 case RemoveZeroLayer:
4017 {
anthony92c93bd2012-03-19 14:02:47 +00004018 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004019 break;
4020 }
4021 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004022 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004023 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004024 if (new_images == (Image *) NULL)
4025 break;
anthony92c93bd2012-03-19 14:02:47 +00004026 _images=DestroyImageList(_images);
4027 _images=OptimizeImageLayers(new_images,_exception);
4028 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004029 break;
4030 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004031 OptimizeImageTransparency(_images,_exception);
4032 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4033 _exception);
anthony805a2d42011-09-25 08:25:12 +00004034 break;
4035 }
4036 case CompositeLayer:
4037 {
anthony805a2d42011-09-25 08:25:12 +00004038 Image
4039 *source;
4040
4041 RectangleInfo
4042 geometry;
4043
anthony31f1bf72012-01-30 12:37:22 +00004044 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004045 compose;
4046
4047 const char*
4048 value;
4049
anthony92c93bd2012-03-19 14:02:47 +00004050 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004051 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004052 if (value != (const char *) NULL)
4053 compose=(CompositeOperator) ParseCommandOption(
4054 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004055
anthony31f1bf72012-01-30 12:37:22 +00004056 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004057 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004058 while (source != (Image *) NULL)
4059 {
4060 source=GetNextImageInList(source);
4061 if ((source != (Image *) NULL) &&
4062 (LocaleCompare(source->magick,"NULL") == 0))
4063 break;
4064 }
4065 if (source != (Image *) NULL)
4066 {
4067 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4068 (GetNextImageInList(source) == (Image *) NULL))
4069 source=(Image *) NULL;
4070 else
anthony31f1bf72012-01-30 12:37:22 +00004071 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004072 source=SplitImageList(source->previous);
4073 DeleteImageFromList(&source);
4074 }
4075 }
4076 if (source == (Image *) NULL)
4077 {
anthony92c93bd2012-03-19 14:02:47 +00004078 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004079 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004080 break;
4081 }
anthony31f1bf72012-01-30 12:37:22 +00004082 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004083 SetGeometry(_images,&geometry);
4084 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004085 geometry.width=source->page.width != 0 ?
4086 source->page.width : source->columns;
4087 geometry.height=source->page.height != 0 ?
4088 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004089 GravityAdjustGeometry(_images->page.width != 0 ?
4090 _images->page.width : _images->columns,
4091 _images->page.height != 0 ? _images->page.height :
4092 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004093
anthony31f1bf72012-01-30 12:37:22 +00004094 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004095 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4096 _exception);
anthony805a2d42011-09-25 08:25:12 +00004097 source=DestroyImageList(source);
4098 break;
4099 }
4100 }
anthony805a2d42011-09-25 08:25:12 +00004101 break;
4102 }
anthonyafa3dfc2012-03-03 11:31:30 +00004103 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00004104 {
4105 MagickSizeType
4106 limit;
4107
anthony72feaa62012-01-17 06:46:23 +00004108 limit=MagickResourceInfinity;
anthonyfe1aa782012-03-24 13:43:04 +00004109 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4110 if ( parse < 0 )
4111 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4112 option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004113 if (LocaleCompare("unlimited",arg2) != 0)
4114 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthonyfe1aa782012-03-24 13:43:04 +00004115 (void) SetMagickResourceLimit((ResourceType)parse,limit);
anthony72feaa62012-01-17 06:46:23 +00004116 break;
4117 }
anthonyebb73a22012-03-22 14:25:52 +00004118 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004119 }
4120 case 'm':
4121 {
anthonyafa3dfc2012-03-03 11:31:30 +00004122 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004123 {
anthony31f1bf72012-01-30 12:37:22 +00004124 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004125 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004126 break;
4127 }
anthonyafa3dfc2012-03-03 11:31:30 +00004128 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004129 {
4130 Image
4131 *morph_image;
4132
anthony7bc87992012-03-25 02:32:51 +00004133 if (IsGeometry(arg1) == MagickFalse)
4134 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004135 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4136 _exception);
anthony805a2d42011-09-25 08:25:12 +00004137 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004138 break;
anthony92c93bd2012-03-19 14:02:47 +00004139 _images=DestroyImageList(_images);
4140 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004141 break;
4142 }
anthonyafa3dfc2012-03-03 11:31:30 +00004143 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004144 {
anthony319dac62012-03-06 04:12:44 +00004145 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00004146 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004147 break;
4148 }
anthonyebb73a22012-03-22 14:25:52 +00004149 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004150 }
4151 case 'p':
4152 {
anthonyafa3dfc2012-03-03 11:31:30 +00004153 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004154 {
4155 char
4156 *string;
4157
anthony92c93bd2012-03-19 14:02:47 +00004158 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004159 if (string == (char *) NULL)
4160 break;
4161 (void) FormatLocaleFile(stdout,"%s",string);
4162 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004163 break;
anthony805a2d42011-09-25 08:25:12 +00004164 }
anthonyafa3dfc2012-03-03 11:31:30 +00004165 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004166 {
4167 char
4168 **arguments;
4169
4170 int
4171 j,
4172 number_arguments;
4173
anthony31f1bf72012-01-30 12:37:22 +00004174 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004175 if (arguments == (char **) NULL)
4176 break;
anthony31f1bf72012-01-30 12:37:22 +00004177 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004178 {
4179 char
4180 breaker,
4181 quote,
4182 *token;
4183
4184 const char
4185 *arguments;
4186
4187 int
4188 next,
4189 status;
4190
4191 size_t
4192 length;
4193
4194 TokenInfo
4195 *token_info;
4196
4197 /*
anthony24aa8822012-03-11 00:56:06 +00004198 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004199 */
anthony31f1bf72012-01-30 12:37:22 +00004200 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004201 token=(char *) NULL;
4202 if (~length >= (MaxTextExtent-1))
4203 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4204 sizeof(*token));
4205 if (token == (char *) NULL)
4206 break;
4207 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004208 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004209 token_info=AcquireTokenInfo();
4210 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4211 "\"",'\0',&breaker,&next,&quote);
4212 token_info=DestroyTokenInfo(token_info);
4213 if (status == 0)
4214 {
4215 const char
4216 *argv;
4217
4218 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004219 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4220 _exception);
anthony805a2d42011-09-25 08:25:12 +00004221 }
4222 token=DestroyString(token);
4223 break;
4224 }
4225 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004226 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4227 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004228 for (j=0; j < number_arguments; j++)
4229 arguments[j]=DestroyString(arguments[j]);
4230 arguments=(char **) RelinquishMagickMemory(arguments);
4231 break;
4232 }
anthonyebb73a22012-03-22 14:25:52 +00004233 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004234 }
4235 case 'r':
4236 {
anthonyafa3dfc2012-03-03 11:31:30 +00004237 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004238 {
anthony92c93bd2012-03-19 14:02:47 +00004239 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4240 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004241 break;
4242 }
anthonyafa3dfc2012-03-03 11:31:30 +00004243 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004244 {
anthony92c93bd2012-03-19 14:02:47 +00004245 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004246 break;
4247 }
anthonyebb73a22012-03-22 14:25:52 +00004248 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004249 }
4250 case 's':
4251 {
anthonyafa3dfc2012-03-03 11:31:30 +00004252 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004253 {
4254 Image
4255 *smush_image;
4256
4257 ssize_t
4258 offset;
4259
anthony31f1bf72012-01-30 12:37:22 +00004260 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004261 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004262 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004263 break;
anthony92c93bd2012-03-19 14:02:47 +00004264 _images=DestroyImageList(_images);
4265 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004266 break;
4267 }
anthonyafa3dfc2012-03-03 11:31:30 +00004268 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004269 {
4270 Image
4271 *p,
4272 *q,
4273 *swap;
4274
4275 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004276 index,
anthony805a2d42011-09-25 08:25:12 +00004277 swap_index;
4278
anthony31f1bf72012-01-30 12:37:22 +00004279 index=-1;
4280 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004281 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004282 {
4283 GeometryInfo
4284 geometry_info;
4285
4286 MagickStatusType
4287 flags;
4288
4289 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004290 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004291 index=(ssize_t) geometry_info.rho;
4292 if ((flags & SigmaValue) != 0)
4293 swap_index=(ssize_t) geometry_info.sigma;
4294 }
anthony92c93bd2012-03-19 14:02:47 +00004295 p=GetImageFromList(_images,index);
4296 q=GetImageFromList(_images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004297 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4298 {
anthony92c93bd2012-03-19 14:02:47 +00004299 (void) ThrowMagickException(_exception,GetMagickModule(),
4300 OptionError,"NoSuchImage","'%s'",_images->filename);
anthony805a2d42011-09-25 08:25:12 +00004301 break;
4302 }
4303 if (p == q)
4304 break;
anthony92c93bd2012-03-19 14:02:47 +00004305 swap=CloneImage(p,0,0,MagickTrue,_exception);
4306 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
anthony805a2d42011-09-25 08:25:12 +00004307 ReplaceImageInList(&q,swap);
anthony92c93bd2012-03-19 14:02:47 +00004308 _images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004309 break;
4310 }
anthonyebb73a22012-03-22 14:25:52 +00004311 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004312 }
4313 case 'w':
4314 {
anthonyafa3dfc2012-03-03 11:31:30 +00004315 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004316 {
4317 char
4318 key[MaxTextExtent];
4319
4320 Image
4321 *write_images;
4322
4323 ImageInfo
4324 *write_info;
4325
anthony31f1bf72012-01-30 12:37:22 +00004326 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004327 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004328 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004329 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004330 write_images=CloneImageList(_images,_exception);
4331 write_info=CloneImageInfo(_image_info);
4332 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004333 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004334 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004335 write_images=DestroyImageList(write_images);
4336 break;
4337 }
anthonyebb73a22012-03-22 14:25:52 +00004338 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004339 }
4340 default:
anthonyebb73a22012-03-22 14:25:52 +00004341 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004342 }
anthony31f1bf72012-01-30 12:37:22 +00004343 if (new_images == (Image *) NULL)
4344 return;
anthony805a2d42011-09-25 08:25:12 +00004345
anthony92c93bd2012-03-19 14:02:47 +00004346 if (_images != (Image *) NULL)
4347 _images=DestroyImageList(_images);
4348 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004349 return;
4350
anthony92c93bd2012-03-19 14:02:47 +00004351#undef _image_info
4352#undef _images
4353#undef _exception
4354#undef _draw_info
4355#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004356#undef IfNormalOp
4357#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004358#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004359}
anthony43f425d2012-02-26 12:58:58 +00004360
4361/*
4362%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4363% %
4364% %
4365% %
4366+ C L I S p e c i a l O p e r a t i o n s %
4367% %
4368% %
4369% %
4370%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4371%
4372% CLISpecialOption() Applies operations that may involve empty image lists
4373% and or stacks of image lists or image_info settings.
4374%
anthonyafa3dfc2012-03-03 11:31:30 +00004375% The classic operators of this type is -read, and image stack operators,
4376% which can be applied to empty image lists.
4377%
4378% Note: unlike other Operators, these may involve other special 'option'
4379% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004380%
4381% The format of the CLISpecialOption method is:
4382%
4383% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004384% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004385%
4386% A description of each parameter follows:
4387%
4388% o cli_wand: the main CLI Wand to use.
4389%
4390% o option: The special option (with any switch char) to process
4391%
anthony24aa8822012-03-11 00:56:06 +00004392% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004393%
anthony2052d272012-02-28 12:48:29 +00004394% Example Usage...
4395%
anthonyce8dcb32012-03-21 13:20:31 +00004396% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004397%
anthony24aa8822012-03-11 00:56:06 +00004398% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004399%
4400% cli_wand
4401% argc,argv
4402% i=index in argv
4403%
4404% option_info = GetCommandOptionInfo(argv[i]);
4405% count=option_info->type;
4406% option_type=option_info->flags;
4407%
4408% if ( (option_type & SpecialOptionFlag) != 0 )
4409% CLISpecialOperator(cli_wand,argv[i],
4410% count>=1 ? argv[i+1] : (char *)NULL);
4411% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004412%
4413*/
4414
anthony43f425d2012-02-26 12:58:58 +00004415WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004416 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004417{
anthony92c93bd2012-03-19 14:02:47 +00004418#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004419
4420 assert(cli_wand != (MagickCLI *) NULL);
4421 assert(cli_wand->signature == WandSignature);
4422 assert(cli_wand->wand.signature == WandSignature);
4423 if (cli_wand->wand.debug != MagickFalse)
4424 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4425
anthony24aa8822012-03-11 00:56:06 +00004426 if(cli_wand->wand.images != (Image *)NULL)
4427 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004428 _exception);
anthony24aa8822012-03-11 00:56:06 +00004429
anthonyce8dcb32012-03-21 13:20:31 +00004430 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
4431 /* image-setting stack linkage */
4432 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4433 *option == '-' ? "true" : (char *) NULL);
4434 return;
4435 }
4436 if (LocaleCompare("(",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004437 /* stack 'push' images */
4438 Stack
4439 *node;
4440
4441 size_t
4442 size;
4443
anthony43f425d2012-02-26 12:58:58 +00004444 size=0;
4445 node=cli_wand->image_list_stack;
4446 for ( ; node != (Stack *)NULL; node=node->next)
4447 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004448 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004449 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004450 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4451 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004452 CLIWandExceptionReturn(ResourceLimitFatalError,
4453 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004454 node->data = (void *)cli_wand->wand.images;
4455 cli_wand->wand.images = NewImageList();
4456 node->next = cli_wand->image_list_stack;
4457 cli_wand->image_list_stack = node;
4458
4459 /* handle respect-parenthesis */
anthonyce8dcb32012-03-21 13:20:31 +00004460 if ( IsMagickTrue(GetImageOption(cli_wand->wand.image_info,
4461 "respect-parenthesis")) != MagickFalse )
anthony4d4f2c72012-03-22 03:22:03 +00004462 option="{"; /* push image settings too */
anthony43f425d2012-02-26 12:58:58 +00004463 else
4464 return;
4465 }
anthonyce8dcb32012-03-21 13:20:31 +00004466 if (LocaleCompare("{",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004467 /* stack 'push' of image_info settings */
4468 Stack
4469 *node;
4470
4471 size_t
4472 size;
4473
4474 size=0;
4475 node=cli_wand->image_info_stack;
4476 for ( ; node != (Stack *)NULL; node=node->next)
4477 size++;
anthony92c93bd2012-03-19 14:02:47 +00004478 if ( size >= MAX_STACK_DEPTH )
anthony4d4f2c72012-03-22 03:22:03 +00004479 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004480 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004481 if (node == (Stack *) NULL)
4482 CLIWandExceptionReturn(ResourceLimitFatalError,
4483 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004484
4485 node->data = (void *)cli_wand->wand.image_info;
4486 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004487 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
anthony92c93bd2012-03-19 14:02:47 +00004488 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4489 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004490 cli_wand->wand.image_info = (ImageInfo *)node->data;
4491 node = (Stack *)RelinquishMagickMemory(node);
4492 return;
4493 }
anthony43f425d2012-02-26 12:58:58 +00004494
4495 node->next = cli_wand->image_info_stack;
4496 cli_wand->image_info_stack = node;
4497
4498 return;
4499 }
anthonyce8dcb32012-03-21 13:20:31 +00004500 if (LocaleCompare(")",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004501 /* pop images from stack */
4502 Stack
4503 *node;
4504
anthony43f425d2012-02-26 12:58:58 +00004505 node = (void *)cli_wand->image_list_stack;
4506 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004507 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004508 cli_wand->image_list_stack = node->next;
4509
4510 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4511 cli_wand->wand.images= (Image *)node->data;
4512 node = (Stack *)RelinquishMagickMemory(node);
4513
anthony4d4f2c72012-03-22 03:22:03 +00004514 /* handle respect-parenthesis - of the previous 'pushed' settings */
anthony43f425d2012-02-26 12:58:58 +00004515 node = cli_wand->image_info_stack;
4516 if ( node != (Stack *)NULL)
4517 {
anthonyce8dcb32012-03-21 13:20:31 +00004518 if (IsMagickTrue(GetImageOption((ImageInfo *)node->data,
4519 "respect-parenthesis")) != MagickFalse )
anthony4d4f2c72012-03-22 03:22:03 +00004520 option="}"; /* pop image settings too */
anthony43f425d2012-02-26 12:58:58 +00004521 else
4522 return;
4523 }
4524 else
4525 return;
4526 }
anthonyce8dcb32012-03-21 13:20:31 +00004527 if (LocaleCompare("}",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004528 /* pop image_info settings from stack */
4529 Stack
4530 *node;
4531
4532 node = (void *)cli_wand->image_info_stack;
4533 if ( node == (Stack *)NULL)
anthony4d4f2c72012-03-22 03:22:03 +00004534 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
anthony43f425d2012-02-26 12:58:58 +00004535 cli_wand->image_info_stack = node->next;
4536
4537 (void) DestroyImageInfo(cli_wand->wand.image_info);
4538 cli_wand->wand.image_info = (ImageInfo *)node->data;
4539 node = (Stack *)RelinquishMagickMemory(node);
4540
4541 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4542 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4543 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4544
4545 return;
4546 }
anthonyce8dcb32012-03-21 13:20:31 +00004547 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004548 Image
4549 *new_images;
4550
4551 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004552 arg1="-1";
4553 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004554 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004555 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004556 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004557 new_images = (Image *)cli_wand->image_list_stack->data;
4558 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004559 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4560 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004561 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004562 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004563 AppendImageToList(&cli_wand->wand.images,new_images);
4564 return;
4565 }
anthony319dac62012-03-06 04:12:44 +00004566 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthonyce8dcb32012-03-21 13:20:31 +00004567 ( LocaleCompare("--",option) == 0 ) ) {
anthonyafa3dfc2012-03-03 11:31:30 +00004568#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004569 Image *
4570 new_images;
4571
anthony43f425d2012-02-26 12:58:58 +00004572 if (cli_wand->wand.image_info->ping != MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004573 new_images=PingImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004574 else
anthony92c93bd2012-03-19 14:02:47 +00004575 new_images=ReadImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004576 AppendImageToList(&cli_wand->wand.images, new_images);
4577#else
4578 /* read images using MagickWand method - no ping */
4579 /* This is not working! - it locks up in a CPU loop! */
4580 MagickSetLastIterator(&cli_wand->wand);
anthony24aa8822012-03-11 00:56:06 +00004581 MagickReadImage(&cli_wand->wand,arg1);
anthony43f425d2012-02-26 12:58:58 +00004582 MagickSetFirstIterator(&cli_wand->wand);
4583#endif
4584 return;
4585 }
anthonyafa3dfc2012-03-03 11:31:30 +00004586 /* No-op options */
4587 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004588 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004589 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004590 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004591 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004592 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004593 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004594 return;
anthonyce8dcb32012-03-21 13:20:31 +00004595 if (LocaleCompare("list",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004596 /* FUTURE: This should really be built into the MagickCore
4597 It does not actually require any wand or images at all!
4598 */
4599 ssize_t
4600 list;
4601
anthony24aa8822012-03-11 00:56:06 +00004602 list=ParseCommandOption(MagickListOptions,MagickFalse, arg1);
anthonyfe1aa782012-03-24 13:43:04 +00004603 if ( list < 0 ) {
4604 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4605 return;
4606 }
anthony43f425d2012-02-26 12:58:58 +00004607 switch (list)
4608 {
4609 case MagickCoderOptions:
4610 {
anthony92c93bd2012-03-19 14:02:47 +00004611 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004612 break;
4613 }
4614 case MagickColorOptions:
4615 {
anthony92c93bd2012-03-19 14:02:47 +00004616 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004617 break;
4618 }
4619 case MagickConfigureOptions:
4620 {
anthony92c93bd2012-03-19 14:02:47 +00004621 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004622 break;
4623 }
4624 case MagickDelegateOptions:
4625 {
anthony92c93bd2012-03-19 14:02:47 +00004626 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004627 break;
4628 }
4629 case MagickFontOptions:
4630 {
anthony92c93bd2012-03-19 14:02:47 +00004631 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004632 break;
4633 }
4634 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004635 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004636 break;
4637 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004638 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004639 break;
4640 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004641 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004642 break;
4643 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004644 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004645 break;
4646 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004647 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004648 break;
4649 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004650 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004651 break;
4652 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004653 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004654 break;
4655 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004656 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004657 break;
4658 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004659 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004660 break;
4661 default:
4662 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004663 _exception);
anthony43f425d2012-02-26 12:58:58 +00004664 break;
4665 }
4666 return;
4667 }
4668
4669#if 0
4670 // adjust stack handling
4671 // Other 'special' options this should handle
4672 // "region" "list" "version"
4673 // It does not do "exit" however as due to its side-effect requirements
4674#endif
4675#if 0
4676 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004677#endif
anthonyebb73a22012-03-22 14:25:52 +00004678 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004679
anthony92c93bd2012-03-19 14:02:47 +00004680#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004681}