blob: 42a170191b4a83e9b4e97a2221dca3e754e02f5a [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 */
anthony92c93bd2012-03-19 14:02:47 +00001235 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1236 _image_info->orientation=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001237 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001238 break;
1239 }
anthonyebb73a22012-03-22 14:25:52 +00001240 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001241 }
1242 case 'p':
1243 {
anthonyafa3dfc2012-03-03 11:31:30 +00001244 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001245 {
anthony72feaa62012-01-17 06:46:23 +00001246 /* Only used for new images and image generators
1247 SyncImageSettings() used to set per-image attribute. ?????
1248 That last is WRONG!!!!
1249 */
anthony805a2d42011-09-25 08:25:12 +00001250 char
1251 *canonical_page,
1252 page[MaxTextExtent];
1253
1254 const char
1255 *image_option;
1256
1257 MagickStatusType
1258 flags;
1259
1260 RectangleInfo
1261 geometry;
1262
anthonydcf510d2011-10-30 13:51:40 +00001263 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001264 {
anthony92c93bd2012-03-19 14:02:47 +00001265 (void) DeleteImageOption(_image_info,option+1);
1266 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001267 break;
1268 }
1269 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001270 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001271 if (image_option != (const char *) NULL)
1272 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001273 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001274 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1275 canonical_page=DestroyString(canonical_page);
1276 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1277 (unsigned long) geometry.width,(unsigned long) geometry.height);
1278 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1279 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1280 (unsigned long) geometry.width,(unsigned long) geometry.height,
1281 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001282 (void) SetImageOption(_image_info,option+1,page);
1283 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001284 break;
1285 }
anthonyafa3dfc2012-03-03 11:31:30 +00001286 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001287 {
anthony92c93bd2012-03-19 14:02:47 +00001288 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001289 break;
1290 }
anthonyafa3dfc2012-03-03 11:31:30 +00001291 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001292 {
anthony92c93bd2012-03-19 14:02:47 +00001293 _image_info->pointsize=_draw_info->pointsize=
anthony72feaa62012-01-17 06:46:23 +00001294 StringToDouble(ArgOption("12"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001295 break;
1296 }
anthonyafa3dfc2012-03-03 11:31:30 +00001297 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001298 {
anthony72feaa62012-01-17 06:46:23 +00001299 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
anthony805a2d42011-09-25 08:25:12 +00001300 break;
1301 }
anthonydcf510d2011-10-30 13:51:40 +00001302 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001303 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001304 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001305 {
anthony92c93bd2012-03-19 14:02:47 +00001306 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001307 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001308 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001309 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001310 break;
1311 }
anthonydcf510d2011-10-30 13:51:40 +00001312 */
anthonyebb73a22012-03-22 14:25:52 +00001313 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001314 }
1315 case 'q':
1316 {
anthonyafa3dfc2012-03-03 11:31:30 +00001317 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001318 {
anthony92c93bd2012-03-19 14:02:47 +00001319 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1320 _image_info->quality=UNDEFINED_COMPRESSION_QUALITY;
anthony72feaa62012-01-17 06:46:23 +00001321 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001322 _image_info->quality=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00001323 break;
1324 }
anthonyafa3dfc2012-03-03 11:31:30 +00001325 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001326 {
anthony92c93bd2012-03-19 14:02:47 +00001327 /* Just a set direct in _quantize_info */
1328 _quantize_info->colorspace=UndefinedColorspace;
anthonyafbaed72011-10-26 12:05:04 +00001329 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001330 _quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001331 MagickColorspaceOptions,MagickFalse,arg1);
anthonyafbaed72011-10-26 12:05:04 +00001332 break;
1333 }
anthonyafa3dfc2012-03-03 11:31:30 +00001334 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001335 {
anthonydcf510d2011-10-30 13:51:40 +00001336 /* FUTURE: if two -quiet is performed you can not do +quiet! */
anthony805a2d42011-09-25 08:25:12 +00001337 static WarningHandler
1338 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001339
anthonyafbaed72011-10-26 12:05:04 +00001340 WarningHandler
1341 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001342
anthonyafbaed72011-10-26 12:05:04 +00001343 if ( tmp != (WarningHandler) NULL)
1344 warning_handler = tmp; /* remember the old handler */
1345 if (!IfSetOption) /* set the old handler */
1346 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001347 break;
1348 }
anthonyebb73a22012-03-22 14:25:52 +00001349 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001350 }
1351 case 'r':
1352 {
anthonyafa3dfc2012-03-03 11:31:30 +00001353 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001354 {
anthonydcf510d2011-10-30 13:51:40 +00001355 /* Image chromaticity X,Y NB: Y=X if Y not defined
1356 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001357 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001358 */
anthonyfe1aa782012-03-24 13:43:04 +00001359 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
1360 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001361 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001362 break;
1363 }
anthonyafa3dfc2012-03-03 11:31:30 +00001364 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001365 {
anthony92c93bd2012-03-19 14:02:47 +00001366 /* _draw_info only setting */
1367 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001368 break;
1369 }
anthonyebb73a22012-03-22 14:25:52 +00001370 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001371 }
1372 case 's':
1373 {
anthonyafa3dfc2012-03-03 11:31:30 +00001374 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001375 {
anthonyafbaed72011-10-26 12:05:04 +00001376 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony92c93bd2012-03-19 14:02:47 +00001377 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001378 break;
1379 }
anthonyafa3dfc2012-03-03 11:31:30 +00001380 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001381 {
anthony72feaa62012-01-17 06:46:23 +00001382 /* SyncImageSettings() used to set per-image attribute.
1383 What ??? Why ????
1384 */
anthony92c93bd2012-03-19 14:02:47 +00001385 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1386 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001387 break;
1388 }
anthonyafa3dfc2012-03-03 11:31:30 +00001389 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001390 {
anthonyafbaed72011-10-26 12:05:04 +00001391 SeedPseudoRandomGenerator(
anthony24aa8822012-03-11 00:56:06 +00001392 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001393 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001394 break;
1395 }
anthonyafa3dfc2012-03-03 11:31:30 +00001396 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001397 {
anthony92c93bd2012-03-19 14:02:47 +00001398 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001399 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001400 */
anthony92c93bd2012-03-19 14:02:47 +00001401 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001402 break;
1403 }
anthonyafa3dfc2012-03-03 11:31:30 +00001404 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001405 {
anthony92c93bd2012-03-19 14:02:47 +00001406 _draw_info->stretch=(StretchType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001407 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001408 break;
1409 }
anthonyafa3dfc2012-03-03 11:31:30 +00001410 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001411 {
anthonyafbaed72011-10-26 12:05:04 +00001412 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001413 UPDATE: ensure stroke color is not destroyed is a pattern
1414 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001415 */
anthony72feaa62012-01-17 06:46:23 +00001416 MagickBooleanType
1417 status;
anthonyafbaed72011-10-26 12:05:04 +00001418
1419 ExceptionInfo
1420 *sans;
1421
anthonyfd706f92012-01-19 04:22:02 +00001422 PixelInfo
1423 color;
1424
anthony2a0ec8c2012-03-24 04:35:56 +00001425 arg1 = ArgOption("none"); /* +fill turns it off! */
1426 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001427 if (_draw_info->stroke_pattern != (Image *) NULL)
1428 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001429
1430 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001431 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001432 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001433 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001434
anthonyafbaed72011-10-26 12:05:04 +00001435 if (status == MagickFalse)
anthony2a0ec8c2012-03-24 04:35:56 +00001436 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001437 else
anthony92c93bd2012-03-19 14:02:47 +00001438 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001439 break;
1440 }
anthonyafa3dfc2012-03-03 11:31:30 +00001441 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001442 {
anthony92c93bd2012-03-19 14:02:47 +00001443 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1444 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001445 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001446 break;
1447 }
anthonyafa3dfc2012-03-03 11:31:30 +00001448 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001449 {
anthony92c93bd2012-03-19 14:02:47 +00001450 _draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
anthony72feaa62012-01-17 06:46:23 +00001451 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001452 break;
1453 }
anthonyafa3dfc2012-03-03 11:31:30 +00001454 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001455 {
anthony92c93bd2012-03-19 14:02:47 +00001456 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001457 break;
1458 }
anthonyebb73a22012-03-22 14:25:52 +00001459 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001460 }
1461 case 't':
1462 {
anthonyafa3dfc2012-03-03 11:31:30 +00001463 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001464 {
anthony72feaa62012-01-17 06:46:23 +00001465 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001466 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001467 break;
1468 }
anthonyafa3dfc2012-03-03 11:31:30 +00001469 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001470 {
anthony92c93bd2012-03-19 14:02:47 +00001471 /* FUTURE: move _image_info string to option splay-tree */
1472 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001473 break;
1474 }
anthonyafa3dfc2012-03-03 11:31:30 +00001475 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001476 {
anthony92c93bd2012-03-19 14:02:47 +00001477 _draw_info->fill_pattern=IfSetOption
1478 ?GetImageCache(_image_info,arg1,_exception)
1479 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001480 break;
1481 }
anthonyafa3dfc2012-03-03 11:31:30 +00001482 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001483 {
anthony72feaa62012-01-17 06:46:23 +00001484 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony92c93bd2012-03-19 14:02:47 +00001485 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001486 break;
1487 }
anthonyafa3dfc2012-03-03 11:31:30 +00001488 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001489 {
anthony92c93bd2012-03-19 14:02:47 +00001490 /* FUTURE: both _image_info attribute & ImageOption in use!
1491 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001492 SyncImageSettings() used to set per-image attribute.
1493
anthonyafbaed72011-10-26 12:05:04 +00001494 Note that +transparent-color, means fall-back to image
1495 attribute so ImageOption is deleted, not set to a default.
1496 */
anthony92c93bd2012-03-19 14:02:47 +00001497 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001498 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001499 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001500 break;
1501 }
anthonyafa3dfc2012-03-03 11:31:30 +00001502 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001503 {
anthony92c93bd2012-03-19 14:02:47 +00001504 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1505 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001506 break;
1507 }
anthonyafa3dfc2012-03-03 11:31:30 +00001508 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001509 {
anthony72feaa62012-01-17 06:46:23 +00001510 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001511 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1512 _image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
anthony72feaa62012-01-17 06:46:23 +00001513 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001514 break;
1515 }
anthonyebb73a22012-03-22 14:25:52 +00001516 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001517 }
1518 case 'u':
1519 {
anthonyafa3dfc2012-03-03 11:31:30 +00001520 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001521 {
anthony92c93bd2012-03-19 14:02:47 +00001522 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001523 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001524 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001525 break;
1526 }
anthonyafa3dfc2012-03-03 11:31:30 +00001527 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001528 {
anthony72feaa62012-01-17 06:46:23 +00001529 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001530 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001531 FUTURE: this probably should be part of the density setting
1532 */
anthony92c93bd2012-03-19 14:02:47 +00001533 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1534 _image_info->units=(ResolutionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001535 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001536 break;
1537 }
anthonyebb73a22012-03-22 14:25:52 +00001538 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001539 }
1540 case 'v':
1541 {
anthonyafa3dfc2012-03-03 11:31:30 +00001542 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001543 {
anthony24aa8822012-03-11 00:56:06 +00001544 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001545 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001546 */
anthony92c93bd2012-03-19 14:02:47 +00001547 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1548 _image_info->verbose= ArgBoolean;
1549 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001550 break;
1551 }
anthonyafa3dfc2012-03-03 11:31:30 +00001552 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001553 {
anthony92c93bd2012-03-19 14:02:47 +00001554 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001555 Only used by coder FPX
1556 */
anthony92c93bd2012-03-19 14:02:47 +00001557 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001558 break;
1559 }
anthonyafa3dfc2012-03-03 11:31:30 +00001560 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001561 {
anthonyfd706f92012-01-19 04:22:02 +00001562 /* SyncImageSettings() used to set per-image attribute.
1563 This is VERY deep in the image caching structure.
1564 */
anthony92c93bd2012-03-19 14:02:47 +00001565 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001566 break;
1567 }
anthonyebb73a22012-03-22 14:25:52 +00001568 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001569 }
1570 case 'w':
1571 {
anthonyafa3dfc2012-03-03 11:31:30 +00001572 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001573 {
anthony72feaa62012-01-17 06:46:23 +00001574 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001575 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001576 */
anthony72feaa62012-01-17 06:46:23 +00001577 if (!IfSetOption)
1578 break;
anthony92c93bd2012-03-19 14:02:47 +00001579 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001580 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001581 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001582 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001583 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001584 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001585 if (_draw_info->weight <= 800)
1586 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001587 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001588 if (_draw_info->weight >= 100)
1589 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001590 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001591 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001592 break;
1593 }
anthonyafa3dfc2012-03-03 11:31:30 +00001594 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001595 {
anthony72feaa62012-01-17 06:46:23 +00001596 /* Used as a image chromaticity setting
1597 SyncImageSettings() used to set per-image attribute.
1598 */
anthony92c93bd2012-03-19 14:02:47 +00001599 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001600 break;
1601 }
anthonyebb73a22012-03-22 14:25:52 +00001602 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001603 }
1604 default:
anthonyebb73a22012-03-22 14:25:52 +00001605 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001606 }
anthony24aa8822012-03-11 00:56:06 +00001607
anthony92c93bd2012-03-19 14:02:47 +00001608#undef _image_info
1609#undef _exception
1610#undef _draw_info
1611#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001612#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001613#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001614#undef ArgBooleanNot
1615#undef ArgBooleanString
1616#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001617
anthony31f1bf72012-01-30 12:37:22 +00001618 return;
anthony805a2d42011-09-25 08:25:12 +00001619}
1620
1621/*
1622%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1623% %
1624% %
1625% %
anthony43f425d2012-02-26 12:58:58 +00001626+ 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 +00001627% %
1628% %
1629% %
1630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1631%
anthony31f1bf72012-01-30 12:37:22 +00001632% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001633% the images in the CLI wand, with the settings that was previously saved in
1634% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001635%
1636% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001637% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001638%
anthonyd1447672012-01-19 05:33:53 +00001639% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001640%
anthony43f425d2012-02-26 12:58:58 +00001641% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001642% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001643%
1644% A description of each parameter follows:
1645%
anthony43f425d2012-02-26 12:58:58 +00001646% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001647%
anthonyfd706f92012-01-19 04:22:02 +00001648% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001649%
anthonyfd706f92012-01-19 04:22:02 +00001650% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001651%
anthony31f1bf72012-01-30 12:37:22 +00001652% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001653%
anthony31f1bf72012-01-30 12:37:22 +00001654% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001655%
anthonyafa3dfc2012-03-03 11:31:30 +00001656% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1657% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1658% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001659%
anthony24aa8822012-03-11 00:56:06 +00001660% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001661%
anthony43f425d2012-02-26 12:58:58 +00001662% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001663% argc,argv
1664% i=index in argv
1665%
anthony2052d272012-02-28 12:48:29 +00001666% option_info = GetCommandOptionInfo(argv[i]);
1667% count=option_info->type;
1668% option_type=option_info->flags;
1669%
1670% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001671% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001672% count>=1 ? argv[i+1] : (char *)NULL,
1673% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001674% i += count+1;
1675%
anthony805a2d42011-09-25 08:25:12 +00001676*/
anthony31f1bf72012-01-30 12:37:22 +00001677
1678/*
1679 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001680 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001681
1682 The image in the list may be modified in three different ways...
1683 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1684 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1685 * one image replace by a list of images (-separate and -crop only!)
1686
anthonyafa3dfc2012-03-03 11:31:30 +00001687 In each case the result replaces the single original image in the list, as
1688 well as the pointer to the modified image (last image added if replaced by a
1689 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001690
1691 As the image pointed to may be replaced, the first image in the list may
1692 also change. GetFirstImageInList() should be used by caller if they wish
1693 return the Image pointer to the first image in list.
1694*/
anthony43f425d2012-02-26 12:58:58 +00001695static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001696 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001697{
1698 Image *
1699 new_image;
1700
anthony805a2d42011-09-25 08:25:12 +00001701 GeometryInfo
1702 geometry_info;
1703
1704 RectangleInfo
1705 geometry;
1706
1707 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001708 flags;
1709
anthony92c93bd2012-03-19 14:02:47 +00001710 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001711 parse;
anthony92c93bd2012-03-19 14:02:47 +00001712
1713#define _image_info (cli_wand->wand.image_info)
1714#define _image (cli_wand->wand.images)
1715#define _exception (cli_wand->wand.exception)
1716#define _draw_info (cli_wand->draw_info)
1717#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001718#define IfNormalOp (*option=='-')
1719#define IfPlusOp (*option!='-')
1720#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1721#define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001722
anthony43f425d2012-02-26 12:58:58 +00001723 assert(cli_wand != (MagickCLI *) NULL);
1724 assert(cli_wand->signature == WandSignature);
1725 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001726 assert(_image != (Image *) NULL); /* an image must be present */
anthony43f425d2012-02-26 12:58:58 +00001727 if (cli_wand->wand.debug != MagickFalse)
1728 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001729
anthony92c93bd2012-03-19 14:02:47 +00001730 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001731
anthony805a2d42011-09-25 08:25:12 +00001732 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001733
anthony5330ae02012-03-20 14:17:01 +00001734 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001735
anthonyfd706f92012-01-19 04:22:02 +00001736 /* FUTURE: We may need somthing a little more optimized than this!
1737 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1738 */
anthonyafa3dfc2012-03-03 11:31:30 +00001739 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001740 {
1741 case 'a':
1742 {
anthonyafa3dfc2012-03-03 11:31:30 +00001743 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001744 {
anthony92c93bd2012-03-19 14:02:47 +00001745 if (IsGeometry(arg1) == MagickFalse)
1746 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001747 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001748 if ((flags & SigmaValue) == 0)
1749 geometry_info.sigma=1.0;
1750 if ((flags & XiValue) == 0)
1751 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001752 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1753 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001754 break;
1755 }
anthonyafa3dfc2012-03-03 11:31:30 +00001756 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001757 {
anthonyfe1aa782012-03-24 13:43:04 +00001758 /* FUTURE: Roll into a resize special operator */
anthony92c93bd2012-03-19 14:02:47 +00001759 if (IsGeometry(arg1) == MagickFalse)
1760 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1761 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1762 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1763 _exception);
anthony805a2d42011-09-25 08:25:12 +00001764 break;
1765 }
anthonyafa3dfc2012-03-03 11:31:30 +00001766 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001767 {
anthony92c93bd2012-03-19 14:02:47 +00001768 if (IsGeometry(arg1) == MagickFalse)
1769 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001770 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001771 if ((flags & SigmaValue) == 0)
1772 geometry_info.sigma=1.0;
1773 if ((flags & XiValue) == 0)
1774 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001775 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1776 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001777 break;
1778 }
anthonyafa3dfc2012-03-03 11:31:30 +00001779 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001780 {
anthony2a0ec8c2012-03-24 04:35:56 +00001781 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1782 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001783 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1784 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001785 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1786 _exception);
anthony805a2d42011-09-25 08:25:12 +00001787 break;
1788 }
anthonyafa3dfc2012-03-03 11:31:30 +00001789 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001790 {
1791 char
1792 *text,
1793 geometry[MaxTextExtent];
1794
anthony92c93bd2012-03-19 14:02:47 +00001795 if (IsGeometry(arg1) == MagickFalse)
1796 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001797 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001798 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001799 if ((flags & SigmaValue) == 0)
1800 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001801 text=InterpretImageProperties(_image_info,_image,arg2,
1802 _exception);
anthony805a2d42011-09-25 08:25:12 +00001803 if (text == (char *) NULL)
1804 break;
anthony92c93bd2012-03-19 14:02:47 +00001805 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001806 text=DestroyString(text);
1807 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1808 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001809 (void) CloneString(&_draw_info->geometry,geometry);
1810 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001811 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001812 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001813 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001814 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001815 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001816 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001817 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001818 (void) AnnotateImage(_image,_draw_info,_exception);
1819 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001820 break;
1821 }
anthonyafa3dfc2012-03-03 11:31:30 +00001822 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001823 {
anthony92c93bd2012-03-19 14:02:47 +00001824 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001825 break;
1826 }
anthonyafa3dfc2012-03-03 11:31:30 +00001827 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001828 {
anthony92c93bd2012-03-19 14:02:47 +00001829 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001830 break;
1831 }
anthonyafa3dfc2012-03-03 11:31:30 +00001832 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001833 {
anthony5330ae02012-03-20 14:17:01 +00001834 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001835 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001836 {
1837 case TopRightOrientation:
1838 {
anthony92c93bd2012-03-19 14:02:47 +00001839 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001840 break;
1841 }
1842 case BottomRightOrientation:
1843 {
anthony92c93bd2012-03-19 14:02:47 +00001844 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001845 break;
1846 }
1847 case BottomLeftOrientation:
1848 {
anthony92c93bd2012-03-19 14:02:47 +00001849 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001850 break;
1851 }
1852 case LeftTopOrientation:
1853 {
anthony92c93bd2012-03-19 14:02:47 +00001854 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001855 break;
1856 }
1857 case RightTopOrientation:
1858 {
anthony92c93bd2012-03-19 14:02:47 +00001859 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001860 break;
1861 }
1862 case RightBottomOrientation:
1863 {
anthony92c93bd2012-03-19 14:02:47 +00001864 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001865 break;
1866 }
1867 case LeftBottomOrientation:
1868 {
anthony92c93bd2012-03-19 14:02:47 +00001869 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001870 break;
1871 }
1872 default:
1873 break;
1874 }
1875 if (new_image != (Image *) NULL)
1876 new_image->orientation=TopLeftOrientation;
1877 break;
1878 }
anthonyebb73a22012-03-22 14:25:52 +00001879 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001880 }
1881 case 'b':
1882 {
anthonyafa3dfc2012-03-03 11:31:30 +00001883 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001884 {
anthony5330ae02012-03-20 14:17:01 +00001885 if (IsGeometry(arg1) == MagickFalse)
1886 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001887 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001888 break;
1889 }
anthonyafa3dfc2012-03-03 11:31:30 +00001890 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001891 {
anthony805a2d42011-09-25 08:25:12 +00001892 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001893 if (IfNormalOp) {
1894 if (IsGeometry(arg1) == MagickFalse)
1895 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001896 flags=ParseGeometry(arg1,&geometry_info);
anthony5330ae02012-03-20 14:17:01 +00001897 }
anthony92c93bd2012-03-19 14:02:47 +00001898 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001899 break;
1900 }
anthonyafa3dfc2012-03-03 11:31:30 +00001901 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001902 {
anthony74b1cfc2011-10-06 12:44:16 +00001903 /* FUTURE: use of "bias" in a blur is non-sensible */
anthony5330ae02012-03-20 14:17:01 +00001904 if (IsGeometry(arg1) == MagickFalse)
1905 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001906 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001907 if ((flags & SigmaValue) == 0)
1908 geometry_info.sigma=1.0;
1909 if ((flags & XiValue) == 0)
1910 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001911 new_image=BlurImage(_image,geometry_info.rho,
1912 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001913 break;
1914 }
anthonyafa3dfc2012-03-03 11:31:30 +00001915 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001916 {
anthony31f1bf72012-01-30 12:37:22 +00001917 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001918 compose;
1919
1920 const char*
anthony5f867ae2011-10-09 10:28:34 +00001921 value;
1922
anthony5330ae02012-03-20 14:17:01 +00001923 if (IsGeometry(arg1) == MagickFalse)
1924 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1925
anthony92c93bd2012-03-19 14:02:47 +00001926 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001927 if (value != (const char *) NULL)
1928 compose=(CompositeOperator) ParseCommandOption(
1929 MagickComposeOptions,MagickFalse,value);
1930 else
anthony92c93bd2012-03-19 14:02:47 +00001931 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001932
anthony92c93bd2012-03-19 14:02:47 +00001933 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001934 if ((flags & SigmaValue) == 0)
1935 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001936 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001937 break;
1938 }
anthonyafa3dfc2012-03-03 11:31:30 +00001939 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001940 {
1941 double
1942 brightness,
1943 contrast;
1944
1945 GeometryInfo
1946 geometry_info;
1947
1948 MagickStatusType
1949 flags;
1950
anthony5330ae02012-03-20 14:17:01 +00001951 if (IsGeometry(arg1) == MagickFalse)
1952 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001953 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001954 brightness=geometry_info.rho;
1955 contrast=0.0;
1956 if ((flags & SigmaValue) != 0)
1957 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001958 (void) BrightnessContrastImage(_image,brightness,contrast,
1959 _exception);
anthony805a2d42011-09-25 08:25:12 +00001960 break;
1961 }
anthonyebb73a22012-03-22 14:25:52 +00001962 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001963 }
1964 case 'c':
1965 {
anthonyafa3dfc2012-03-03 11:31:30 +00001966 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001967 {
1968 char
1969 *color_correction_collection;
1970
1971 /*
1972 Color correct with a color decision list.
1973 */
anthony92c93bd2012-03-19 14:02:47 +00001974 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001975 if (color_correction_collection == (char *) NULL)
1976 break;
anthony92c93bd2012-03-19 14:02:47 +00001977 (void) ColorDecisionListImage(_image,color_correction_collection,
1978 _exception);
anthony805a2d42011-09-25 08:25:12 +00001979 break;
1980 }
anthonyafa3dfc2012-03-03 11:31:30 +00001981 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001982 {
anthony5330ae02012-03-20 14:17:01 +00001983 if (IsGeometry(arg1) == MagickFalse)
1984 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001985 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001986 if ((flags & SigmaValue) == 0)
1987 geometry_info.sigma=1.0;
1988 if ((flags & XiValue) == 0)
1989 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001990 new_image=CharcoalImage(_image,geometry_info.rho,
1991 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001992 break;
1993 }
anthonyafa3dfc2012-03-03 11:31:30 +00001994 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001995 {
anthony5330ae02012-03-20 14:17:01 +00001996 if (IsGeometry(arg1) == MagickFalse)
1997 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001998 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1999 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002000 break;
2001 }
anthonyafa3dfc2012-03-03 11:31:30 +00002002 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002003 {
anthony92c93bd2012-03-19 14:02:47 +00002004 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002005 break;
2006 }
anthonyafa3dfc2012-03-03 11:31:30 +00002007 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002008 {
anthonyafa3dfc2012-03-03 11:31:30 +00002009 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002010 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00002011 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002012 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002013 break;
2014 }
anthonyafa3dfc2012-03-03 11:31:30 +00002015 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002016 {
2017 CacheView
2018 *mask_view;
2019
2020 Image
2021 *mask_image;
2022
2023 register Quantum
2024 *restrict q;
2025
2026 register ssize_t
2027 x;
2028
2029 ssize_t
2030 y;
2031
anthonyafa3dfc2012-03-03 11:31:30 +00002032 if (IfPlusOp) {
2033 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002034 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002035 break;
2036 }
anthony92c93bd2012-03-19 14:02:47 +00002037 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002038 if (mask_image == (Image *) NULL)
2039 break;
anthony92c93bd2012-03-19 14:02:47 +00002040 if (SetImageStorageClass(mask_image,DirectClass,_exception)
anthonyfd706f92012-01-19 04:22:02 +00002041 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00002042 break;
anthony5330ae02012-03-20 14:17:01 +00002043 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002044 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00002045 mask_view=AcquireCacheView(mask_image);
2046 for (y=0; y < (ssize_t) mask_image->rows; y++)
2047 {
2048 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002049 _exception);
anthony805a2d42011-09-25 08:25:12 +00002050 if (q == (Quantum *) NULL)
2051 break;
2052 for (x=0; x < (ssize_t) mask_image->columns; x++)
2053 {
2054 if (mask_image->matte == MagickFalse)
2055 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2056 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2057 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2058 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2059 q+=GetPixelChannels(mask_image);
2060 }
anthony92c93bd2012-03-19 14:02:47 +00002061 if (SyncCacheViewAuthenticPixels(mask_view,_exception) == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002062 break;
2063 }
anthonyfd706f92012-01-19 04:22:02 +00002064 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002065 mask_view=DestroyCacheView(mask_view);
2066 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002067 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002068 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002069 break;
2070 }
anthonyafa3dfc2012-03-03 11:31:30 +00002071 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002072 {
anthony92c93bd2012-03-19 14:02:47 +00002073 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002074 break;
2075 }
anthonyafa3dfc2012-03-03 11:31:30 +00002076 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002077 {
anthony5330ae02012-03-20 14:17:01 +00002078 if (IsGeometry(arg1) == MagickFalse)
2079 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002080 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002081 break;
2082 }
anthonyafa3dfc2012-03-03 11:31:30 +00002083 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002084 {
2085 KernelInfo
2086 *kernel;
2087
anthonyfd706f92012-01-19 04:22:02 +00002088 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002089 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002090 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002091 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002092 kernel=DestroyKernelInfo(kernel);
2093 break;
2094 }
anthonyafa3dfc2012-03-03 11:31:30 +00002095 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002096 {
anthony5330ae02012-03-20 14:17:01 +00002097 /* Reduce the number of colors in the image.
2098 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002099 */
anthony92c93bd2012-03-19 14:02:47 +00002100 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2101 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002102 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002103 if ((_image->storage_class == DirectClass) ||
2104 _image->colors > _quantize_info->number_colors)
2105 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002106 else
anthony92c93bd2012-03-19 14:02:47 +00002107 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002108 break;
2109 }
anthonyafa3dfc2012-03-03 11:31:30 +00002110 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002111 {
anthony5330ae02012-03-20 14:17:01 +00002112 /* WARNING: this is both a image_info setting (already done)
2113 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002114
2115 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002116 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002117
anthonyd2cdc862011-10-07 14:07:17 +00002118 Note that +colorspace sets "undefined" or no effect on
2119 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002120 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002121 */
anthony92c93bd2012-03-19 14:02:47 +00002122 (void) TransformImageColorspace(_image,
2123 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2124 _exception);
anthony805a2d42011-09-25 08:25:12 +00002125 break;
2126 }
anthonyafa3dfc2012-03-03 11:31:30 +00002127 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002128 {
anthonydcf3a912012-03-22 14:33:17 +00002129 /* DEPRECIATED: The -/+level provides far more controlled form */
anthony92c93bd2012-03-19 14:02:47 +00002130 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002131 break;
2132 }
anthonyafa3dfc2012-03-03 11:31:30 +00002133 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002134 {
2135 double
2136 black_point,
2137 white_point;
2138
2139 MagickStatusType
2140 flags;
2141
anthonyebb73a22012-03-22 14:25:52 +00002142 if (IsGeometry(arg1) == MagickFalse)
2143 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002144 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002145 black_point=geometry_info.rho;
2146 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2147 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002148 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002149 black_point*=(double) _image->columns*_image->rows/100.0;
2150 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002151 }
anthony92c93bd2012-03-19 14:02:47 +00002152 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002153 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002154 (void) ContrastStretchImage(_image,black_point,white_point,
2155 _exception);
anthony805a2d42011-09-25 08:25:12 +00002156 break;
2157 }
anthonyafa3dfc2012-03-03 11:31:30 +00002158 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002159 {
2160 KernelInfo
2161 *kernel_info;
2162
anthonyfd706f92012-01-19 04:22:02 +00002163 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002164 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002165 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002166 kernel_info->bias=_image->bias;
2167 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002168 kernel_info=DestroyKernelInfo(kernel_info);
2169 break;
2170 }
anthonyafa3dfc2012-03-03 11:31:30 +00002171 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002172 {
anthony31f1bf72012-01-30 12:37:22 +00002173 /* WARNING: This can generate multiple images! */
anthonyebb73a22012-03-22 14:25:52 +00002174 if (IsGeometry(arg1) == MagickFalse)
2175 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002176 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002177 break;
2178 }
anthonyafa3dfc2012-03-03 11:31:30 +00002179 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002180 {
anthonyebb73a22012-03-22 14:25:52 +00002181 if (IsGeometry(arg1) == MagickFalse)
2182 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002183 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2184 _exception);
anthony805a2d42011-09-25 08:25:12 +00002185 break;
2186 }
anthonyebb73a22012-03-22 14:25:52 +00002187 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002188 }
2189 case 'd':
2190 {
anthonyafa3dfc2012-03-03 11:31:30 +00002191 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002192 {
2193 StringInfo
2194 *passkey;
2195
anthony92c93bd2012-03-19 14:02:47 +00002196 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002197 if (passkey == (StringInfo *) NULL)
2198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2199
2200 (void) PasskeyDecipherImage(_image,passkey,_exception);
2201 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002202 break;
2203 }
anthonyafa3dfc2012-03-03 11:31:30 +00002204 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002205 {
anthony92c93bd2012-03-19 14:02:47 +00002206 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002207 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002208
anthonydcf510d2011-10-30 13:51:40 +00002209 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2210 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002211
anthonyfd706f92012-01-19 04:22:02 +00002212 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002213 */
anthony92c93bd2012-03-19 14:02:47 +00002214 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002215 break;
2216 }
anthonyafa3dfc2012-03-03 11:31:30 +00002217 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002218 {
2219 double
2220 threshold;
2221
anthonyebb73a22012-03-22 14:25:52 +00002222 if (IfNormalOp) {
2223 if (IsGeometry(arg1) == MagickFalse)
2224 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002225 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002226 }
anthonyafa3dfc2012-03-03 11:31:30 +00002227 else
2228 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002229 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002230 break;
2231 }
anthonyafa3dfc2012-03-03 11:31:30 +00002232 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002233 {
anthony92c93bd2012-03-19 14:02:47 +00002234 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002235 break;
2236 }
anthonyafa3dfc2012-03-03 11:31:30 +00002237 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002238 {
2239 char
2240 *args,
2241 token[MaxTextExtent];
2242
2243 const char
2244 *p;
2245
anthony805a2d42011-09-25 08:25:12 +00002246 double
2247 *arguments;
2248
2249 register ssize_t
2250 x;
2251
2252 size_t
2253 number_arguments;
2254
anthony2a0ec8c2012-03-24 04:35:56 +00002255 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2256 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002257 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2258 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002259 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002260 {
anthony80c37752012-01-16 01:03:11 +00002261 double
2262 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002263 /* Special Case - Argument is actually a resize geometry!
2264 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002265 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002266 Roll into a resize special operator */
anthonyebb73a22012-03-22 14:25:52 +00002267 if (IsGeometry(arg2) == MagickFalse)
2268 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2269 option,arg2);
2270 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002271 resize_args[0]=(double) geometry.width;
2272 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002273 new_image=DistortImage(_image,(DistortImageMethod) parse,
2274 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002275 break;
2276 }
anthonyfd706f92012-01-19 04:22:02 +00002277 /* handle percent arguments */
anthonyebb73a22012-03-22 14:25:52 +00002278 args=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00002279 if (args == (char *) NULL)
2280 break;
anthonyfd706f92012-01-19 04:22:02 +00002281 /* convert arguments into an array of doubles
2282 FUTURE: make this a separate function.
2283 Also make use of new 'sentinal' feature to avoid need for
2284 tokenization.
2285 */
anthony805a2d42011-09-25 08:25:12 +00002286 p=(char *) args;
2287 for (x=0; *p != '\0'; x++)
2288 {
2289 GetMagickToken(p,&p,token);
2290 if (*token == ',')
2291 GetMagickToken(p,&p,token);
2292 }
2293 number_arguments=(size_t) x;
2294 arguments=(double *) AcquireQuantumMemory(number_arguments,
2295 sizeof(*arguments));
2296 if (arguments == (double *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002297 CLIWandExceptionBreak(ResourceLimitFatalError,
2298 "MemoryAllocationFailed",option);
anthony805a2d42011-09-25 08:25:12 +00002299 (void) ResetMagickMemory(arguments,0,number_arguments*
anthonyebb73a22012-03-22 14:25:52 +00002300 sizeof(*arguments));
anthony805a2d42011-09-25 08:25:12 +00002301 p=(char *) args;
2302 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2303 {
2304 GetMagickToken(p,&p,token);
2305 if (*token == ',')
2306 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002307 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002308 }
2309 args=DestroyString(args);
anthony2a0ec8c2012-03-24 04:35:56 +00002310 new_image=DistortImage(_image,(DistortImageMethod) parse,
2311 number_arguments,arguments,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002312 arguments=(double *) RelinquishMagickMemory(arguments);
2313 break;
2314 }
anthonyafa3dfc2012-03-03 11:31:30 +00002315 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002316 {
anthony92c93bd2012-03-19 14:02:47 +00002317 (void) CloneString(&_draw_info->primitive,arg1);
2318 (void) DrawImage(_image,_draw_info,_exception);
2319 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002320 break;
2321 }
anthonyebb73a22012-03-22 14:25:52 +00002322 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002323 }
2324 case 'e':
2325 {
anthonyafa3dfc2012-03-03 11:31:30 +00002326 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002327 {
anthony2a0ec8c2012-03-24 04:35:56 +00002328 if (IsGeometry(arg1) == MagickFalse)
2329 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002330 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002331 if ((flags & SigmaValue) == 0)
2332 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002333 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2334 _exception);
anthony805a2d42011-09-25 08:25:12 +00002335 break;
2336 }
anthonyafa3dfc2012-03-03 11:31:30 +00002337 if (LocaleCompare("emboss",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;
anthony92c93bd2012-03-19 14:02:47 +00002344 new_image=EmbossImage(_image,geometry_info.rho,
2345 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002346 break;
2347 }
anthonyafa3dfc2012-03-03 11:31:30 +00002348 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002349 {
2350 StringInfo
2351 *passkey;
2352
anthony92c93bd2012-03-19 14:02:47 +00002353 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002354 if (passkey != (StringInfo *) NULL)
2355 {
anthony92c93bd2012-03-19 14:02:47 +00002356 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002357 passkey=DestroyStringInfo(passkey);
2358 }
2359 break;
2360 }
anthonyafa3dfc2012-03-03 11:31:30 +00002361 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002362 {
anthony92c93bd2012-03-19 14:02:47 +00002363 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002364 break;
2365 }
anthonyafa3dfc2012-03-03 11:31:30 +00002366 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002367 {
anthony92c93bd2012-03-19 14:02:47 +00002368 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002369 break;
2370 }
anthonyafa3dfc2012-03-03 11:31:30 +00002371 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002372 {
2373 double
2374 constant;
2375
anthony2a0ec8c2012-03-24 04:35:56 +00002376 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2377 if ( parse < 0 )
2378 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2379 option,arg1);
2380 if (IsGeometry(arg2) == MagickFalse)
2381 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002382 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002383 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2384 _exception);
anthony805a2d42011-09-25 08:25:12 +00002385 break;
2386 }
anthonyafa3dfc2012-03-03 11:31:30 +00002387 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002388 {
anthony2a0ec8c2012-03-24 04:35:56 +00002389 if (IsGeometry(arg1) == MagickFalse)
2390 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002391 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002392 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002393 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002394 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002395 geometry.height=_image->rows;
2396 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002397 break;
2398 }
anthonyebb73a22012-03-22 14:25:52 +00002399 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002400 }
2401 case 'f':
2402 {
anthonyafa3dfc2012-03-03 11:31:30 +00002403 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002404 {
anthony31f1bf72012-01-30 12:37:22 +00002405 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002406 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002407 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002408 break;
2409 }
anthony92c93bd2012-03-19 14:02:47 +00002410 (void) SetImageArtifact(_image,"identify:features","true");
2411 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002412 break;
2413 }
anthonyafa3dfc2012-03-03 11:31:30 +00002414 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002415 {
anthony92c93bd2012-03-19 14:02:47 +00002416 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002417 break;
2418 }
anthonyafa3dfc2012-03-03 11:31:30 +00002419 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002420 {
anthony92c93bd2012-03-19 14:02:47 +00002421 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002422 break;
2423 }
anthonyafa3dfc2012-03-03 11:31:30 +00002424 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002425 {
2426 PixelInfo
2427 target;
2428
anthony2a0ec8c2012-03-24 04:35:56 +00002429 if (IsGeometry(arg1) == MagickFalse)
2430 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002431 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2432 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2433 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2434 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002435 break;
2436 }
anthonyafa3dfc2012-03-03 11:31:30 +00002437 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002438 {
2439 FrameInfo
2440 frame_info;
2441
anthony31f1bf72012-01-30 12:37:22 +00002442 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002443 compose;
2444
2445 const char*
2446 value;
2447
anthony92c93bd2012-03-19 14:02:47 +00002448 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002449 if (value != (const char *) NULL)
2450 compose=(CompositeOperator) ParseCommandOption(
2451 MagickComposeOptions,MagickFalse,value);
2452 else
anthony92c93bd2012-03-19 14:02:47 +00002453 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002454
anthony2a0ec8c2012-03-24 04:35:56 +00002455 if (IsGeometry(arg1) == MagickFalse)
2456 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002457 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002458 frame_info.width=geometry.width;
2459 frame_info.height=geometry.height;
2460 if ((flags & HeightValue) == 0)
2461 frame_info.height=geometry.width;
2462 frame_info.outer_bevel=geometry.x;
2463 frame_info.inner_bevel=geometry.y;
2464 frame_info.x=(ssize_t) frame_info.width;
2465 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002466 frame_info.width=_image->columns+2*frame_info.width;
2467 frame_info.height=_image->rows+2*frame_info.height;
2468 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002469 break;
2470 }
anthonyafa3dfc2012-03-03 11:31:30 +00002471 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002472 {
2473 char
2474 *arguments,
2475 token[MaxTextExtent];
2476
2477 const char
2478 *p;
2479
2480 double
2481 *parameters;
2482
anthony805a2d42011-09-25 08:25:12 +00002483 register ssize_t
2484 x;
2485
2486 size_t
2487 number_parameters;
2488
cristy947cb4c2011-10-20 18:41:46 +00002489 /*
2490 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002491 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002492 */
anthony2a0ec8c2012-03-24 04:35:56 +00002493 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2494 if ( parse < 0 )
2495 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2496 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002497 arguments=InterpretImageProperties(_image_info,_image,arg2,
2498 _exception);
anthony805a2d42011-09-25 08:25:12 +00002499 if (arguments == (char *) NULL)
anthony2a0ec8c2012-03-24 04:35:56 +00002500 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony805a2d42011-09-25 08:25:12 +00002501 p=(char *) arguments;
2502 for (x=0; *p != '\0'; x++)
2503 {
2504 GetMagickToken(p,&p,token);
2505 if (*token == ',')
2506 GetMagickToken(p,&p,token);
2507 }
2508 number_parameters=(size_t) x;
2509 parameters=(double *) AcquireQuantumMemory(number_parameters,
2510 sizeof(*parameters));
2511 if (parameters == (double *) NULL)
2512 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002513 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002514 (void) ResetMagickMemory(parameters,0,number_parameters*
2515 sizeof(*parameters));
2516 p=(char *) arguments;
anthony2a0ec8c2012-03-24 04:35:56 +00002517 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++) {
anthony805a2d42011-09-25 08:25:12 +00002518 GetMagickToken(p,&p,token);
2519 if (*token == ',')
2520 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002521 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002522 }
2523 arguments=DestroyString(arguments);
anthony2a0ec8c2012-03-24 04:35:56 +00002524 (void) FunctionImage(_image,(MagickFunction)parse,number_parameters,
2525 parameters,_exception);
anthony805a2d42011-09-25 08:25:12 +00002526 parameters=(double *) RelinquishMagickMemory(parameters);
2527 break;
2528 }
anthonyebb73a22012-03-22 14:25:52 +00002529 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002530 }
2531 case 'g':
2532 {
anthonyafa3dfc2012-03-03 11:31:30 +00002533 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002534 {
anthonyfe1aa782012-03-24 13:43:04 +00002535 if (IsGeometry(arg1) == MagickFalse)
2536 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafa3dfc2012-03-03 11:31:30 +00002537 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002538 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2539 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002540 else
anthony92c93bd2012-03-19 14:02:47 +00002541 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002542 break;
2543 }
anthonyafa3dfc2012-03-03 11:31:30 +00002544 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2545 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002546 {
anthonyfe1aa782012-03-24 13:43:04 +00002547 if (IsGeometry(arg1) == MagickFalse)
2548 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002549 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002550 if ((flags & SigmaValue) == 0)
2551 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002552 new_image=GaussianBlurImage(_image,geometry_info.rho,
2553 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002554 break;
2555 }
anthonyafa3dfc2012-03-03 11:31:30 +00002556 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002557 {
anthonyfd706f92012-01-19 04:22:02 +00002558 /*
anthony31f1bf72012-01-30 12:37:22 +00002559 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002560 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002561 FUTURE: Why if no 'offset' does this resize ALL images?
2562 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002563 */
anthonyafa3dfc2012-03-03 11:31:30 +00002564 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002565 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002566 if (_image->geometry != (char *) NULL)
2567 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002568 break;
2569 }
anthonyfe1aa782012-03-24 13:43:04 +00002570 if (IsGeometry(arg1) == MagickFalse)
2571 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002572 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002573 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002574 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002575 else
anthony92c93bd2012-03-19 14:02:47 +00002576 new_image=ResizeImage(_image,geometry.width,geometry.height,
2577 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00002578 break;
2579 }
anthonyebb73a22012-03-22 14:25:52 +00002580 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002581 }
2582 case 'h':
2583 {
anthonyafa3dfc2012-03-03 11:31:30 +00002584 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002585 {
anthony92c93bd2012-03-19 14:02:47 +00002586 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002587 break;
2588 }
anthonyebb73a22012-03-22 14:25:52 +00002589 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002590 }
2591 case 'i':
2592 {
anthonyafa3dfc2012-03-03 11:31:30 +00002593 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002594 {
anthony31f1bf72012-01-30 12:37:22 +00002595 const char
2596 *format,
anthony805a2d42011-09-25 08:25:12 +00002597 *text;
2598
anthony92c93bd2012-03-19 14:02:47 +00002599 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002600 if (format == (char *) NULL)
2601 {
anthony92c93bd2012-03-19 14:02:47 +00002602 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2603 _exception);
anthony805a2d42011-09-25 08:25:12 +00002604 break;
2605 }
anthony92c93bd2012-03-19 14:02:47 +00002606 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002607 if (text == (char *) NULL)
2608 break;
2609 (void) fputs(text,stdout);
2610 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002611 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002612 break;
2613 }
anthonyafa3dfc2012-03-03 11:31:30 +00002614 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002615 {
anthonyfe1aa782012-03-24 13:43:04 +00002616 if (IsGeometry(arg1) == MagickFalse)
2617 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002618 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002619 new_image=ImplodeImage(_image,geometry_info.rho,
2620 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002621 break;
2622 }
anthonyafa3dfc2012-03-03 11:31:30 +00002623 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002624 {
anthonyfe1aa782012-03-24 13:43:04 +00002625 /* FUTURE: New to IMv7
2626 Roll into a resize special operator */
2627 if (IsGeometry(arg1) == MagickFalse)
2628 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002629 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2630 new_image=InterpolativeResizeImage(_image,geometry.width,
2631 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002632 break;
2633 }
anthonyebb73a22012-03-22 14:25:52 +00002634 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002635 }
2636 case 'l':
2637 {
anthonyafa3dfc2012-03-03 11:31:30 +00002638 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002639 {
anthonyfe1aa782012-03-24 13:43:04 +00002640 if (IsGeometry(arg1) == MagickFalse)
2641 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002642 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002643 if ((flags & PercentValue) != 0)
2644 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002645 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002646 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002647 _exception);
anthony805a2d42011-09-25 08:25:12 +00002648 break;
2649 }
anthonyafa3dfc2012-03-03 11:31:30 +00002650 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002651 {
2652 MagickRealType
2653 black_point,
2654 gamma,
2655 white_point;
2656
2657 MagickStatusType
2658 flags;
2659
anthonyfe1aa782012-03-24 13:43:04 +00002660 if (IsGeometry(arg1) == MagickFalse)
2661 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002662 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002663 black_point=geometry_info.rho;
2664 white_point=(MagickRealType) QuantumRange;
2665 if ((flags & SigmaValue) != 0)
2666 white_point=geometry_info.sigma;
2667 gamma=1.0;
2668 if ((flags & XiValue) != 0)
2669 gamma=geometry_info.xi;
2670 if ((flags & PercentValue) != 0)
2671 {
2672 black_point*=(MagickRealType) (QuantumRange/100.0);
2673 white_point*=(MagickRealType) (QuantumRange/100.0);
2674 }
2675 if ((flags & SigmaValue) == 0)
2676 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002677 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002678 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002679 else
anthony92c93bd2012-03-19 14:02:47 +00002680 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002681 break;
2682 }
anthonyafa3dfc2012-03-03 11:31:30 +00002683 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002684 {
2685 char
2686 token[MaxTextExtent];
2687
2688 const char
2689 *p;
2690
2691 PixelInfo
2692 black_point,
2693 white_point;
2694
anthonyfd706f92012-01-19 04:22:02 +00002695 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002696 GetMagickToken(p,&p,token); /* get black point color */
2697 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002698 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002699 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002700 else
cristy269c9412011-10-13 23:41:15 +00002701 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002702 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002703 if (isalpha((int) token[0]) || (token[0] == '#'))
2704 GetMagickToken(p,&p,token);
2705 if (*token == '\0')
2706 white_point=black_point; /* set everything to that color */
2707 else
2708 {
2709 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2710 GetMagickToken(p,&p,token); /* Get white point color. */
2711 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002712 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002713 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002714 else
cristy269c9412011-10-13 23:41:15 +00002715 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002716 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002717 }
anthony92c93bd2012-03-19 14:02:47 +00002718 (void) LevelImageColors(_image,&black_point,&white_point,
2719 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002720 break;
2721 }
anthonyafa3dfc2012-03-03 11:31:30 +00002722 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002723 {
2724 double
2725 black_point,
2726 white_point;
2727
2728 MagickStatusType
2729 flags;
2730
anthonyfe1aa782012-03-24 13:43:04 +00002731 if (IsGeometry(arg1) == MagickFalse)
2732 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002733 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002734 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002735 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002736 if ((flags & SigmaValue) != 0)
2737 white_point=geometry_info.sigma;
2738 if ((flags & PercentValue) != 0)
2739 {
anthony92c93bd2012-03-19 14:02:47 +00002740 black_point*=(double) _image->columns*_image->rows/100.0;
2741 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002742 }
2743 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002744 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002745 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002746 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002747 break;
2748 }
anthonyafa3dfc2012-03-03 11:31:30 +00002749 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002750 {
anthonyfe1aa782012-03-24 13:43:04 +00002751 /* FUTURE: Roll into a resize special operator */
2752 if (IsGeometry(arg1) == MagickFalse)
2753 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002754 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002755 if ((flags & XValue) == 0)
2756 geometry.x=1;
2757 if ((flags & YValue) == 0)
2758 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002759 new_image=LiquidRescaleImage(_image,geometry.width,
2760 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002761 break;
2762 }
anthonyafa3dfc2012-03-03 11:31:30 +00002763 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002764 {
anthony92c93bd2012-03-19 14:02:47 +00002765 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002766 break;
2767 }
anthonyebb73a22012-03-22 14:25:52 +00002768 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002769 }
2770 case 'm':
2771 {
anthonyafa3dfc2012-03-03 11:31:30 +00002772 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002773 {
2774 Image
2775 *remap_image;
2776
anthony31f1bf72012-01-30 12:37:22 +00002777 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002778 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002779 if (remap_image == (Image *) NULL)
2780 break;
anthony92c93bd2012-03-19 14:02:47 +00002781 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002782 remap_image=DestroyImage(remap_image);
2783 break;
2784 }
anthonyafa3dfc2012-03-03 11:31:30 +00002785 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002786 {
2787 Image
2788 *mask;
2789
anthonyafa3dfc2012-03-03 11:31:30 +00002790 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002791 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002792 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002793 break;
2794 }
anthony5330ae02012-03-20 14:17:01 +00002795 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002796 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002797 if (mask == (Image *) NULL)
2798 break;
anthony92c93bd2012-03-19 14:02:47 +00002799 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002800 mask=DestroyImage(mask);
2801 break;
2802 }
anthonyafa3dfc2012-03-03 11:31:30 +00002803 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002804 {
anthony31f1bf72012-01-30 12:37:22 +00002805 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002806 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2807 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002808 break;
2809 }
anthonya3ef4ed2012-03-17 06:52:53 +00002810 if (LocaleCompare("median",option+1) == 0)
2811 {
2812 /* DEPRECIATED - use -statistic Median */
2813 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2814 break;
2815 }
anthonyafa3dfc2012-03-03 11:31:30 +00002816 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002817 {
anthonyfd706f92012-01-19 04:22:02 +00002818 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002819 if ((flags & SigmaValue) == 0)
2820 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002821 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2822 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002823 break;
2824 }
anthonyafa3dfc2012-03-03 11:31:30 +00002825 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002826 {
anthony92c93bd2012-03-19 14:02:47 +00002827 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002828 break;
2829 }
anthonyafa3dfc2012-03-03 11:31:30 +00002830 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002831 {
anthony92c93bd2012-03-19 14:02:47 +00002832 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002833 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002834 break;
2835 }
anthonyafa3dfc2012-03-03 11:31:30 +00002836 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002837 {
anthony92c93bd2012-03-19 14:02:47 +00002838 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002839 break;
2840 }
anthonyafa3dfc2012-03-03 11:31:30 +00002841 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002842 {
2843 char
2844 token[MaxTextExtent];
2845
2846 const char
2847 *p;
2848
2849 KernelInfo
2850 *kernel;
2851
2852 MorphologyMethod
2853 method;
2854
2855 ssize_t
2856 iterations;
2857
anthonyfd706f92012-01-19 04:22:02 +00002858 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002859 GetMagickToken(p,&p,token);
2860 method=(MorphologyMethod) ParseCommandOption(
2861 MagickMorphologyOptions,MagickFalse,token);
2862 iterations=1L;
2863 GetMagickToken(p,&p,token);
2864 if ((*p == ':') || (*p == ','))
2865 GetMagickToken(p,&p,token);
2866 if ((*p != '\0'))
2867 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002868 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002869 if (kernel == (KernelInfo *) NULL)
2870 {
anthony92c93bd2012-03-19 14:02:47 +00002871 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002872 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002873 break;
2874 }
anthony92c93bd2012-03-19 14:02:47 +00002875 new_image=MorphologyImage(_image,method,iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002876 kernel=DestroyKernelInfo(kernel);
2877 break;
2878 }
anthonyafa3dfc2012-03-03 11:31:30 +00002879 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002880 {
anthonyfd706f92012-01-19 04:22:02 +00002881 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002882 if ((flags & SigmaValue) == 0)
2883 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002884 new_image=MotionBlurImage(_image,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002885 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
anthony92c93bd2012-03-19 14:02:47 +00002886 _exception);
anthony805a2d42011-09-25 08:25:12 +00002887 break;
2888 }
anthonyebb73a22012-03-22 14:25:52 +00002889 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002890 }
2891 case 'n':
2892 {
anthonyafa3dfc2012-03-03 11:31:30 +00002893 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002894 {
anthony92c93bd2012-03-19 14:02:47 +00002895 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002896 break;
2897 }
anthonyafa3dfc2012-03-03 11:31:30 +00002898 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002899 {
anthonyafa3dfc2012-03-03 11:31:30 +00002900 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002901 {
anthonyfd706f92012-01-19 04:22:02 +00002902 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002903 if ((flags & SigmaValue) == 0)
2904 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002905 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2906 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002907 }
2908 else
2909 {
2910 NoiseType
2911 noise;
2912
anthony31f1bf72012-01-30 12:37:22 +00002913 double
2914 attenuate;
2915
2916 const char*
2917 value;
2918
anthony805a2d42011-09-25 08:25:12 +00002919 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002920 MagickFalse,arg1),
2921
anthony92c93bd2012-03-19 14:02:47 +00002922 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002923 if (value != (const char *) NULL)
2924 attenuate=StringToDouble(value,(char **) NULL);
2925 else
2926 attenuate=1.0;
2927
anthony92c93bd2012-03-19 14:02:47 +00002928 new_image=AddNoiseImage(_image,noise,attenuate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002929 }
2930 break;
2931 }
anthonyafa3dfc2012-03-03 11:31:30 +00002932 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002933 {
anthony92c93bd2012-03-19 14:02:47 +00002934 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002935 break;
2936 }
anthonyebb73a22012-03-22 14:25:52 +00002937 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002938 }
2939 case 'o':
2940 {
anthonyafa3dfc2012-03-03 11:31:30 +00002941 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002942 {
2943 PixelInfo
2944 target;
2945
anthony92c93bd2012-03-19 14:02:47 +00002946 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2947 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2948 _exception);
anthony805a2d42011-09-25 08:25:12 +00002949 break;
2950 }
anthonyafa3dfc2012-03-03 11:31:30 +00002951 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002952 {
anthony92c93bd2012-03-19 14:02:47 +00002953 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002954 break;
2955 }
anthonyebb73a22012-03-22 14:25:52 +00002956 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002957 }
2958 case 'p':
2959 {
anthonyafa3dfc2012-03-03 11:31:30 +00002960 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002961 {
anthonyfd706f92012-01-19 04:22:02 +00002962 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002963 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2964 _exception);
anthony805a2d42011-09-25 08:25:12 +00002965 break;
2966 }
anthonyafa3dfc2012-03-03 11:31:30 +00002967 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002968 {
cristye9e3d382011-12-14 01:50:13 +00002969 const char
2970 *caption;
2971
anthony805a2d42011-09-25 08:25:12 +00002972 double
2973 angle;
2974
anthonyafa3dfc2012-03-03 11:31:30 +00002975 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002976 {
2977 RandomInfo
2978 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002979
anthony31f1bf72012-01-30 12:37:22 +00002980 random_info=AcquireRandomInfo();
2981 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2982 random_info=DestroyRandomInfo(random_info);
2983 }
2984 else
anthony805a2d42011-09-25 08:25:12 +00002985 {
2986 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002987 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002988 angle=geometry_info.rho;
2989 }
anthony92c93bd2012-03-19 14:02:47 +00002990 caption=GetImageProperty(_image,"caption",_exception);
2991 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2992 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002993 break;
2994 }
anthonyafa3dfc2012-03-03 11:31:30 +00002995 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002996 {
anthony31f1bf72012-01-30 12:37:22 +00002997 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002998 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2999 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00003000 break;
3001 }
anthonyafa3dfc2012-03-03 11:31:30 +00003002 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003003 {
3004 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00003005 preview_type;
anthony170fce92011-10-20 11:50:23 +00003006
anthony31f1bf72012-01-30 12:37:22 +00003007 /* FUTURE: should be a 'Genesis' option?
3008 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00003009 */
anthony31f1bf72012-01-30 12:37:22 +00003010 preview_type=UndefinedPreview;
anthonyafa3dfc2012-03-03 11:31:30 +00003011 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003012 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
3013 MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003014 new_image=PreviewImage(_image,preview_type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003015 break;
3016 }
anthonyafa3dfc2012-03-03 11:31:30 +00003017 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003018 {
3019 const char
3020 *name;
3021
3022 const StringInfo
3023 *profile;
3024
3025 Image
3026 *profile_image;
3027
3028 ImageInfo
3029 *profile_info;
3030
anthonyafa3dfc2012-03-03 11:31:30 +00003031 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003032 { /* Remove a profile from the _image. */
3033 (void) ProfileImage(_image,arg1,(const unsigned char *)
3034 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003035 break;
3036 }
anthony92c93bd2012-03-19 14:02:47 +00003037 /* Associate a profile with the _image. */
3038 profile_info=CloneImageInfo(_image_info);
3039 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003040 if (profile != (StringInfo *) NULL)
3041 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003042 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003043 profile_info=DestroyImageInfo(profile_info);
3044 if (profile_image == (Image *) NULL)
3045 {
3046 StringInfo
3047 *profile;
3048
anthony92c93bd2012-03-19 14:02:47 +00003049 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003050 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00003051 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00003052 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003053 if (profile != (StringInfo *) NULL)
3054 {
anthony92c93bd2012-03-19 14:02:47 +00003055 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003056 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003057 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003058 profile=DestroyStringInfo(profile);
3059 }
3060 profile_info=DestroyImageInfo(profile_info);
3061 break;
3062 }
3063 ResetImageProfileIterator(profile_image);
3064 name=GetNextImageProfile(profile_image);
3065 while (name != (const char *) NULL)
3066 {
3067 profile=GetImageProfile(profile_image,name);
3068 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003069 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3070 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003071 name=GetNextImageProfile(profile_image);
3072 }
3073 profile_image=DestroyImage(profile_image);
3074 break;
3075 }
anthonyebb73a22012-03-22 14:25:52 +00003076 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003077 }
anthony805a2d42011-09-25 08:25:12 +00003078 case 'r':
3079 {
anthonyafa3dfc2012-03-03 11:31:30 +00003080 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003081 {
anthonyfd706f92012-01-19 04:22:02 +00003082 flags=ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003083 new_image=RadialBlurImage(_image,geometry_info.rho,
3084 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003085 break;
3086 }
anthonyafa3dfc2012-03-03 11:31:30 +00003087 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003088 {
anthony92c93bd2012-03-19 14:02:47 +00003089 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003090 if ((flags & SigmaValue) == 0)
3091 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00003092 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003093 break;
3094 }
anthonyafa3dfc2012-03-03 11:31:30 +00003095 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003096 {
anthony92c93bd2012-03-19 14:02:47 +00003097 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003098 break;
3099 }
anthonyafa3dfc2012-03-03 11:31:30 +00003100 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003101 {
3102 Image
3103 *remap_image;
3104
anthony92c93bd2012-03-19 14:02:47 +00003105 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003106 if (remap_image == (Image *) NULL)
3107 break;
anthony92c93bd2012-03-19 14:02:47 +00003108 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003109 remap_image=DestroyImage(remap_image);
3110 break;
3111 }
anthonyafa3dfc2012-03-03 11:31:30 +00003112 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003113 {
anthonyafa3dfc2012-03-03 11:31:30 +00003114 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003115 (void) ResetImagePage(_image,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003116 else
anthony92c93bd2012-03-19 14:02:47 +00003117 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003118 break;
3119 }
anthonyafa3dfc2012-03-03 11:31:30 +00003120 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003121 {
anthony31f1bf72012-01-30 12:37:22 +00003122 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00003123 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003124 if ((flags & SigmaValue) == 0)
3125 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003126 new_image=ResampleImage(_image,geometry_info.rho,
3127 geometry_info.sigma,_image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003128 break;
3129 }
anthonyafa3dfc2012-03-03 11:31:30 +00003130 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003131 {
anthonyafbaed72011-10-26 12:05:04 +00003132 /* FUTURE: remove blur argument - no longer used */
anthony92c93bd2012-03-19 14:02:47 +00003133 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3134 new_image=ResizeImage(_image,geometry.width,geometry.height,
3135 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003136 break;
3137 }
anthonyafa3dfc2012-03-03 11:31:30 +00003138 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003139 {
anthony92c93bd2012-03-19 14:02:47 +00003140 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3141 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003142 break;
3143 }
anthonyafa3dfc2012-03-03 11:31:30 +00003144 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003145 {
anthonyfd706f92012-01-19 04:22:02 +00003146 if (strchr(arg1,'>') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003147 if (_image->columns <= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003148 break;
anthonyfd706f92012-01-19 04:22:02 +00003149 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003150 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003151 break;
anthonyafbaed72011-10-26 12:05:04 +00003152
anthonyfd706f92012-01-19 04:22:02 +00003153 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003154 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003155 break;
3156 }
anthonyebb73a22012-03-22 14:25:52 +00003157 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003158 }
3159 case 's':
3160 {
anthonyafa3dfc2012-03-03 11:31:30 +00003161 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003162 {
anthonyfe1aa782012-03-24 13:43:04 +00003163 /* FUTURE: Roll into a resize special operator */
anthony92c93bd2012-03-19 14:02:47 +00003164 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3165 new_image=SampleImage(_image,geometry.width,geometry.height,
3166 _exception);
anthony805a2d42011-09-25 08:25:12 +00003167 break;
3168 }
anthonyafa3dfc2012-03-03 11:31:30 +00003169 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003170 {
anthonyfe1aa782012-03-24 13:43:04 +00003171 /* FUTURE: Roll into a resize special operator */
anthony92c93bd2012-03-19 14:02:47 +00003172 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3173 new_image=ScaleImage(_image,geometry.width,geometry.height,
3174 _exception);
anthony805a2d42011-09-25 08:25:12 +00003175 break;
3176 }
anthonyafa3dfc2012-03-03 11:31:30 +00003177 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003178 {
anthonyfd706f92012-01-19 04:22:02 +00003179 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003180 if ((flags & PercentValue) != 0)
3181 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003182 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3183 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003184 break;
3185 }
anthonyafa3dfc2012-03-03 11:31:30 +00003186 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003187 {
anthony31f1bf72012-01-30 12:37:22 +00003188 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003189 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003190 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003191 break;
3192 }
anthonyafa3dfc2012-03-03 11:31:30 +00003193 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003194 {
3195 double
3196 threshold;
3197
anthonyfd706f92012-01-19 04:22:02 +00003198 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003199 new_image=SepiaToneImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003200 break;
3201 }
anthonyafa3dfc2012-03-03 11:31:30 +00003202 if (LocaleCompare("segment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003203 {
anthonyfd706f92012-01-19 04:22:02 +00003204 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003205 if ((flags & SigmaValue) == 0)
3206 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003207 (void) SegmentImage(_image,_image->colorspace,
3208 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3209 _exception);
anthony805a2d42011-09-25 08:25:12 +00003210 break;
3211 }
anthonyafa3dfc2012-03-03 11:31:30 +00003212 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003213 {
3214 char
3215 *value;
3216
anthonyafa3dfc2012-03-03 11:31:30 +00003217 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00003218 {
anthonyfd706f92012-01-19 04:22:02 +00003219 if (LocaleNCompare(arg1,"registry:",9) == 0)
3220 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003221 else
anthony31f1bf72012-01-30 12:37:22 +00003222 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003223 {
anthony92c93bd2012-03-19 14:02:47 +00003224 (void) DeleteImageOption(_image_info,arg1+7);
3225 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003226 }
3227 else
anthony92c93bd2012-03-19 14:02:47 +00003228 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003229 break;
3230 }
anthony92c93bd2012-03-19 14:02:47 +00003231 value=InterpretImageProperties(_image_info,_image,arg2,
3232 _exception);
anthony805a2d42011-09-25 08:25:12 +00003233 if (value == (char *) NULL)
3234 break;
anthonyfd706f92012-01-19 04:22:02 +00003235 if (LocaleNCompare(arg1,"registry:",9) == 0)
3236 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony92c93bd2012-03-19 14:02:47 +00003237 _exception);
anthony805a2d42011-09-25 08:25:12 +00003238 else
anthonyfd706f92012-01-19 04:22:02 +00003239 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003240 {
anthony92c93bd2012-03-19 14:02:47 +00003241 (void) SetImageOption(_image_info,arg1+7,value);
3242 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003243 }
3244 else
anthony92c93bd2012-03-19 14:02:47 +00003245 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003246 value=DestroyString(value);
3247 break;
3248 }
anthonyafa3dfc2012-03-03 11:31:30 +00003249 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003250 {
anthonyfd706f92012-01-19 04:22:02 +00003251 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003252 if ((flags & SigmaValue) == 0)
3253 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003254 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3255 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003256 break;
3257 }
anthonyafa3dfc2012-03-03 11:31:30 +00003258 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003259 {
anthonyfd706f92012-01-19 04:22:02 +00003260 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003261 if ((flags & SigmaValue) == 0)
3262 geometry_info.sigma=1.0;
3263 if ((flags & XiValue) == 0)
3264 geometry_info.xi=4.0;
3265 if ((flags & PsiValue) == 0)
3266 geometry_info.psi=4.0;
anthony92c93bd2012-03-19 14:02:47 +00003267 new_image=ShadowImage(_image,geometry_info.rho,
3268 geometry_info.sigma,_image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003269 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
anthony92c93bd2012-03-19 14:02:47 +00003270 _exception);
anthony805a2d42011-09-25 08:25:12 +00003271 break;
3272 }
anthonyafa3dfc2012-03-03 11:31:30 +00003273 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003274 {
anthonyfd706f92012-01-19 04:22:02 +00003275 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003276 if ((flags & SigmaValue) == 0)
3277 geometry_info.sigma=1.0;
3278 if ((flags & XiValue) == 0)
3279 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00003280 new_image=SharpenImage(_image,geometry_info.rho,
3281 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003282 break;
3283 }
anthonyafa3dfc2012-03-03 11:31:30 +00003284 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003285 {
anthony92c93bd2012-03-19 14:02:47 +00003286 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3287 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003288 break;
3289 }
anthonyafa3dfc2012-03-03 11:31:30 +00003290 if (LocaleCompare("shear",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=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003295 new_image=ShearImage(_image,geometry_info.rho,
3296 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003297 break;
3298 }
anthonyafa3dfc2012-03-03 11:31:30 +00003299 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003300 {
anthonyfd706f92012-01-19 04:22:02 +00003301 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003302 if ((flags & SigmaValue) == 0)
3303 geometry_info.sigma=(double) QuantumRange/2.0;
3304 if ((flags & PercentValue) != 0)
3305 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3306 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003307 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003308 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003309 _exception);
anthony805a2d42011-09-25 08:25:12 +00003310 break;
3311 }
anthonyafa3dfc2012-03-03 11:31:30 +00003312 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003313 {
anthonyfd706f92012-01-19 04:22:02 +00003314 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003315 if ((flags & SigmaValue) == 0)
3316 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003317 new_image=SketchImage(_image,geometry_info.rho,
3318 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003319 break;
3320 }
anthonyafa3dfc2012-03-03 11:31:30 +00003321 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003322 {
anthony92c93bd2012-03-19 14:02:47 +00003323 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3324 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003325 break;
3326 }
anthonyafa3dfc2012-03-03 11:31:30 +00003327 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003328 {
3329 SparseColorMethod
3330 method;
3331
3332 char
3333 *arguments;
3334
anthony805a2d42011-09-25 08:25:12 +00003335 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003336 MagickSparseColorOptions,MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003337 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003338 if (arguments == (char *) NULL)
3339 break;
anthony92c93bd2012-03-19 14:02:47 +00003340 new_image=SparseColorOption(_image,method,arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003341 arguments=DestroyString(arguments);
3342 break;
3343 }
anthonyafa3dfc2012-03-03 11:31:30 +00003344 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003345 {
anthony92c93bd2012-03-19 14:02:47 +00003346 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3347 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003348 break;
3349 }
anthonyafa3dfc2012-03-03 11:31:30 +00003350 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003351 {
anthonyfd706f92012-01-19 04:22:02 +00003352 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003353 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3354 _exception);
anthony805a2d42011-09-25 08:25:12 +00003355 break;
3356 }
anthonyafa3dfc2012-03-03 11:31:30 +00003357 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003358 {
3359 StatisticType
3360 type;
3361
anthony805a2d42011-09-25 08:25:12 +00003362 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003363 MagickFalse,arg1);
3364 (void) ParseGeometry(arg2,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003365 new_image=StatisticImage(_image,type,(size_t) geometry_info.rho,
3366 (size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003367 break;
3368 }
anthonyafa3dfc2012-03-03 11:31:30 +00003369 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003370 {
anthony92c93bd2012-03-19 14:02:47 +00003371 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003372 break;
3373 }
anthonyafa3dfc2012-03-03 11:31:30 +00003374 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003375 {
anthonyfd706f92012-01-19 04:22:02 +00003376 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003377 new_image=SwirlImage(_image,geometry_info.rho,
3378 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003379 break;
3380 }
anthonyebb73a22012-03-22 14:25:52 +00003381 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003382 }
3383 case 't':
3384 {
anthonyafa3dfc2012-03-03 11:31:30 +00003385 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003386 {
3387 double
3388 threshold;
3389
anthonyafa3dfc2012-03-03 11:31:30 +00003390 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003391 threshold=(double) QuantumRange/2;
3392 else
anthonyfd706f92012-01-19 04:22:02 +00003393 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003394 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003395 break;
3396 }
anthonyafa3dfc2012-03-03 11:31:30 +00003397 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003398 {
anthony92c93bd2012-03-19 14:02:47 +00003399 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3400 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3401 _exception);
anthony805a2d42011-09-25 08:25:12 +00003402 break;
3403 }
anthonyafa3dfc2012-03-03 11:31:30 +00003404 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003405 {
anthony92c93bd2012-03-19 14:02:47 +00003406 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003407 break;
3408 }
anthonyafa3dfc2012-03-03 11:31:30 +00003409 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003410 {
anthonya3ef4ed2012-03-17 06:52:53 +00003411 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony92c93bd2012-03-19 14:02:47 +00003412 new_image=AffineTransformImage(_image,&_draw_info->affine,
3413 _exception);
anthony805a2d42011-09-25 08:25:12 +00003414 break;
3415 }
anthonyafa3dfc2012-03-03 11:31:30 +00003416 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003417 {
3418 PixelInfo
3419 target;
3420
anthony92c93bd2012-03-19 14:02:47 +00003421 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3422 (void) TransparentPaintImage(_image,&target,(Quantum)
3423 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003424 break;
3425 }
anthonyafa3dfc2012-03-03 11:31:30 +00003426 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003427 {
anthony92c93bd2012-03-19 14:02:47 +00003428 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003429 break;
3430 }
anthonyafa3dfc2012-03-03 11:31:30 +00003431 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003432 {
anthony92c93bd2012-03-19 14:02:47 +00003433 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003434 break;
3435 }
anthonyafa3dfc2012-03-03 11:31:30 +00003436 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003437 {
anthony92c93bd2012-03-19 14:02:47 +00003438 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003439 break;
3440 }
anthonyafa3dfc2012-03-03 11:31:30 +00003441 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003442 {
anthonyab3a50c2011-10-27 11:48:57 +00003443 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003444 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003445 break;
3446 }
anthonyebb73a22012-03-22 14:25:52 +00003447 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003448 }
3449 case 'u':
3450 {
anthonyafa3dfc2012-03-03 11:31:30 +00003451 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003452 {
anthony31f1bf72012-01-30 12:37:22 +00003453 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthony24aa8822012-03-11 00:56:06 +00003454 /* FUTURE: This option is not documented!!!!! */
anthonyafa3dfc2012-03-03 11:31:30 +00003455 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003456 {
anthony92c93bd2012-03-19 14:02:47 +00003457 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003458 break;
3459 }
anthony92c93bd2012-03-19 14:02:47 +00003460 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3461 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003462 break;
3463 }
anthonyafa3dfc2012-03-03 11:31:30 +00003464 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003465 {
anthony92c93bd2012-03-19 14:02:47 +00003466 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003467 break;
3468 }
anthonyafa3dfc2012-03-03 11:31:30 +00003469 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003470 {
anthonyfd706f92012-01-19 04:22:02 +00003471 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003472 if ((flags & SigmaValue) == 0)
3473 geometry_info.sigma=1.0;
3474 if ((flags & XiValue) == 0)
3475 geometry_info.xi=1.0;
3476 if ((flags & PsiValue) == 0)
3477 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003478 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3479 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003480 break;
3481 }
anthonyebb73a22012-03-22 14:25:52 +00003482 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003483 }
3484 case 'v':
3485 {
anthonyafa3dfc2012-03-03 11:31:30 +00003486 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003487 {
anthonyafa3dfc2012-03-03 11:31:30 +00003488 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003489 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003490 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003491 */
anthony92c93bd2012-03-19 14:02:47 +00003492 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003493 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003494 break;
3495 }
anthonyafa3dfc2012-03-03 11:31:30 +00003496 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003497 {
anthonyfd706f92012-01-19 04:22:02 +00003498 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003499 if ((flags & SigmaValue) == 0)
3500 geometry_info.sigma=1.0;
3501 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003502 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003503 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003504 geometry_info.psi=0.1*_image->rows;
3505 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3506 _image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3507 (ssize_t) ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003508 break;
3509 }
anthonyebb73a22012-03-22 14:25:52 +00003510 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003511 }
3512 case 'w':
3513 {
anthonyafa3dfc2012-03-03 11:31:30 +00003514 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003515 {
anthonyfd706f92012-01-19 04:22:02 +00003516 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003517 if ((flags & SigmaValue) == 0)
3518 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003519 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3520 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003521 break;
3522 }
anthonyafa3dfc2012-03-03 11:31:30 +00003523 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003524 {
anthony92c93bd2012-03-19 14:02:47 +00003525 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003526 break;
3527 }
anthonyebb73a22012-03-22 14:25:52 +00003528 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003529 }
3530 default:
anthonyebb73a22012-03-22 14:25:52 +00003531 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003532 }
3533 /*
3534 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003535 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003536 */
3537 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003538 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003539
anthony31f1bf72012-01-30 12:37:22 +00003540 return;
anthony92c93bd2012-03-19 14:02:47 +00003541#undef _image_info
3542#undef _draw_info
3543#undef _quantize_info
3544#undef _image
3545#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003546#undef IfNormalOp
3547#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003548#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003549#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003550}
anthonyfd706f92012-01-19 04:22:02 +00003551
anthony43f425d2012-02-26 12:58:58 +00003552WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003553 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003554{
3555 size_t
anthony43f425d2012-02-26 12:58:58 +00003556 n,
anthony31f1bf72012-01-30 12:37:22 +00003557 i;
3558
anthony43f425d2012-02-26 12:58:58 +00003559 assert(cli_wand != (MagickCLI *) NULL);
3560 assert(cli_wand->signature == WandSignature);
3561 assert(cli_wand->wand.signature == WandSignature);
3562 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3563 if (cli_wand->wand.debug != MagickFalse)
3564 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003565
anthonyafa3dfc2012-03-03 11:31:30 +00003566#if !USE_WAND_METHODS
3567 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003568 i=0;
anthony43f425d2012-02-26 12:58:58 +00003569 n=GetImageListLength(cli_wand->wand.images);
3570 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003571 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003572 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003573 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003574 if ( cli_wand->wand.images->next == (Image *) NULL )
3575 break;
3576 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003577 }
anthony43f425d2012-02-26 12:58:58 +00003578 assert( i == n );
3579 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003580#else
3581 MagickResetIterator(&cli_wand->wand);
3582 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3583 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3584 MagickResetIterator(&cli_wand->wand);
3585#endif
anthony31f1bf72012-01-30 12:37:22 +00003586 return;
anthony805a2d42011-09-25 08:25:12 +00003587}
3588
3589/*
3590%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3591% %
3592% %
3593% %
anthony43f425d2012-02-26 12:58:58 +00003594+ 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 +00003595% %
3596% %
3597% %
3598%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3599%
anthony43f425d2012-02-26 12:58:58 +00003600% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003601% entire image list as a whole. The result is often a complete replacment
3602% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003603%
3604% The format of the MogrifyImage method is:
3605%
anthony43f425d2012-02-26 12:58:58 +00003606% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003607% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003608%
3609% A description of each parameter follows:
3610%
anthony43f425d2012-02-26 12:58:58 +00003611% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003612%
anthony36a8c2c2012-02-10 00:08:44 +00003613% o option: The option string for the operation
3614%
anthony31f1bf72012-01-30 12:37:22 +00003615% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003616%
anthonyfe1aa782012-03-24 13:43:04 +00003617% NOTE: only "limit" uses two arguments.
anthony8b10b462012-02-08 12:32:44 +00003618%
3619% Example usage...
3620%
anthonyafa3dfc2012-03-03 11:31:30 +00003621% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3622% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003623%
anthony24aa8822012-03-11 00:56:06 +00003624% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003625%
anthony43f425d2012-02-26 12:58:58 +00003626% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003627% argc,argv
3628% i=index in argv
3629%
anthony2052d272012-02-28 12:48:29 +00003630% option_info = GetCommandOptionInfo(argv[i]);
3631% count=option_info->type;
3632% option_type=option_info->flags;
3633%
3634% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003635% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003636% count>=1 ? argv[i+1] : (char *)NULL,
3637% count>=2 ? argv[i+2] : (char *)NULL );
3638% i += count+1;
3639%
anthony805a2d42011-09-25 08:25:12 +00003640*/
anthony43f425d2012-02-26 12:58:58 +00003641WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003642 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003643{
anthony2a0ec8c2012-03-24 04:35:56 +00003644 ssize_t
3645 parse;
3646
anthony31f1bf72012-01-30 12:37:22 +00003647 Image
3648 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003649
anthony92c93bd2012-03-19 14:02:47 +00003650#define _image_info (cli_wand->wand.image_info)
3651#define _images (cli_wand->wand.images)
3652#define _exception (cli_wand->wand.exception)
3653#define _draw_info (cli_wand->draw_info)
3654#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003655#define IfNormalOp (*option=='-')
3656#define IfPlusOp (*option!='-')
3657#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003658
anthony43f425d2012-02-26 12:58:58 +00003659 assert(cli_wand != (MagickCLI *) NULL);
3660 assert(cli_wand->signature == WandSignature);
3661 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003662 assert(_images != (Image *) NULL); /* _images must be present */
anthony43f425d2012-02-26 12:58:58 +00003663 if (cli_wand->wand.debug != MagickFalse)
3664 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003665
anthony92c93bd2012-03-19 14:02:47 +00003666 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003667
3668 new_images=NewImageList();
3669
anthonyafa3dfc2012-03-03 11:31:30 +00003670 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003671 {
3672 case 'a':
3673 {
anthonyafa3dfc2012-03-03 11:31:30 +00003674 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003675 {
anthony92c93bd2012-03-19 14:02:47 +00003676 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003677 break;
3678 }
anthonyafa3dfc2012-03-03 11:31:30 +00003679 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003680 {
anthony31f1bf72012-01-30 12:37:22 +00003681 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003682 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003683 break;
3684 }
anthonyebb73a22012-03-22 14:25:52 +00003685 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003686 }
3687 case 'c':
3688 {
cristy5f257b22012-03-07 00:27:29 +00003689 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003690 {
anthony92c93bd2012-03-19 14:02:47 +00003691 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003692 break;
3693 }
anthonyafa3dfc2012-03-03 11:31:30 +00003694 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003695 {
anthony805a2d42011-09-25 08:25:12 +00003696 Image
anthony31f1bf72012-01-30 12:37:22 +00003697 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003698
anthonyafa3dfc2012-03-03 11:31:30 +00003699 /* FUTURE - make this a compose option, and thus can be used
3700 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003701 _images.
cristy87c02f42012-02-24 00:19:10 +00003702 */
anthony92c93bd2012-03-19 14:02:47 +00003703 new_images=RemoveFirstImageFromList(&_images);
3704 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003705 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003706 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003707 break;
anthony92c93bd2012-03-19 14:02:47 +00003708 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003709 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003710 break;
3711 }
anthonyafa3dfc2012-03-03 11:31:30 +00003712 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003713 {
anthony92c93bd2012-03-19 14:02:47 +00003714 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003715 break;
3716 }
anthonyafa3dfc2012-03-03 11:31:30 +00003717 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003718 {
anthony43f425d2012-02-26 12:58:58 +00003719 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003720 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003721 break;
3722 }
anthonyafa3dfc2012-03-03 11:31:30 +00003723 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003724 {
3725 Image
3726 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003727 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003728
3729 RectangleInfo
3730 geometry;
3731
anthony31f1bf72012-01-30 12:37:22 +00003732 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003733 compose;
3734
3735 const char*
3736 value;
3737
anthony92c93bd2012-03-19 14:02:47 +00003738 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003739 if (value != (const char *) NULL)
3740 compose=(CompositeOperator) ParseCommandOption(
3741 MagickComposeOptions,MagickFalse,value);
3742 else
anthony31f1bf72012-01-30 12:37:22 +00003743 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003744
anthony92c93bd2012-03-19 14:02:47 +00003745 new_images=RemoveFirstImageFromList(&_images);
3746 source_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003747 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003748 if (source_image == (Image *) NULL)
3749 break;
anthonye8f56492012-02-12 12:39:02 +00003750
anthony31f1bf72012-01-30 12:37:22 +00003751 /* FUTURE - this should not be here! - should be part of -geometry */
3752 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003753 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003754
anthony31f1bf72012-01-30 12:37:22 +00003755 SetGeometry(source_image,&geometry);
3756 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3757 GravityAdjustGeometry(new_images->columns,new_images->rows,
3758 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003759
anthony92c93bd2012-03-19 14:02:47 +00003760 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003761 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003762 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003763 if ((compose == DisplaceCompositeOp) ||
3764 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003765 { /* Merge Y displacement into X displace/distort map. */
3766 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony92c93bd2012-03-19 14:02:47 +00003767 mask_image,0,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003768 mask_image=DestroyImage(mask_image);
3769 }
3770 else
3771 {
3772 /*
3773 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003774 */
anthony92c93bd2012-03-19 14:02:47 +00003775 (void) NegateImage(mask_image,MagickFalse,_exception);
3776 (void) SetImageMask(new_images,mask_image,_exception);
cristy1539afd2012-01-30 01:32:59 +00003777 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003778 }
3779 }
anthony31f1bf72012-01-30 12:37:22 +00003780 (void) CompositeImage(new_images,compose,source_image,geometry.x,
anthony92c93bd2012-03-19 14:02:47 +00003781 geometry.y,_exception);
3782 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003783 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003784 break;
3785 }
anthonyebb73a22012-03-22 14:25:52 +00003786 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003787 }
3788 case 'd':
3789 {
anthonyafa3dfc2012-03-03 11:31:30 +00003790 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003791 {
anthony31f1bf72012-01-30 12:37:22 +00003792 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003793 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003794 break;
3795 }
anthonyafa3dfc2012-03-03 11:31:30 +00003796 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003797 {
anthonyafa3dfc2012-03-03 11:31:30 +00003798 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003799 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003800 else
anthony92c93bd2012-03-19 14:02:47 +00003801 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003802 break;
3803 }
anthonyafa3dfc2012-03-03 11:31:30 +00003804 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003805 {
anthonyafa3dfc2012-03-03 11:31:30 +00003806 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003807 {
3808 const char
3809 *p;
3810
3811 size_t
3812 number_duplicates;
3813
anthonyebb73a22012-03-22 14:25:52 +00003814 if (IsGeometry(arg1) == MagickFalse)
3815 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3816 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003817 number_duplicates=(size_t) StringToLong(arg1);
3818 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003819 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003820 new_images=DuplicateImages(_images,number_duplicates,"-1",
3821 _exception);
anthony805a2d42011-09-25 08:25:12 +00003822 else
anthony92c93bd2012-03-19 14:02:47 +00003823 new_images=DuplicateImages(_images,number_duplicates,p,
3824 _exception);
anthony805a2d42011-09-25 08:25:12 +00003825 }
anthonyafa3dfc2012-03-03 11:31:30 +00003826 else
anthony92c93bd2012-03-19 14:02:47 +00003827 new_images=DuplicateImages(_images,1,"-1",_exception);
3828 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003829 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003830 break;
3831 }
anthonyebb73a22012-03-22 14:25:52 +00003832 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003833 }
3834 case 'e':
3835 {
anthonyafa3dfc2012-03-03 11:31:30 +00003836 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003837 {
anthony2a0ec8c2012-03-24 04:35:56 +00003838 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3839 if ( parse < 0 )
3840 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3841 option,arg1);
3842 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3843 _exception);
anthony805a2d42011-09-25 08:25:12 +00003844 break;
3845 }
anthonyebb73a22012-03-22 14:25:52 +00003846 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003847 }
3848 case 'f':
3849 {
anthonyafa3dfc2012-03-03 11:31:30 +00003850 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003851 {
anthony92c93bd2012-03-19 14:02:47 +00003852 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003853 break;
3854 }
anthonyafa3dfc2012-03-03 11:31:30 +00003855 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003856 {
anthony319dac62012-03-06 04:12:44 +00003857 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003858 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003859 break;
3860 }
anthonyafa3dfc2012-03-03 11:31:30 +00003861 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003862 {
anthony92c93bd2012-03-19 14:02:47 +00003863 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003864 break;
3865 }
anthonyebb73a22012-03-22 14:25:52 +00003866 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003867 }
3868 case 'h':
3869 {
anthonyafa3dfc2012-03-03 11:31:30 +00003870 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003871 {
anthony31f1bf72012-01-30 12:37:22 +00003872 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003873 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003874 */
anthony805a2d42011-09-25 08:25:12 +00003875 Image
anthony31f1bf72012-01-30 12:37:22 +00003876 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003877
anthony92c93bd2012-03-19 14:02:47 +00003878 new_images=RemoveFirstImageFromList(&_images);
3879 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003880 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003881 break;
anthony92c93bd2012-03-19 14:02:47 +00003882 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003883 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003884 break;
3885 }
anthonyebb73a22012-03-22 14:25:52 +00003886 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003887 }
3888 case 'i':
3889 {
anthonyafa3dfc2012-03-03 11:31:30 +00003890 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003891 {
3892 Image
anthony805a2d42011-09-25 08:25:12 +00003893 *magnitude_image,
3894 *phase_image;
3895
anthony92c93bd2012-03-19 14:02:47 +00003896 magnitude_image=RemoveFirstImageFromList(&_images);
3897 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003898 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003899 if (phase_image == (Image *) NULL)
3900 break;
3901 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003902 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003903 magnitude_image=DestroyImage(magnitude_image);
3904 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003905 break;
3906 }
anthonyafa3dfc2012-03-03 11:31:30 +00003907 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003908 {
3909 Image
anthony31f1bf72012-01-30 12:37:22 +00003910 *insert_image,
3911 *index_image;
3912
3913 ssize_t
3914 index;
anthony805a2d42011-09-25 08:25:12 +00003915
anthonyfe1aa782012-03-24 13:43:04 +00003916 if (IfNormalOp && IsGeometry(arg1) == MagickFalse)
3917 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00003918 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003919 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003920 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003921 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003922 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003923 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003924 PrependImageToList(&_images,insert_image);
3925 else if (index == (ssize_t) GetImageListLength(_images))
3926 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003927 else
anthony43f425d2012-02-26 12:58:58 +00003928 {
anthony92c93bd2012-03-19 14:02:47 +00003929 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003930 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00003931 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00003932 InsertImageInList(&index_image,insert_image);
3933 }
anthony92c93bd2012-03-19 14:02:47 +00003934 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003935 break;
3936 }
anthonyebb73a22012-03-22 14:25:52 +00003937 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003938 }
3939 case 'l':
3940 {
anthonyafa3dfc2012-03-03 11:31:30 +00003941 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003942 {
anthonyfe1aa782012-03-24 13:43:04 +00003943 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3944 if ( parse < 0 )
3945 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3946 option,arg1);
3947 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00003948 {
3949 case CoalesceLayer:
3950 {
anthony92c93bd2012-03-19 14:02:47 +00003951 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003952 break;
3953 }
3954 case CompareAnyLayer:
3955 case CompareClearLayer:
3956 case CompareOverlayLayer:
3957 default:
3958 {
anthonyfe1aa782012-03-24 13:43:04 +00003959 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
3960 _exception);
anthony805a2d42011-09-25 08:25:12 +00003961 break;
3962 }
3963 case MergeLayer:
3964 case FlattenLayer:
3965 case MosaicLayer:
3966 case TrimBoundsLayer:
3967 {
anthonyfe1aa782012-03-24 13:43:04 +00003968 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
3969 _exception);
anthony805a2d42011-09-25 08:25:12 +00003970 break;
3971 }
3972 case DisposeLayer:
3973 {
anthony92c93bd2012-03-19 14:02:47 +00003974 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003975 break;
3976 }
3977 case OptimizeImageLayer:
3978 {
anthony92c93bd2012-03-19 14:02:47 +00003979 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003980 break;
3981 }
3982 case OptimizePlusLayer:
3983 {
anthony92c93bd2012-03-19 14:02:47 +00003984 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003985 break;
3986 }
3987 case OptimizeTransLayer:
3988 {
anthony92c93bd2012-03-19 14:02:47 +00003989 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003990 break;
3991 }
3992 case RemoveDupsLayer:
3993 {
anthony92c93bd2012-03-19 14:02:47 +00003994 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003995 break;
3996 }
3997 case RemoveZeroLayer:
3998 {
anthony92c93bd2012-03-19 14:02:47 +00003999 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004000 break;
4001 }
4002 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004003 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004004 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004005 if (new_images == (Image *) NULL)
4006 break;
anthony92c93bd2012-03-19 14:02:47 +00004007 _images=DestroyImageList(_images);
4008 _images=OptimizeImageLayers(new_images,_exception);
4009 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004010 break;
4011 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004012 OptimizeImageTransparency(_images,_exception);
4013 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4014 _exception);
anthony805a2d42011-09-25 08:25:12 +00004015 break;
4016 }
4017 case CompositeLayer:
4018 {
anthony805a2d42011-09-25 08:25:12 +00004019 Image
4020 *source;
4021
4022 RectangleInfo
4023 geometry;
4024
anthony31f1bf72012-01-30 12:37:22 +00004025 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004026 compose;
4027
4028 const char*
4029 value;
4030
anthony92c93bd2012-03-19 14:02:47 +00004031 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004032 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004033 if (value != (const char *) NULL)
4034 compose=(CompositeOperator) ParseCommandOption(
4035 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004036
anthony31f1bf72012-01-30 12:37:22 +00004037 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004038 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004039 while (source != (Image *) NULL)
4040 {
4041 source=GetNextImageInList(source);
4042 if ((source != (Image *) NULL) &&
4043 (LocaleCompare(source->magick,"NULL") == 0))
4044 break;
4045 }
4046 if (source != (Image *) NULL)
4047 {
4048 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4049 (GetNextImageInList(source) == (Image *) NULL))
4050 source=(Image *) NULL;
4051 else
anthony31f1bf72012-01-30 12:37:22 +00004052 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004053 source=SplitImageList(source->previous);
4054 DeleteImageFromList(&source);
4055 }
4056 }
4057 if (source == (Image *) NULL)
4058 {
anthony92c93bd2012-03-19 14:02:47 +00004059 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004060 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004061 break;
4062 }
anthony31f1bf72012-01-30 12:37:22 +00004063 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004064 SetGeometry(_images,&geometry);
4065 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004066 geometry.width=source->page.width != 0 ?
4067 source->page.width : source->columns;
4068 geometry.height=source->page.height != 0 ?
4069 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004070 GravityAdjustGeometry(_images->page.width != 0 ?
4071 _images->page.width : _images->columns,
4072 _images->page.height != 0 ? _images->page.height :
4073 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004074
anthony31f1bf72012-01-30 12:37:22 +00004075 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004076 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4077 _exception);
anthony805a2d42011-09-25 08:25:12 +00004078 source=DestroyImageList(source);
4079 break;
4080 }
4081 }
anthony805a2d42011-09-25 08:25:12 +00004082 break;
4083 }
anthonyafa3dfc2012-03-03 11:31:30 +00004084 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00004085 {
4086 MagickSizeType
4087 limit;
4088
anthony72feaa62012-01-17 06:46:23 +00004089 limit=MagickResourceInfinity;
anthonyfe1aa782012-03-24 13:43:04 +00004090 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4091 if ( parse < 0 )
4092 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4093 option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004094 if (LocaleCompare("unlimited",arg2) != 0)
4095 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthonyfe1aa782012-03-24 13:43:04 +00004096 (void) SetMagickResourceLimit((ResourceType)parse,limit);
anthony72feaa62012-01-17 06:46:23 +00004097 break;
4098 }
anthonyebb73a22012-03-22 14:25:52 +00004099 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004100 }
4101 case 'm':
4102 {
anthonyafa3dfc2012-03-03 11:31:30 +00004103 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004104 {
anthony31f1bf72012-01-30 12:37:22 +00004105 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004106 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004107 break;
4108 }
anthonyafa3dfc2012-03-03 11:31:30 +00004109 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004110 {
4111 Image
4112 *morph_image;
4113
anthony92c93bd2012-03-19 14:02:47 +00004114 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4115 _exception);
anthony805a2d42011-09-25 08:25:12 +00004116 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004117 break;
anthony92c93bd2012-03-19 14:02:47 +00004118 _images=DestroyImageList(_images);
4119 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004120 break;
4121 }
anthonyafa3dfc2012-03-03 11:31:30 +00004122 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004123 {
anthony319dac62012-03-06 04:12:44 +00004124 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00004125 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004126 break;
4127 }
anthonyebb73a22012-03-22 14:25:52 +00004128 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004129 }
4130 case 'p':
4131 {
anthonyafa3dfc2012-03-03 11:31:30 +00004132 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004133 {
4134 char
4135 *string;
4136
anthony92c93bd2012-03-19 14:02:47 +00004137 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004138 if (string == (char *) NULL)
4139 break;
4140 (void) FormatLocaleFile(stdout,"%s",string);
4141 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004142 break;
anthony805a2d42011-09-25 08:25:12 +00004143 }
anthonyafa3dfc2012-03-03 11:31:30 +00004144 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004145 {
4146 char
4147 **arguments;
4148
4149 int
4150 j,
4151 number_arguments;
4152
anthony31f1bf72012-01-30 12:37:22 +00004153 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004154 if (arguments == (char **) NULL)
4155 break;
anthony31f1bf72012-01-30 12:37:22 +00004156 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004157 {
4158 char
4159 breaker,
4160 quote,
4161 *token;
4162
4163 const char
4164 *arguments;
4165
4166 int
4167 next,
4168 status;
4169
4170 size_t
4171 length;
4172
4173 TokenInfo
4174 *token_info;
4175
4176 /*
anthony24aa8822012-03-11 00:56:06 +00004177 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004178 */
anthony31f1bf72012-01-30 12:37:22 +00004179 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004180 token=(char *) NULL;
4181 if (~length >= (MaxTextExtent-1))
4182 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4183 sizeof(*token));
4184 if (token == (char *) NULL)
4185 break;
4186 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004187 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004188 token_info=AcquireTokenInfo();
4189 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4190 "\"",'\0',&breaker,&next,&quote);
4191 token_info=DestroyTokenInfo(token_info);
4192 if (status == 0)
4193 {
4194 const char
4195 *argv;
4196
4197 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004198 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4199 _exception);
anthony805a2d42011-09-25 08:25:12 +00004200 }
4201 token=DestroyString(token);
4202 break;
4203 }
4204 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004205 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4206 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004207 for (j=0; j < number_arguments; j++)
4208 arguments[j]=DestroyString(arguments[j]);
4209 arguments=(char **) RelinquishMagickMemory(arguments);
4210 break;
4211 }
anthonyebb73a22012-03-22 14:25:52 +00004212 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004213 }
4214 case 'r':
4215 {
anthonyafa3dfc2012-03-03 11:31:30 +00004216 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004217 {
anthony92c93bd2012-03-19 14:02:47 +00004218 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4219 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004220 break;
4221 }
anthonyafa3dfc2012-03-03 11:31:30 +00004222 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004223 {
anthony92c93bd2012-03-19 14:02:47 +00004224 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004225 break;
4226 }
anthonyebb73a22012-03-22 14:25:52 +00004227 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004228 }
4229 case 's':
4230 {
anthonyafa3dfc2012-03-03 11:31:30 +00004231 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004232 {
4233 Image
4234 *smush_image;
4235
4236 ssize_t
4237 offset;
4238
anthony31f1bf72012-01-30 12:37:22 +00004239 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004240 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004241 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004242 break;
anthony92c93bd2012-03-19 14:02:47 +00004243 _images=DestroyImageList(_images);
4244 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004245 break;
4246 }
anthonyafa3dfc2012-03-03 11:31:30 +00004247 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004248 {
4249 Image
4250 *p,
4251 *q,
4252 *swap;
4253
4254 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004255 index,
anthony805a2d42011-09-25 08:25:12 +00004256 swap_index;
4257
anthony31f1bf72012-01-30 12:37:22 +00004258 index=-1;
4259 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004260 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004261 {
4262 GeometryInfo
4263 geometry_info;
4264
4265 MagickStatusType
4266 flags;
4267
4268 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004269 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004270 index=(ssize_t) geometry_info.rho;
4271 if ((flags & SigmaValue) != 0)
4272 swap_index=(ssize_t) geometry_info.sigma;
4273 }
anthony92c93bd2012-03-19 14:02:47 +00004274 p=GetImageFromList(_images,index);
4275 q=GetImageFromList(_images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004276 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4277 {
anthony92c93bd2012-03-19 14:02:47 +00004278 (void) ThrowMagickException(_exception,GetMagickModule(),
4279 OptionError,"NoSuchImage","'%s'",_images->filename);
anthony805a2d42011-09-25 08:25:12 +00004280 break;
4281 }
4282 if (p == q)
4283 break;
anthony92c93bd2012-03-19 14:02:47 +00004284 swap=CloneImage(p,0,0,MagickTrue,_exception);
4285 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
anthony805a2d42011-09-25 08:25:12 +00004286 ReplaceImageInList(&q,swap);
anthony92c93bd2012-03-19 14:02:47 +00004287 _images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004288 break;
4289 }
anthonyebb73a22012-03-22 14:25:52 +00004290 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004291 }
4292 case 'w':
4293 {
anthonyafa3dfc2012-03-03 11:31:30 +00004294 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004295 {
4296 char
4297 key[MaxTextExtent];
4298
4299 Image
4300 *write_images;
4301
4302 ImageInfo
4303 *write_info;
4304
anthony31f1bf72012-01-30 12:37:22 +00004305 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004306 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004307 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004308 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004309 write_images=CloneImageList(_images,_exception);
4310 write_info=CloneImageInfo(_image_info);
4311 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004312 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004313 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004314 write_images=DestroyImageList(write_images);
4315 break;
4316 }
anthonyebb73a22012-03-22 14:25:52 +00004317 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004318 }
4319 default:
anthonyebb73a22012-03-22 14:25:52 +00004320 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004321 }
anthony31f1bf72012-01-30 12:37:22 +00004322 if (new_images == (Image *) NULL)
4323 return;
anthony805a2d42011-09-25 08:25:12 +00004324
anthony92c93bd2012-03-19 14:02:47 +00004325 if (_images != (Image *) NULL)
4326 _images=DestroyImageList(_images);
4327 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004328 return;
4329
anthony92c93bd2012-03-19 14:02:47 +00004330#undef _image_info
4331#undef _images
4332#undef _exception
4333#undef _draw_info
4334#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004335#undef IfNormalOp
4336#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004337#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004338}
anthony43f425d2012-02-26 12:58:58 +00004339
4340/*
4341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4342% %
4343% %
4344% %
4345+ C L I S p e c i a l O p e r a t i o n s %
4346% %
4347% %
4348% %
4349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4350%
4351% CLISpecialOption() Applies operations that may involve empty image lists
4352% and or stacks of image lists or image_info settings.
4353%
anthonyafa3dfc2012-03-03 11:31:30 +00004354% The classic operators of this type is -read, and image stack operators,
4355% which can be applied to empty image lists.
4356%
4357% Note: unlike other Operators, these may involve other special 'option'
4358% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004359%
4360% The format of the CLISpecialOption method is:
4361%
4362% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004363% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004364%
4365% A description of each parameter follows:
4366%
4367% o cli_wand: the main CLI Wand to use.
4368%
4369% o option: The special option (with any switch char) to process
4370%
anthony24aa8822012-03-11 00:56:06 +00004371% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004372%
anthony2052d272012-02-28 12:48:29 +00004373% Example Usage...
4374%
anthonyce8dcb32012-03-21 13:20:31 +00004375% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004376%
anthony24aa8822012-03-11 00:56:06 +00004377% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004378%
4379% cli_wand
4380% argc,argv
4381% i=index in argv
4382%
4383% option_info = GetCommandOptionInfo(argv[i]);
4384% count=option_info->type;
4385% option_type=option_info->flags;
4386%
4387% if ( (option_type & SpecialOptionFlag) != 0 )
4388% CLISpecialOperator(cli_wand,argv[i],
4389% count>=1 ? argv[i+1] : (char *)NULL);
4390% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004391%
4392*/
4393
anthony43f425d2012-02-26 12:58:58 +00004394WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004395 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004396{
anthony92c93bd2012-03-19 14:02:47 +00004397#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004398
4399 assert(cli_wand != (MagickCLI *) NULL);
4400 assert(cli_wand->signature == WandSignature);
4401 assert(cli_wand->wand.signature == WandSignature);
4402 if (cli_wand->wand.debug != MagickFalse)
4403 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4404
anthony24aa8822012-03-11 00:56:06 +00004405 if(cli_wand->wand.images != (Image *)NULL)
4406 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004407 _exception);
anthony24aa8822012-03-11 00:56:06 +00004408
anthonyce8dcb32012-03-21 13:20:31 +00004409 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
4410 /* image-setting stack linkage */
4411 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4412 *option == '-' ? "true" : (char *) NULL);
4413 return;
4414 }
4415 if (LocaleCompare("(",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004416 /* stack 'push' images */
4417 Stack
4418 *node;
4419
4420 size_t
4421 size;
4422
anthony43f425d2012-02-26 12:58:58 +00004423 size=0;
4424 node=cli_wand->image_list_stack;
4425 for ( ; node != (Stack *)NULL; node=node->next)
4426 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004427 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004428 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004429 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4430 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004431 CLIWandExceptionReturn(ResourceLimitFatalError,
4432 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004433 node->data = (void *)cli_wand->wand.images;
4434 cli_wand->wand.images = NewImageList();
4435 node->next = cli_wand->image_list_stack;
4436 cli_wand->image_list_stack = node;
4437
4438 /* handle respect-parenthesis */
anthonyce8dcb32012-03-21 13:20:31 +00004439 if ( IsMagickTrue(GetImageOption(cli_wand->wand.image_info,
4440 "respect-parenthesis")) != MagickFalse )
anthony4d4f2c72012-03-22 03:22:03 +00004441 option="{"; /* push image settings too */
anthony43f425d2012-02-26 12:58:58 +00004442 else
4443 return;
4444 }
anthonyce8dcb32012-03-21 13:20:31 +00004445 if (LocaleCompare("{",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004446 /* stack 'push' of image_info settings */
4447 Stack
4448 *node;
4449
4450 size_t
4451 size;
4452
4453 size=0;
4454 node=cli_wand->image_info_stack;
4455 for ( ; node != (Stack *)NULL; node=node->next)
4456 size++;
anthony92c93bd2012-03-19 14:02:47 +00004457 if ( size >= MAX_STACK_DEPTH )
anthony4d4f2c72012-03-22 03:22:03 +00004458 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004459 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004460 if (node == (Stack *) NULL)
4461 CLIWandExceptionReturn(ResourceLimitFatalError,
4462 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004463
4464 node->data = (void *)cli_wand->wand.image_info;
4465 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004466 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
anthony92c93bd2012-03-19 14:02:47 +00004467 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4468 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004469 cli_wand->wand.image_info = (ImageInfo *)node->data;
4470 node = (Stack *)RelinquishMagickMemory(node);
4471 return;
4472 }
anthony43f425d2012-02-26 12:58:58 +00004473
4474 node->next = cli_wand->image_info_stack;
4475 cli_wand->image_info_stack = node;
4476
4477 return;
4478 }
anthonyce8dcb32012-03-21 13:20:31 +00004479 if (LocaleCompare(")",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004480 /* pop images from stack */
4481 Stack
4482 *node;
4483
anthony43f425d2012-02-26 12:58:58 +00004484 node = (void *)cli_wand->image_list_stack;
4485 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004486 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004487 cli_wand->image_list_stack = node->next;
4488
4489 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4490 cli_wand->wand.images= (Image *)node->data;
4491 node = (Stack *)RelinquishMagickMemory(node);
4492
anthony4d4f2c72012-03-22 03:22:03 +00004493 /* handle respect-parenthesis - of the previous 'pushed' settings */
anthony43f425d2012-02-26 12:58:58 +00004494 node = cli_wand->image_info_stack;
4495 if ( node != (Stack *)NULL)
4496 {
anthonyce8dcb32012-03-21 13:20:31 +00004497 if (IsMagickTrue(GetImageOption((ImageInfo *)node->data,
4498 "respect-parenthesis")) != MagickFalse )
anthony4d4f2c72012-03-22 03:22:03 +00004499 option="}"; /* pop image settings too */
anthony43f425d2012-02-26 12:58:58 +00004500 else
4501 return;
4502 }
4503 else
4504 return;
4505 }
anthonyce8dcb32012-03-21 13:20:31 +00004506 if (LocaleCompare("}",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004507 /* pop image_info settings from stack */
4508 Stack
4509 *node;
4510
4511 node = (void *)cli_wand->image_info_stack;
4512 if ( node == (Stack *)NULL)
anthony4d4f2c72012-03-22 03:22:03 +00004513 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
anthony43f425d2012-02-26 12:58:58 +00004514 cli_wand->image_info_stack = node->next;
4515
4516 (void) DestroyImageInfo(cli_wand->wand.image_info);
4517 cli_wand->wand.image_info = (ImageInfo *)node->data;
4518 node = (Stack *)RelinquishMagickMemory(node);
4519
4520 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4521 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4522 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4523
4524 return;
4525 }
anthonyce8dcb32012-03-21 13:20:31 +00004526 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004527 Image
4528 *new_images;
4529
4530 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004531 arg1="-1";
4532 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004533 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004534 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004535 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004536 new_images = (Image *)cli_wand->image_list_stack->data;
4537 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004538 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4539 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004540 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004541 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004542 AppendImageToList(&cli_wand->wand.images,new_images);
4543 return;
4544 }
anthony319dac62012-03-06 04:12:44 +00004545 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthonyce8dcb32012-03-21 13:20:31 +00004546 ( LocaleCompare("--",option) == 0 ) ) {
anthonyafa3dfc2012-03-03 11:31:30 +00004547#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004548 Image *
4549 new_images;
4550
anthony43f425d2012-02-26 12:58:58 +00004551 if (cli_wand->wand.image_info->ping != MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004552 new_images=PingImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004553 else
anthony92c93bd2012-03-19 14:02:47 +00004554 new_images=ReadImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004555 AppendImageToList(&cli_wand->wand.images, new_images);
4556#else
4557 /* read images using MagickWand method - no ping */
4558 /* This is not working! - it locks up in a CPU loop! */
4559 MagickSetLastIterator(&cli_wand->wand);
anthony24aa8822012-03-11 00:56:06 +00004560 MagickReadImage(&cli_wand->wand,arg1);
anthony43f425d2012-02-26 12:58:58 +00004561 MagickSetFirstIterator(&cli_wand->wand);
4562#endif
4563 return;
4564 }
anthonyafa3dfc2012-03-03 11:31:30 +00004565 /* No-op options */
4566 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004567 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004568 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004569 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004570 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004571 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004572 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004573 return;
anthonyce8dcb32012-03-21 13:20:31 +00004574 if (LocaleCompare("list",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004575 /* FUTURE: This should really be built into the MagickCore
4576 It does not actually require any wand or images at all!
4577 */
4578 ssize_t
4579 list;
4580
anthony24aa8822012-03-11 00:56:06 +00004581 list=ParseCommandOption(MagickListOptions,MagickFalse, arg1);
anthonyfe1aa782012-03-24 13:43:04 +00004582 if ( list < 0 ) {
4583 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4584 return;
4585 }
anthony43f425d2012-02-26 12:58:58 +00004586 switch (list)
4587 {
4588 case MagickCoderOptions:
4589 {
anthony92c93bd2012-03-19 14:02:47 +00004590 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004591 break;
4592 }
4593 case MagickColorOptions:
4594 {
anthony92c93bd2012-03-19 14:02:47 +00004595 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004596 break;
4597 }
4598 case MagickConfigureOptions:
4599 {
anthony92c93bd2012-03-19 14:02:47 +00004600 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004601 break;
4602 }
4603 case MagickDelegateOptions:
4604 {
anthony92c93bd2012-03-19 14:02:47 +00004605 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004606 break;
4607 }
4608 case MagickFontOptions:
4609 {
anthony92c93bd2012-03-19 14:02:47 +00004610 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004611 break;
4612 }
4613 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004614 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004615 break;
4616 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004617 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004618 break;
4619 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004620 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004621 break;
4622 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004623 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004624 break;
4625 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004626 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004627 break;
4628 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004629 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004630 break;
4631 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004632 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004633 break;
4634 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004635 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004636 break;
4637 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004638 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004639 break;
4640 default:
4641 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004642 _exception);
anthony43f425d2012-02-26 12:58:58 +00004643 break;
4644 }
4645 return;
4646 }
4647
4648#if 0
4649 // adjust stack handling
4650 // Other 'special' options this should handle
4651 // "region" "list" "version"
4652 // It does not do "exit" however as due to its side-effect requirements
4653#endif
4654#if 0
4655 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004656#endif
anthonyebb73a22012-03-22 14:25:52 +00004657 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004658
anthony92c93bd2012-03-19 14:02:47 +00004659#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004660}